using:
golang custom credential provider which allows for arbitrary aws source credential usage (eg AWS_WEB_IDENTITY_TOKEN_FILE
)
AwsSecurityCredentialsSupplier
also see in python here
to use this, you may have en-vars setup like so
export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/aws.txt
export AWS_ROLE_ARN="arn:aws:iam::291738886548:role/cicps3role"
export AWS_ROLE_SESSION_NAME=mysession
and a gcp workload identity provider as shown below along with an iam binding which authorizes a session (eg, for gcs)
gcloud storage buckets add-iam-policy-binding gs://$PROJECT_ID-bucket \
--member="principal://iam.googleapis.com/projects/995081019036/locations/global/workloadIdentityPools/aws-pool-1/subject/arn:aws:sts::291738886548:assumed-role/cicps3role/mysession" \
--role="roles/storage.objectViewer"
package main
import (
"context"
"flag"
"log"
"cloud.google.com/go/storage"
"golang.org/x/oauth2/google/externalaccount"
//"github.com/aws/aws-sdk-go-v2/aws/session"
"github.com/aws/aws-sdk-go-v2/aws"
ac "github.com/aws/aws-sdk-go-v2/config"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
)
/*
export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/aws.txt
export AWS_ROLE_ARN="arn:aws:iam::291738886548:role/cicps3role"
export AWS_ROLE_SESSION_NAME=mysession
$ aws s3 ls s3://
$ aws sts assume-role-with-web-identity \
--role-arn $AWS_ROLE_ARN \
--role-session-name $AWS_ROLE_SESSION_NAME \
--web-identity-token file:///$AWS_WEB_IDENTITY_TOKEN_FILE \
--duration-seconds 1000
gcloud storage buckets add-iam-policy-binding gs://$PROJECT_ID-bucket \
--member="principal://iam.googleapis.com/projects/995081019036/locations/global/workloadIdentityPools/aws-pool-1/subject/arn:aws:sts::291738886548:assumed-role/cicps3role/mysession" \
--role="roles/storage.objectViewer"
*/
var (
projectId = flag.String("projectId", "core-eso", "ProjectID")
)
type awsSupplier struct {
awsRegion string
awsCredentialProvider aws.CredentialsProvider
}
func NewAWSCredProvider(c aws.CredentialsProvider, r string) (awsSupplier, error) {
return awsSupplier{
awsCredentialProvider: c,
awsRegion: r,
}, nil
}
func (supp awsSupplier) AwsRegion(ctx context.Context, options externalaccount.SupplierOptions) (string, error) {
return supp.awsRegion, nil
}
func (supp awsSupplier) AwsSecurityCredentials(ctx context.Context, options externalaccount.SupplierOptions) (*externalaccount.AwsSecurityCredentials, error) {
c, err := supp.awsCredentialProvider.Retrieve(ctx)
if err != nil {
return nil, err
}
return &externalaccount.AwsSecurityCredentials{
AccessKeyID: c.AccessKeyID,
SecretAccessKey: c.SecretAccessKey,
SessionToken: c.SessionToken,
}, nil
}
func main() {
flag.Parse()
log.Printf("======= Init ========")
ctx := context.Background()
cfg, err := ac.LoadDefaultConfig(ctx, ac.WithRegion("us-east-1"))
if err != nil {
log.Fatal(err)
}
ac, err := NewAWSCredProvider(cfg.Credentials, "us-east-1")
if err != nil {
log.Fatal(err)
}
ts, err := externalaccount.NewTokenSource(ctx, externalaccount.Config{
Audience: "//iam.googleapis.com/projects/995081019036/locations/global/workloadIdentityPools/aws-pool-1/providers/aws-provider-1",
SubjectTokenType: "urn:ietf:params:aws:token-type:aws4_request",
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
AwsSecurityCredentialsSupplier: ac,
})
if err != nil {
log.Fatal(err)
}
storageClient, err := storage.NewClient(ctx, option.WithTokenSource(ts))
if err != nil {
log.Fatal(err)
}
sit := storageClient.Buckets(ctx, *projectId)
for {
battrs, err := sit.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
log.Printf(battrs.Name)
}
}