github.com/yogeshlonkar/moby@v1.13.2-0.20201203103638-c0b64beaea94/integration-cli/registry.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "os/exec" 9 "path/filepath" 10 11 "github.com/docker/distribution/digest" 12 "github.com/go-check/check" 13 ) 14 15 const ( 16 v2binary = "registry-v2" 17 v2binarySchema1 = "registry-v2-schema1" 18 ) 19 20 type testRegistryV2 struct { 21 cmd *exec.Cmd 22 dir string 23 auth string 24 username string 25 password string 26 email string 27 } 28 29 func newTestRegistryV2(c *check.C, schema1 bool, auth, tokenURL string) (*testRegistryV2, error) { 30 tmp, err := ioutil.TempDir("", "registry-test-") 31 if err != nil { 32 return nil, err 33 } 34 template := `version: 0.1 35 loglevel: debug 36 storage: 37 filesystem: 38 rootdirectory: %s 39 http: 40 addr: %s 41 %s` 42 var ( 43 authTemplate string 44 username string 45 password string 46 email string 47 ) 48 switch auth { 49 case "htpasswd": 50 htpasswdPath := filepath.Join(tmp, "htpasswd") 51 // generated with: htpasswd -Bbn testuser testpassword 52 userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m" 53 username = "testuser" 54 password = "testpassword" 55 email = "test@test.org" 56 if err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644)); err != nil { 57 return nil, err 58 } 59 authTemplate = fmt.Sprintf(`auth: 60 htpasswd: 61 realm: basic-realm 62 path: %s 63 `, htpasswdPath) 64 case "token": 65 authTemplate = fmt.Sprintf(`auth: 66 token: 67 realm: %s 68 service: "registry" 69 issuer: "auth-registry" 70 rootcertbundle: "fixtures/registry/cert.pem" 71 `, tokenURL) 72 } 73 74 confPath := filepath.Join(tmp, "config.yaml") 75 config, err := os.Create(confPath) 76 if err != nil { 77 return nil, err 78 } 79 defer config.Close() 80 81 if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, authTemplate); err != nil { 82 os.RemoveAll(tmp) 83 return nil, err 84 } 85 86 binary := v2binary 87 if schema1 { 88 binary = v2binarySchema1 89 } 90 cmd := exec.Command(binary, confPath) 91 if err := cmd.Start(); err != nil { 92 os.RemoveAll(tmp) 93 if os.IsNotExist(err) { 94 c.Skip(err.Error()) 95 } 96 return nil, err 97 } 98 return &testRegistryV2{ 99 cmd: cmd, 100 dir: tmp, 101 auth: auth, 102 username: username, 103 password: password, 104 email: email, 105 }, nil 106 } 107 108 func (t *testRegistryV2) Ping() error { 109 // We always ping through HTTP for our test registry. 110 resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL)) 111 if err != nil { 112 return err 113 } 114 resp.Body.Close() 115 116 fail := resp.StatusCode != http.StatusOK 117 if t.auth != "" { 118 // unauthorized is a _good_ status when pinging v2/ and it needs auth 119 fail = fail && resp.StatusCode != http.StatusUnauthorized 120 } 121 if fail { 122 return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode) 123 } 124 return nil 125 } 126 127 func (t *testRegistryV2) Close() { 128 t.cmd.Process.Kill() 129 os.RemoveAll(t.dir) 130 } 131 132 func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string { 133 // Split the digest into its algorithm and hex components. 134 dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex() 135 136 // The path to the target blob data looks something like: 137 // baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data" 138 return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", t.dir, dgstAlg, dgstHex[:2], dgstHex) 139 } 140 141 func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte { 142 // Load the target manifest blob. 143 manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest)) 144 if err != nil { 145 c.Fatalf("unable to read blob: %s", err) 146 } 147 148 return manifestBlob 149 } 150 151 func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) { 152 if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil { 153 c.Fatalf("unable to write malicious data blob: %s", err) 154 } 155 } 156 157 func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) { 158 tempFile, err := ioutil.TempFile("", "registry-temp-blob-") 159 if err != nil { 160 c.Fatalf("unable to get temporary blob file: %s", err) 161 } 162 tempFile.Close() 163 164 blobFilename := t.getBlobFilename(blobDigest) 165 166 // Move the existing data file aside, so that we can replace it with a 167 // another blob of data. 168 if err := os.Rename(blobFilename, tempFile.Name()); err != nil { 169 os.Remove(tempFile.Name()) 170 c.Fatalf("unable to move data blob: %s", err) 171 } 172 173 return func() { 174 os.Rename(tempFile.Name(), blobFilename) 175 os.Remove(tempFile.Name()) 176 } 177 }