// Provide implements DockerConfigProvider func (g *containerRegistryProvider) Provide() credentialprovider.DockerConfig { cfg := credentialprovider.DockerConfig{} tokenJsonBlob, err := credentialprovider.ReadUrl(metadataToken, g.Client, metadataHeader) if err != nil { glog.Errorf("while reading access token endpoint: %v", err) return cfg } email, err := credentialprovider.ReadUrl(metadataEmail, g.Client, metadataHeader) if err != nil { glog.Errorf("while reading email endpoint: %v", err) return cfg } var parsedBlob tokenBlob if err := json.Unmarshal([]byte(tokenJsonBlob), &parsedBlob); err != nil { glog.Errorf("while parsing json blob %s: %v", tokenJsonBlob, err) return cfg } entry := credentialprovider.DockerConfigEntry{ Username: "******", Password: parsedBlob.AccessToken, Email: string(email), } // Add our entry for each of the supported container registry URLs for _, k := range containerRegistryUrls { cfg[k] = entry } return cfg }
// Enabled implements a special metadata-based check, which verifies the // storage scope is available on the GCE VM. // If running on a GCE VM, check if 'default' service account exists. // If it does not exist, assume that registry is not enabled. // If default service account exists, check if relevant scopes exist in the default service account. // The metadata service can become temporarily inaccesible. Hence all requests to the metadata // service will be retried until the metadata server returns a `200`. // It is expected that "http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/" will return a `200` // and "http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/default/scopes" will also return `200`. // More information on metadata service can be found here - https://cloud.google.com/compute/docs/storing-retrieving-metadata func (g *containerRegistryProvider) Enabled() bool { if !onGCEVM() { return false } // Given that we are on GCE, we should keep retrying until the metadata server responds. value := runWithBackoff(func() ([]byte, error) { value, err := credentialprovider.ReadUrl(serviceAccounts, g.Client, metadataHeader) if err != nil { glog.V(2).Infof("Failed to Get service accounts from gce metadata server: %v", err) } return value, err }) // We expect the service account to return a list of account directories separated by newlines, e.g., // sv-account-name1/ // sv-account-name2/ // ref: https://cloud.google.com/compute/docs/storing-retrieving-metadata defaultServiceAccountExists := false for _, sa := range strings.Split(string(value), "\n") { if strings.TrimSpace(sa) == defaultServiceAccount { defaultServiceAccountExists = true break } } if !defaultServiceAccountExists { glog.V(2).Infof("'default' service account does not exist. Found following service accounts: %q", string(value)) return false } url := metadataScopes + "?alt=json" value = runWithBackoff(func() ([]byte, error) { value, err := credentialprovider.ReadUrl(url, g.Client, metadataHeader) if err != nil { glog.V(2).Infof("Failed to Get scopes in default service account from gce metadata server: %v", err) } return value, err }) var scopes []string if err := json.Unmarshal(value, &scopes); err != nil { glog.Errorf("Failed to unmarshal scopes: %v", err) return false } for _, v := range scopes { // cloudPlatformScope implies storage scope. if strings.HasPrefix(v, storageScopePrefix) || strings.HasPrefix(v, cloudPlatformScopePrefix) { return true } } glog.Warningf("Google container registry is disabled, no storage scope is available: %s", value) return false }
// Enabled implements a special metadata-based check, which verifies the // storage scope is available on the GCE VM. func (g *containerRegistryProvider) Enabled() bool { value, err := credentialprovider.ReadUrl(metadataScopes+"?alt=json", g.Client, metadataHeader) if err != nil { return false } var scopes []string if err := json.Unmarshal([]byte(value), &scopes); err != nil { return false } for _, v := range scopes { if strings.HasPrefix(v, storageScopePrefix) { return true } } glog.Warningf("Google container registry is disabled, no storage scope is available: %s", value) return false }
// Provide implements DockerConfigProvider func (g *dockerConfigUrlKeyProvider) Provide() credentialprovider.DockerConfig { // Read the contents of the google-dockercfg-url key and load a .dockercfg from there if url, err := credentialprovider.ReadUrl(dockerConfigUrlKey, g.Client, metadataHeader); err != nil { glog.Errorf("while reading 'google-dockercfg-url' metadata: %v", err) } else { if strings.HasPrefix(string(url), "http") { if cfg, err := credentialprovider.ReadDockerConfigFileFromUrl(string(url), g.Client, nil); err != nil { glog.Errorf("while reading 'google-dockercfg-url'-specified url: %s, %v", string(url), err) } else { return cfg } } else { // TODO(mattmoor): support reading alternate scheme URLs (e.g. gs:// or s3://) glog.Errorf("Unsupported URL scheme: %s", string(url)) } } return credentialprovider.DockerConfig{} }
// Enabled implements DockerConfigProvider for all of the Google implementations. func (g *metadataProvider) Enabled() bool { _, err := credentialprovider.ReadUrl(metadataUrl, g.Client, metadataHeader) return err == nil }