ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
163
services/mirrored-image/controller/registry_test.go
Normal file
163
services/mirrored-image/controller/registry_test.go
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const childDigest = "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
|
||||
func TestPhysicalPresence(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, status := range []int{200, 404, 401, 403, 429, 500, 502} {
|
||||
t.Run(fmt.Sprint(status), func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
||||
if request.URL.Path != "/api/v1/repository/candidates/pause/manifest/"+testDigest+"/security" || request.URL.Query().Get("vulnerabilities") != "false" {
|
||||
t.Errorf("unexpected lookup: %s", request.URL)
|
||||
}
|
||||
if request.Header.Get("Authorization") != "Bearer reader-token" {
|
||||
t.Error("lookup did not use reader authority")
|
||||
}
|
||||
response.WriteHeader(status)
|
||||
_, _ = fmt.Fprint(response, `{"status":"queued"}`)
|
||||
}))
|
||||
defer server.Close()
|
||||
api, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
reader := &quayReader{api: api, client: server.Client(), candidates: "reader-token"}
|
||||
present, err := reader.physicallyPresent(context.Background(), "candidates/pause", testDigest)
|
||||
if present != (status == 200) || (err != nil) != (status != 200 && status != 404) {
|
||||
t.Fatalf("HTTP %d: present=%t err=%v", status, present, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuayScanAndExistence(t *testing.T) {
|
||||
t.Parallel()
|
||||
child := fmt.Sprintf(`{"schemaVersion":2,"layers":[{"digest":%q}]}`, testDigest)
|
||||
childDigest := fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(child)))
|
||||
index := fmt.Sprintf(`{"manifests":[{"digest":%q}]}`, childDigest)
|
||||
testDigest := fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(index)))
|
||||
severity := "Low"
|
||||
var server *httptest.Server
|
||||
server = httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
||||
switch {
|
||||
case request.URL.Path == "/v2/candidates/pause/manifests/"+childDigest:
|
||||
_, _ = fmt.Fprint(response, child)
|
||||
case request.URL.Path == "/v2/auth":
|
||||
username, password, found := request.BasicAuth()
|
||||
if !found || username != oauthUser || (password != "candidate-token" && password != "mirror-token") {
|
||||
http.Error(response, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
response.Header().Set("Content-Type", "application/json")
|
||||
if _, err := fmt.Fprintf(response, `{"token":%q}`, password+"-registry"); err != nil {
|
||||
t.Errorf("write token response: %v", err)
|
||||
}
|
||||
case request.URL.Path == "/v2/candidates/pause/manifests/"+testDigest || request.URL.Path == "/v2/mirror/pause/manifests/"+testDigest:
|
||||
expected := "Bearer candidate-token-registry"
|
||||
if strings.Contains(request.URL.Path, "/mirror/") {
|
||||
expected = "Bearer mirror-token-registry"
|
||||
}
|
||||
if request.Header.Get("Authorization") != expected {
|
||||
response.Header().Set("WWW-Authenticate", `Bearer realm="`+server.URL+`/v2/auth",service="fixture",scope="repository:test:pull"`)
|
||||
response.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if strings.Contains(request.URL.Path, "/mirror/") {
|
||||
response.Header().Set("Content-Type", "application/vnd.oci.image.manifest.v1+json")
|
||||
if _, err := fmt.Fprint(response, `{"schemaVersion":2}`); err != nil {
|
||||
t.Errorf("write manifest response: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
response.Header().Set("Content-Type", "application/vnd.oci.image.index.v1+json")
|
||||
if _, err := fmt.Fprintf(response, `{"manifests":[{"digest":%q}]}`, childDigest); err != nil {
|
||||
t.Errorf("write index response: %v", err)
|
||||
}
|
||||
case strings.HasSuffix(request.URL.Path, "/security"):
|
||||
if request.Header.Get("Authorization") != "Bearer candidate-token" || request.URL.Query().Get("vulnerabilities") != "true" {
|
||||
http.Error(response, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
data := inventoryFixture()
|
||||
data.Inventory.Hash = childDigest
|
||||
data.Layer.Name = childDigest
|
||||
(*data.Layer.Features)[0].Vulnerabilities = []vulnerability{{Severity: severity}}
|
||||
if err := json.NewEncoder(response).Encode(securityDoc{Status: "scanned", Data: data}); err != nil {
|
||||
t.Errorf("write scan response: %v", err)
|
||||
}
|
||||
default:
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
api, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
reader := &quayReader{
|
||||
api: api,
|
||||
registry: server.Listener.Addr().String(),
|
||||
client: server.Client(),
|
||||
candidates: "candidate-token",
|
||||
mirror: "mirror-token",
|
||||
}
|
||||
|
||||
phase, err := reader.scan(context.Background(), "candidates/pause", testDigest, "High")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if phase != scanAccepted {
|
||||
t.Fatalf("unexpected accepted phase %q", phase)
|
||||
}
|
||||
severity = "Critical"
|
||||
phase, err = reader.scan(context.Background(), "candidates/pause", testDigest, "High")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if phase != scanRejected {
|
||||
t.Fatalf("unexpected rejected phase %q", phase)
|
||||
}
|
||||
severity = "Unknown"
|
||||
phase, err = reader.scan(context.Background(), "candidates/pause", testDigest, "Critical")
|
||||
if err != nil || phase != scanRejected {
|
||||
t.Fatalf("unknown severity: %s %v", phase, err)
|
||||
}
|
||||
present, err := reader.exists(context.Background(), "mirror/pause", testDigest)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !present {
|
||||
t.Fatal("promoted manifest was not observed")
|
||||
}
|
||||
present, err = reader.exists(context.Background(), "candidates/missing", testDigest)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if present {
|
||||
t.Fatal("missing manifest was observed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSingleManifestScanDigest(t *testing.T) {
|
||||
t.Parallel()
|
||||
digests, err := scanDigests([]byte(`{"schemaVersion":2}`), testDigest)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(digests) != 1 || digests[0] != testDigest {
|
||||
t.Fatalf("unexpected scan digests %#v", digests)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue