diff --git a/README.md b/README.md index 73661d0..3b9a77e 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,12 @@ differences: * `aws_region`: *Optional. Default `""`.* The region to use for accessing ECR. This is required if you are using ECR. This region will help determine the full repository URL you are accessing (e.g., `012345678910.dkr.ecr.us-east-1.amazonaws.com`) * `aws_role_arn`: *Optional. Default `""`.* If set, then this role will be - assumed before authenticating to ECR. + assumed before authenticating to ECR. An error will occur if `aws_role_arns` + is also specified. This is kept for backward compatibility. + +* `aws_role_arns`: *Optional. Default `""`.* An array of AWS IAM roles. + If set, these roles will be assumed in the specified order before authenticating to ECR. + An error will occur if `aws_role_arn` is also specified. * `debug`: *Optional. Default `false`.* If set, progress bars will be disabled and debugging output will be printed instead. @@ -110,7 +115,7 @@ differences: This is used to validate the certificate of the docker registry when the registry's certificate is signed by a custom authority (or itself). -### Signing with Docker Hub +### Signing with Docker Hub Configure Docker Content Trust for use with the [Docker Hub](https:/hub.docker.io) and Notary service by specifying the above source parameters as follows: @@ -265,7 +270,7 @@ Fetches an image at the exact digest specified by the version. The resource will produce the following files: -* `./repository`: A file containing the image's full repository name, e.g. `concourse/concourse`. +* `./repository`: A file containing the image's full repository name, e.g. `concourse/concourse`. For ECR images, this will include the registry the image was pulled from. * `./tag`: A file containing the tag from the version. * `./digest`: A file containing the digest from the version, e.g. `sha256:...`. diff --git a/types.go b/types.go index e9aade4..9f77514 100644 --- a/types.go +++ b/types.go @@ -55,12 +55,13 @@ type OutResponse struct { } type AwsCredentials struct { - AwsAccessKeyId string `json:"aws_access_key_id,omitempty"` - AwsSecretAccessKey string `json:"aws_secret_access_key,omitempty"` - AwsSessionToken string `json:"aws_session_token,omitempty"` - AwsRegion string `json:"aws_region,omitempty"` - AWSECRRegistryId string `json:"aws_ecr_registry_id,omitempty"` - AwsRoleArn string `json:"aws_role_arn,omitempty"` + AwsAccessKeyId string `json:"aws_access_key_id,omitempty"` + AwsSecretAccessKey string `json:"aws_secret_access_key,omitempty"` + AwsSessionToken string `json:"aws_session_token,omitempty"` + AwsRegion string `json:"aws_region,omitempty"` + AWSECRRegistryId string `json:"aws_ecr_registry_id,omitempty"` + AwsRoleArn string `json:"aws_role_arn,omitempty"` + AwsRoleArns []string `json:"aws_role_arns,omitempty"` } type BasicCredentials struct { @@ -278,19 +279,33 @@ func (source *Source) Metadata() []MetadataField { func (source *Source) AuthenticateToECR() bool { logrus.Warnln("ECR integration is experimental and untested") + + if source.AwsRoleArn != "" && len(source.AwsRoleArns) != 0 { + logrus.Errorf("`aws_role_arn` cannot be set at the same time as `aws_role_arns`") + return false + } + mySession := session.Must(session.NewSession(&aws.Config{ Region: aws.String(source.AwsRegion), Credentials: credentials.NewStaticCredentials(source.AwsAccessKeyId, source.AwsSecretAccessKey, source.AwsSessionToken), })) - var config aws.Config - - // If a role arn has been supplied, then assume role and get a new session + // Note: This implementation gives precedence to `aws_role_arn` since it + // assumes that we've errored if both `aws_role_arn` and `aws_role_arns` + // are set + awsRoleArns := source.AwsRoleArns if source.AwsRoleArn != "" { - config = aws.Config{Credentials: stscreds.NewCredentials(mySession, source.AwsRoleArn)} + awsRoleArns = []string{source.AwsRoleArn} + } + for _, roleArn := range awsRoleArns { + logrus.Debugf("assuming new role: %s", roleArn) + mySession = session.Must(session.NewSession(&aws.Config{ + Region: aws.String(source.AwsRegion), + Credentials: stscreds.NewCredentials(mySession, roleArn), + })) } - client := ecr.New(mySession, &config) + client := ecr.New(mySession) result, err := source.GetECRAuthorizationToken(client) if err != nil { logrus.Errorf("failed to authenticate to ECR: %s", err)