Skip to content

Commit f132cba

Browse files
authored
Merge pull request #167 from drone-plugins/CI-14214
feat: [CI-14214]: Add PLUGIN_USER_ROLE_EXTERNAL_ID to pass external ID for the secondary role when required
2 parents c9a496f + 8813c3d commit f132cba

File tree

3 files changed

+79
-53
lines changed

3 files changed

+79
-53
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ docker: Error response from daemon: Container command
4848

4949
Execute from the working directory:
5050

51-
* For upload
51+
* For Upload
5252
```
5353
docker run --rm \
5454
-e PLUGIN_SOURCE=<source> \
@@ -61,7 +61,7 @@ docker run --rm \
6161
plugins/s3 --dry-run
6262
```
6363

64-
* For download
64+
* For Download
6565
```
6666
docker run --rm \
6767
-e PLUGIN_SOURCE=<source directory to be downloaded from bucket> \

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ func main() {
5252
Usage: "AWS user role",
5353
EnvVar: "PLUGIN_USER_ROLE_ARN,AWS_USER_ROLE_ARN",
5454
},
55+
cli.StringFlag{
56+
Name: "user-role-external-id",
57+
Usage: "external ID to use when assuming secondary role",
58+
EnvVar: "PLUGIN_USER_ROLE_EXTERNAL_ID",
59+
},
5560
cli.StringFlag{
5661
Name: "bucket",
5762
Usage: "aws bucket",
@@ -166,6 +171,7 @@ func run(c *cli.Context) error {
166171
AssumeRoleSessionName: c.String("assume-role-session-name"),
167172
Bucket: c.String("bucket"),
168173
UserRoleArn: c.String("user-role-arn"),
174+
UserRoleExternalID: c.String("user-role-external-id"),
169175
Region: c.String("region"),
170176
Access: c.String("acl"),
171177
Source: c.String("source"),
@@ -181,7 +187,7 @@ func run(c *cli.Context) error {
181187
PathStyle: c.Bool("path-style"),
182188
DryRun: c.Bool("dry-run"),
183189
ExternalID: c.String("external-id"),
184-
IdToken: c.String("oidc-token-id"),
190+
IdToken: c.String("oidc-token-id"),
185191
}
186192

187193
return plugin.Exec()

plugin.go

Lines changed: 70 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Plugin struct {
2929
AssumeRoleSessionName string
3030
Bucket string
3131
UserRoleArn string
32+
UserRoleExternalID string // New field for UserRoleArn ExternalID
3233

3334
// if not "", enable server-side encryption
3435
// valid values are:
@@ -99,7 +100,7 @@ type Plugin struct {
99100
// set externalID for assume role
100101
ExternalID string
101102

102-
// set OIDC ID Token to retrieve temporary credentials
103+
// set OIDC ID Token to retrieve temporary credentials
103104
IdToken string
104105
}
105106

@@ -434,60 +435,79 @@ func (p *Plugin) downloadS3Objects(client *s3.S3, sourceDir string) error {
434435

435436
// createS3Client creates and returns an S3 client based on the plugin configuration
436437
func (p *Plugin) createS3Client() *s3.S3 {
437-
conf := &aws.Config{
438-
Region: aws.String(p.Region),
439-
Endpoint: &p.Endpoint,
440-
DisableSSL: aws.Bool(strings.HasPrefix(p.Endpoint, "http://")),
441-
S3ForcePathStyle: aws.Bool(p.PathStyle),
442-
}
443-
444-
sess, err := session.NewSession(conf)
445-
if err != nil {
446-
log.Fatalf("failed to create AWS session: %v", err)
447-
}
448-
449-
if p.Key != "" && p.Secret != "" {
450-
conf.Credentials = credentials.NewStaticCredentials(p.Key, p.Secret, "")
451-
} else if p.IdToken != "" && p.AssumeRole != "" {
452-
creds, err := assumeRoleWithWebIdentity(sess, p.AssumeRole, p.AssumeRoleSessionName, p.IdToken)
453-
if err != nil {
454-
log.Fatalf("failed to assume role with web identity: %v", err)
455-
}
456-
conf.Credentials = creds
457-
} else if p.AssumeRole != "" {
458-
conf.Credentials = assumeRole(p.AssumeRole, p.AssumeRoleSessionName, p.ExternalID)
459-
} else {
460-
log.Warn("AWS Key and/or Secret not provided (falling back to ec2 instance profile)")
461-
}
438+
conf := &aws.Config{
439+
Region: aws.String(p.Region),
440+
Endpoint: &p.Endpoint,
441+
DisableSSL: aws.Bool(strings.HasPrefix(p.Endpoint, "http://")),
442+
S3ForcePathStyle: aws.Bool(p.PathStyle),
443+
}
444+
445+
sess, err := session.NewSession(conf)
446+
if err != nil {
447+
log.Fatalf("failed to create AWS session: %v", err)
448+
}
449+
450+
if p.Key != "" && p.Secret != "" {
451+
conf.Credentials = credentials.NewStaticCredentials(p.Key, p.Secret, "")
452+
} else if p.IdToken != "" && p.AssumeRole != "" {
453+
creds, err := assumeRoleWithWebIdentity(sess, p.AssumeRole, p.AssumeRoleSessionName, p.IdToken)
454+
if err != nil {
455+
log.Fatalf("failed to assume role with web identity: %v", err)
456+
}
457+
conf.Credentials = creds
458+
} else if p.AssumeRole != "" {
459+
conf.Credentials = assumeRole(p.AssumeRole, p.AssumeRoleSessionName, p.ExternalID)
460+
} else {
461+
log.Warn("AWS Key and/or Secret not provided (falling back to ec2 instance profile)")
462+
}
462463

463464
sess, err = session.NewSession(conf)
464-
if err != nil {
465-
log.Fatalf("failed to create AWS session: %v", err)
466-
}
465+
if err != nil {
466+
log.Fatalf("failed to create AWS session: %v", err)
467+
}
468+
469+
client := s3.New(sess, conf)
470+
471+
if len(p.UserRoleArn) > 0 {
472+
log.WithFields(log.Fields{
473+
"UserRoleArn": p.UserRoleArn,
474+
}).Info("Assuming user role ARN")
467475

468-
client := s3.New(sess, conf)
476+
// Create new credentials by assuming the UserRoleArn with ExternalID
477+
creds := stscreds.NewCredentials(sess, p.UserRoleArn, func(provider *stscreds.AssumeRoleProvider) {
478+
if p.UserRoleExternalID != "" {
479+
provider.ExternalID = aws.String(p.UserRoleExternalID)
480+
}
481+
})
469482

470-
if len(p.UserRoleArn) > 0 {
471-
confRoleArn := aws.Config{
472-
Region: aws.String(p.Region),
473-
Credentials: stscreds.NewCredentials(sess, p.UserRoleArn),
474-
}
475-
client = s3.New(sess, &confRoleArn)
476-
}
483+
// Create a new session with the new credentials
484+
confWithUserRole := &aws.Config{
485+
Region: aws.String(p.Region),
486+
Credentials: creds,
487+
}
488+
489+
sessWithUserRole, err := session.NewSession(confWithUserRole)
490+
if err != nil {
491+
log.Fatalf("failed to create AWS session with user role: %v", err)
492+
}
493+
494+
client = s3.New(sessWithUserRole)
495+
}
496+
497+
return client
477498

478-
return client
479499
}
480500

481501
func assumeRoleWithWebIdentity(sess *session.Session, roleArn, roleSessionName, idToken string) (*credentials.Credentials, error) {
482-
svc := sts.New(sess)
483-
input := &sts.AssumeRoleWithWebIdentityInput{
484-
RoleArn: aws.String(roleArn),
485-
RoleSessionName: aws.String(roleSessionName),
486-
WebIdentityToken: aws.String(idToken),
487-
}
488-
result, err := svc.AssumeRoleWithWebIdentity(input)
489-
if err != nil {
490-
log.Fatalf("failed to assume role with web identity: %v", err)
491-
}
492-
return credentials.NewStaticCredentials(*result.Credentials.AccessKeyId, *result.Credentials.SecretAccessKey, *result.Credentials.SessionToken), nil
493-
}
502+
svc := sts.New(sess)
503+
input := &sts.AssumeRoleWithWebIdentityInput{
504+
RoleArn: aws.String(roleArn),
505+
RoleSessionName: aws.String(roleSessionName),
506+
WebIdentityToken: aws.String(idToken),
507+
}
508+
result, err := svc.AssumeRoleWithWebIdentity(input)
509+
if err != nil {
510+
log.Fatalf("failed to assume role with web identity: %v", err)
511+
}
512+
return credentials.NewStaticCredentials(*result.Credentials.AccessKeyId, *result.Credentials.SecretAccessKey, *result.Credentials.SessionToken), nil
513+
}

0 commit comments

Comments
 (0)