mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	ECR credential provider
This commit is contained in:
		@@ -22,6 +22,19 @@
 | 
				
			|||||||
      "Effect": "Allow",
 | 
					      "Effect": "Allow",
 | 
				
			||||||
      "Action": "ec2:DetachVolume",
 | 
					      "Action": "ec2:DetachVolume",
 | 
				
			||||||
      "Resource": "*"
 | 
					      "Resource": "*"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "Effect": "Allow",
 | 
				
			||||||
 | 
					      "Action": [
 | 
				
			||||||
 | 
					        "ecr:GetAuthorizationToken",
 | 
				
			||||||
 | 
					        "ecr:BatchCheckLayerAvailability",
 | 
				
			||||||
 | 
					        "ecr:GetDownloadUrlForLayer",
 | 
				
			||||||
 | 
					        "ecr:GetRepositoryPolicy",
 | 
				
			||||||
 | 
					        "ecr:DescribeRepositories",
 | 
				
			||||||
 | 
					        "ecr:ListImages",
 | 
				
			||||||
 | 
					        "ecr:BatchGetImage"
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "Resource": "*"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package app
 | 
				
			|||||||
// This file exists to force the desired plugin implementations to be linked.
 | 
					// This file exists to force the desired plugin implementations to be linked.
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	// Credential providers
 | 
						// Credential providers
 | 
				
			||||||
 | 
						_ "k8s.io/kubernetes/pkg/credentialprovider/aws"
 | 
				
			||||||
	_ "k8s.io/kubernetes/pkg/credentialprovider/gcp"
 | 
						_ "k8s.io/kubernetes/pkg/credentialprovider/gcp"
 | 
				
			||||||
	// Network plugins
 | 
						// Network plugins
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubelet/network"
 | 
						"k8s.io/kubernetes/pkg/kubelet/network"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,7 +171,11 @@ The nodes do not need a lot of access to the AWS APIs.  They need to download
 | 
				
			|||||||
a distribution file, and then are responsible for attaching and detaching EBS
 | 
					a distribution file, and then are responsible for attaching and detaching EBS
 | 
				
			||||||
volumes from itself.
 | 
					volumes from itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The node policy is relatively minimal.  The master policy is probably overly
 | 
					The node policy is relatively minimal.  In 1.2 and later, nodes can retrieve ECR
 | 
				
			||||||
 | 
					authorization tokens, refresh them every 12 hours if needed, and fetch Docker
 | 
				
			||||||
 | 
					images from it, as long as the appropriate permissions are enabled.  Those in
 | 
				
			||||||
 | 
					[AmazonEC2ContainerRegistryReadOnly](http://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryReadOnly),
 | 
				
			||||||
 | 
					without write access, should suffice.  The master policy is probably overly
 | 
				
			||||||
permissive.  The security conscious may want to lock-down the IAM policies
 | 
					permissive.  The security conscious may want to lock-down the IAM policies
 | 
				
			||||||
further ([#11936](http://issues.k8s.io/11936)).
 | 
					further ([#11936](http://issues.k8s.io/11936)).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -180,7 +184,7 @@ are correctly configured ([#14226](http://issues.k8s.io/14226)).
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Tagging
 | 
					### Tagging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
All AWS resources are tagged with a tag named "KuberentesCluster", with a value
 | 
					All AWS resources are tagged with a tag named "KubernetesCluster", with a value
 | 
				
			||||||
that is the unique cluster-id.  This tag is used to identify a particular
 | 
					that is the unique cluster-id.  This tag is used to identify a particular
 | 
				
			||||||
'instance' of Kubernetes, even if two clusters are deployed into the same VPC.
 | 
					'instance' of Kubernetes, even if two clusters are deployed into the same VPC.
 | 
				
			||||||
Resources are considered to belong to the same cluster if and only if they have
 | 
					Resources are considered to belong to the same cluster if and only if they have
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,7 @@ The `image` property of a container supports the same syntax as the `docker` com
 | 
				
			|||||||
  - [Updating Images](#updating-images)
 | 
					  - [Updating Images](#updating-images)
 | 
				
			||||||
  - [Using a Private Registry](#using-a-private-registry)
 | 
					  - [Using a Private Registry](#using-a-private-registry)
 | 
				
			||||||
    - [Using Google Container Registry](#using-google-container-registry)
 | 
					    - [Using Google Container Registry](#using-google-container-registry)
 | 
				
			||||||
 | 
					    - [Using AWS EC2 Container Registry](#using-aws-ec2-container-registry)
 | 
				
			||||||
    - [Configuring Nodes to Authenticate to a Private Repository](#configuring-nodes-to-authenticate-to-a-private-repository)
 | 
					    - [Configuring Nodes to Authenticate to a Private Repository](#configuring-nodes-to-authenticate-to-a-private-repository)
 | 
				
			||||||
    - [Pre-pulling Images](#pre-pulling-images)
 | 
					    - [Pre-pulling Images](#pre-pulling-images)
 | 
				
			||||||
    - [Specifying ImagePullSecrets on a Pod](#specifying-imagepullsecrets-on-a-pod)
 | 
					    - [Specifying ImagePullSecrets on a Pod](#specifying-imagepullsecrets-on-a-pod)
 | 
				
			||||||
@@ -97,6 +98,21 @@ Google service account.  The service account on the instance
 | 
				
			|||||||
will have a `https://www.googleapis.com/auth/devstorage.read_only`,
 | 
					will have a `https://www.googleapis.com/auth/devstorage.read_only`,
 | 
				
			||||||
so it can pull from the project's GCR, but not push.
 | 
					so it can pull from the project's GCR, but not push.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Using AWS EC2 Container Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Kubernetes has native support for the [AWS EC2 Container
 | 
				
			||||||
 | 
					Registry](https://aws.amazon.com/ecr/), when nodes are AWS instances.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Simply use the full image name (e.g. `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`)
 | 
				
			||||||
 | 
					in the Pod definition.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All users of the cluster who can create pods will be able to run pods that use any of the
 | 
				
			||||||
 | 
					images in the ECR registry.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The kubelet will fetch and periodically refresh ECR credentials.  It needs the
 | 
				
			||||||
 | 
					`ecr:GetAuthorizationToken` permission to do this.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Configuring Nodes to Authenticate to a Private Repository
 | 
					### Configuring Nodes to Authenticate to a Private Repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node
 | 
					**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										163
									
								
								pkg/credentialprovider/aws/aws_credentials.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								pkg/credentialprovider/aws/aws_credentials.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 The Kubernetes Authors All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package aws_credentials
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/session"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/service/ecr"
 | 
				
			||||||
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/cloudprovider"
 | 
				
			||||||
 | 
						aws_cloud "k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/credentialprovider"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var registryUrls = []string{"*.dkr.ecr.*.amazonaws.com"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// awsHandlerLogger is a handler that logs all AWS SDK requests
 | 
				
			||||||
 | 
					// Copied from cloudprovider/aws/log_handler.go
 | 
				
			||||||
 | 
					func awsHandlerLogger(req *request.Request) {
 | 
				
			||||||
 | 
						service := req.ClientInfo.ServiceName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name := "?"
 | 
				
			||||||
 | 
						if req.Operation != nil {
 | 
				
			||||||
 | 
							name = req.Operation.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glog.V(4).Infof("AWS request: %s %s", service, name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An interface for testing purposes.
 | 
				
			||||||
 | 
					type tokenGetter interface {
 | 
				
			||||||
 | 
						GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The canonical implementation
 | 
				
			||||||
 | 
					type ecrTokenGetter struct {
 | 
				
			||||||
 | 
						svc *ecr.ECR
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *ecrTokenGetter) GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error) {
 | 
				
			||||||
 | 
						return p.svc.GetAuthorizationToken(input)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ecrProvider is a DockerConfigProvider that gets and refreshes 12-hour tokens
 | 
				
			||||||
 | 
					// from AWS to access ECR.
 | 
				
			||||||
 | 
					type ecrProvider struct {
 | 
				
			||||||
 | 
						getter tokenGetter
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init registers the various means by which ECR credentials may
 | 
				
			||||||
 | 
					// be resolved.
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						credentialprovider.RegisterCredentialProvider("aws-ecr-key",
 | 
				
			||||||
 | 
							&credentialprovider.CachingDockerConfigProvider{
 | 
				
			||||||
 | 
								Provider: &ecrProvider{},
 | 
				
			||||||
 | 
								// Refresh credentials a little earlier before they expire
 | 
				
			||||||
 | 
								Lifetime: 11*time.Hour + 55*time.Minute,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enabled implements DockerConfigProvider.Enabled for the AWS token-based implementation.
 | 
				
			||||||
 | 
					// For now, it gets activated only if AWS was chosen as the cloud provider.
 | 
				
			||||||
 | 
					// TODO: figure how to enable it manually for deployments that are not on AWS but still
 | 
				
			||||||
 | 
					// use ECR somehow?
 | 
				
			||||||
 | 
					func (p *ecrProvider) Enabled() bool {
 | 
				
			||||||
 | 
						provider, err := cloudprovider.GetCloudProvider(aws_cloud.ProviderName, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Errorf("while initializing AWS cloud provider %v", err)
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if provider == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zones, ok := provider.Zones()
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							glog.Errorf("couldn't get Zones() interface")
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						zone, err := zones.GetZone()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Errorf("while getting zone %v", err)
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if zone.Region == "" {
 | 
				
			||||||
 | 
							glog.Errorf("Region information is empty")
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						getter := &ecrTokenGetter{svc: ecr.New(session.New(&aws.Config{
 | 
				
			||||||
 | 
							Credentials: nil,
 | 
				
			||||||
 | 
							Region:      &zone.Region,
 | 
				
			||||||
 | 
						}))}
 | 
				
			||||||
 | 
						getter.svc.Handlers.Sign.PushFrontNamed(request.NamedHandler{
 | 
				
			||||||
 | 
							Name: "k8s/logger",
 | 
				
			||||||
 | 
							Fn:   awsHandlerLogger,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						p.getter = getter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Provide implements DockerConfigProvider.Provide, refreshing ECR tokens on demand
 | 
				
			||||||
 | 
					func (p *ecrProvider) Provide() credentialprovider.DockerConfig {
 | 
				
			||||||
 | 
						cfg := credentialprovider.DockerConfig{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: fill in RegistryIds?
 | 
				
			||||||
 | 
						params := &ecr.GetAuthorizationTokenInput{}
 | 
				
			||||||
 | 
						output, err := p.getter.GetAuthorizationToken(params)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Errorf("while requesting ECR authorization token %v", err)
 | 
				
			||||||
 | 
							return cfg
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if output == nil {
 | 
				
			||||||
 | 
							glog.Errorf("Got back no ECR token")
 | 
				
			||||||
 | 
							return cfg
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, data := range output.AuthorizationData {
 | 
				
			||||||
 | 
							if data.ProxyEndpoint != nil &&
 | 
				
			||||||
 | 
								data.AuthorizationToken != nil {
 | 
				
			||||||
 | 
								decodedToken, err := base64.StdEncoding.DecodeString(aws.StringValue(data.AuthorizationToken))
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									glog.Errorf("while decoding token for endpoint %s %v", data.ProxyEndpoint, err)
 | 
				
			||||||
 | 
									return cfg
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								parts := strings.SplitN(string(decodedToken), ":", 2)
 | 
				
			||||||
 | 
								user := parts[0]
 | 
				
			||||||
 | 
								password := parts[1]
 | 
				
			||||||
 | 
								entry := credentialprovider.DockerConfigEntry{
 | 
				
			||||||
 | 
									Username: user,
 | 
				
			||||||
 | 
									Password: password,
 | 
				
			||||||
 | 
									// ECR doesn't care and Docker is about to obsolete it
 | 
				
			||||||
 | 
									Email: "not@val.id",
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Add our entry for each of the supported container registry URLs
 | 
				
			||||||
 | 
								for _, k := range registryUrls {
 | 
				
			||||||
 | 
									cfg[k] = entry
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cfg
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										108
									
								
								pkg/credentialprovider/aws/aws_credentials_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								pkg/credentialprovider/aws/aws_credentials_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 The Kubernetes Authors All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package aws_credentials
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/service/ecr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/credentialprovider"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const user = "foo"
 | 
				
			||||||
 | 
					const password = "1234567890abcdef"
 | 
				
			||||||
 | 
					const email = "not@val.id"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Mock implementation
 | 
				
			||||||
 | 
					type testTokenGetter struct {
 | 
				
			||||||
 | 
						user     string
 | 
				
			||||||
 | 
						password string
 | 
				
			||||||
 | 
						endpoint string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *testTokenGetter) GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expiration := time.Now().Add(1 * time.Hour)
 | 
				
			||||||
 | 
						creds := []byte(fmt.Sprintf("%s:%s", p.user, p.password))
 | 
				
			||||||
 | 
						data := &ecr.AuthorizationData{
 | 
				
			||||||
 | 
							AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString(creds)),
 | 
				
			||||||
 | 
							ExpiresAt:          &expiration,
 | 
				
			||||||
 | 
							ProxyEndpoint:      aws.String(p.endpoint),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output := &ecr.GetAuthorizationTokenOutput{
 | 
				
			||||||
 | 
							AuthorizationData: []*ecr.AuthorizationData{data},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return output, nil //p.svc.GetAuthorizationToken(input)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEcrProvide(t *testing.T) {
 | 
				
			||||||
 | 
						registry := "123456789012.dkr.ecr.lala-land-1.amazonaws.com"
 | 
				
			||||||
 | 
						otherRegistries := []string{"private.registry.com",
 | 
				
			||||||
 | 
							"gcr.io",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						image := "foo/bar"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						provider := &ecrProvider{
 | 
				
			||||||
 | 
							getter: &testTokenGetter{
 | 
				
			||||||
 | 
								user:     user,
 | 
				
			||||||
 | 
								password: password,
 | 
				
			||||||
 | 
								endpoint: registry},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						keyring := &credentialprovider.BasicDockerKeyring{}
 | 
				
			||||||
 | 
						keyring.Add(provider.Provide())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Verify that we get the expected username/password combo for
 | 
				
			||||||
 | 
						// an ECR image name.
 | 
				
			||||||
 | 
						fullImage := path.Join(registry, image)
 | 
				
			||||||
 | 
						creds, ok := keyring.Lookup(fullImage)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Errorf("Didn't find expected URL: %s", fullImage)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(creds) > 1 {
 | 
				
			||||||
 | 
							t.Errorf("Got more hits than expected: %s", creds)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						val := creds[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if user != val.Username {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected username value, want: _token, got: %s", val.Username)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if password != val.Password {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if email != val.Email {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Verify that we get an error for other images.
 | 
				
			||||||
 | 
						for _, otherRegistry := range otherRegistries {
 | 
				
			||||||
 | 
							fullImage = path.Join(otherRegistry, image)
 | 
				
			||||||
 | 
							creds, ok = keyring.Lookup(fullImage)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								t.Errorf("Unexpectedly found image: %s", fullImage)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user