Skip to content

Commit

Permalink
support EC2 AWS credentials and IAM roles chain
Browse files Browse the repository at this point in the history
In order to avoid passing explicitly the AWS credentials, the resource
has been modified to support retrieval of AWS credentials via EC2
metadata. In addition, IAM roles chain is now supported to provide the
flexibility required for GOV.UK scenario where the ec2 instances have
the credentials of the Concourse worker role which needs to be used to
assume the Concourse deployer role. The deployer role is then used to
assume a role in the GOV.UK production ECR to pull images.

To build and push image, e.g. procedure:

```sh
docker build -t registry-image-resource --target tests -f dockerfiles/alpine/Dockerfile .
docker tag registry-image-resource:latest fredericfran/registry-image:0.0.2
docker push fredericfran/registry-image:0.0.2
```

Signed-off-by: Frederic Francois <[email protected]>
  • Loading branch information
fredericfran-gds committed Jul 8, 2021
1 parent 753290b commit 397083c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,16 @@ 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_ec2_credentials`: *Optional. Default `false`.* If set, allows the retrieval of
AWS credentials from the EC2 metadata.

* `aws_role_arn`: *Optional. Default `""`.* If set, then this role will be
assumed before authenticating to ECR.
assumed before authenticating to ECR. It is overridden by `aws_role_arns` if
latter is also specified. This is kept for backward compatibility.

* `aws_role_arns`: *Optional. Default `""`.* A comma-delimited list of AWS IAM roles.
If set, these roles will be assumed in the specified order before authenticating to ECR.
It overrides `aws_role_arn`.

* `debug`: *Optional. Default `false`.* If set, progress bars will be disabled
and debugging output will be printed instead.
Expand Down Expand Up @@ -110,7 +118,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:
Expand Down Expand Up @@ -265,7 +273,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:...`.
Expand Down
3 changes: 2 additions & 1 deletion commands/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func (c *Check) Execute() error {
return fmt.Errorf("invalid payload: %s", err)
}

if req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "" && req.Source.AwsRegion != "" {
if ((req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "") ||
(req.Source.AwsEC2Credentials)) && req.Source.AwsRegion != "" {
if !req.Source.AuthenticateToECR() {
return fmt.Errorf("cannot authenticate with ECR")
}
Expand Down
3 changes: 2 additions & 1 deletion commands/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func (i *In) Execute() error {

dest := i.args[1]

if req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "" && req.Source.AwsRegion != "" {
if ((req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "") ||
(req.Source.AwsEC2Credentials)) && req.Source.AwsRegion != "" {
if !req.Source.AuthenticateToECR() {
return fmt.Errorf("cannot authenticate with ECR")
}
Expand Down
3 changes: 2 additions & 1 deletion commands/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func (o *Out) Execute() error {

src := o.args[1]

if req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "" && req.Source.AwsRegion != "" {
if ((req.Source.AwsAccessKeyId != "" && req.Source.AwsSecretAccessKey != "") ||
(req.Source.AwsEC2Credentials)) && req.Source.AwsRegion != "" {
if !req.Source.AuthenticateToECR() {
return fmt.Errorf("cannot authenticate with ECR")
}
Expand Down
46 changes: 37 additions & 9 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go/service/ecr/ecriface"
Expand Down Expand Up @@ -55,12 +57,14 @@ type OutResponse struct {
}

type AwsCredentials struct {
AwsEC2Credentials bool `json:"aws_ec2_credentials,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 {
Expand Down Expand Up @@ -278,19 +282,43 @@ func (source *Source) Metadata() []MetadataField {

func (source *Source) AuthenticateToECR() bool {
logrus.Warnln("ECR integration is experimental and untested")
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
var mySession *session.Session

// If a role arn has been supplied, then assume role and get a new session
if source.AwsRoleArn != "" {
config = aws.Config{Credentials: stscreds.NewCredentials(mySession, source.AwsRoleArn)}
if source.AwsEC2Credentials {
mySession = session.Must(session.NewSession(&aws.Config{
Region: aws.String(source.AwsRegion),
Credentials: credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())}),
}))

} else {
mySession = session.Must(session.NewSession(&aws.Config{
Region: aws.String(source.AwsRegion),
Credentials: credentials.NewStaticCredentials(source.AwsAccessKeyId, source.AwsSecretAccessKey, source.AwsSessionToken),
}))
}

// If aws role arns chain has been supplied, then assume roles in turn and get a new session
if source.AwsRoleArns != "" {
logrus.Warnln("Using `aws_role_arns` rather than `aws_role_arn`, see documentation")
awsRoleArnsList := strings.Split(source.AwsRoleArns, ",")

for _, roleArn := range awsRoleArnsList {
logrus.Debugf("assuming new role: %s", roleArn)
mySession = session.Must(session.NewSession(&aws.Config{
Region: aws.String(source.AwsRegion),
Credentials: stscreds.NewCredentials(mySession, roleArn),
}))
}
} else if source.AwsRoleArn != "" { //Assume one aws role only, kept for backward compatibility.
logrus.Debugf("assuming new role: %s", source.AwsRoleArn)
mySession = session.Must(session.NewSession(&aws.Config{
Region: aws.String(source.AwsRegion),
Credentials: stscreds.NewCredentials(mySession, source.AwsRoleArn),
}))
}

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)
Expand Down

0 comments on commit 397083c

Please sign in to comment.