diff --git a/apis/v1beta1/types.go b/apis/v1beta1/types.go index 3f856cfe95..b7f5a3e29f 100644 --- a/apis/v1beta1/types.go +++ b/apis/v1beta1/types.go @@ -53,6 +53,11 @@ type AssumeRoleOptions struct { // +optional ExternalID *string `json:"externalID,omitempty"` + // An ExternalIDSecretRef is a reference to a secret key that contains the external ID + // that must be used to assume the role. + // +optional + ExternalIDSecretRef *xpv1.SecretKeySelector `json:"externalIDSecretRef,omitempty"` + // Tags is list of session tags that you want to pass. Each session tag consists of a key // name and an associated value. For more information about session tags, see // Tagging STS Sessions diff --git a/build b/build index d3155548bf..1ed19332b9 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit d3155548bfab68fc8bea64c5526642b7b565ae33 +Subproject commit 1ed19332b947c449795fd016f3c21ee0a64930fd diff --git a/internal/clients/provider_config.go b/internal/clients/provider_config.go index 1c6661776c..7ebbde74d5 100644 --- a/internal/clients/provider_config.go +++ b/internal/clients/provider_config.go @@ -129,7 +129,7 @@ func GetAWSConfigWithoutTracking(ctx context.Context, c client.Client, obj runti } } - cfg, err = GetRoleChainConfig(ctx, &pc.Spec, cfg) + cfg, err = GetRoleChainConfig(ctx, c, &pc.Spec, cfg) if err != nil { return nil, errors.Wrap(err, "cannot get credentials") } @@ -293,13 +293,13 @@ func UseProviderSecret(ctx context.Context, data []byte, profile, region string) // GetRoleChainConfig returns an aws.Config capable of doing role chaining with // AssumeRoleWithWebIdentity & AssumeRoles. -func GetRoleChainConfig(ctx context.Context, pcs *v1beta1.ProviderConfigSpec, cfg *aws.Config) (*aws.Config, error) { +func GetRoleChainConfig(ctx context.Context, kube client.Client, pcs *v1beta1.ProviderConfigSpec, cfg *aws.Config) (*aws.Config, error) { pCfg := cfg for _, aro := range pcs.AssumeRoleChain { stsAssume := stscreds.NewAssumeRoleProvider( sts.NewFromConfig(*pCfg, stsRegionOrDefault(cfg.Region)), //nolint:contextcheck aws.ToString(aro.RoleARN), - SetAssumeRoleOptions(aro), + SetAssumeRoleOptions(ctx, kube, aro), ) cfgWithAssumeRole, err := config.LoadDefaultConfig( ctx, @@ -450,10 +450,38 @@ func UseUpbound(ctx context.Context, region string, pcs *v1beta1.ProviderConfigS return GetAssumeRoleWithWebIdentityConfig(ctx, cfg, *pcs.Credentials.Upbound.WebIdentity, upboundProviderIdentityTokenFile) } +// ExtractSecretValue extracts the value from a secret using a v1.SecretKeySelector, to reuse resource.ExtractSecret that does it using v1.CommonCredentialSelectors +func ExtractSecretValue(ctx context.Context, kube client.Client, selector *v1.SecretKeySelector) ([]byte, error) { + if selector == nil { + return nil, errors.New("SecretKeySelector is nil") + } + + // Wrap SecretKeySelector in CommonCredentialSelectors + credSelectors := v1.CommonCredentialSelectors{ + SecretRef: selector, + } + + // Reuse ExtractSecret function (https://github.com/crossplane/crossplane-runtime/blob/19d95a69cc03690c4b867ff91d89681fcf872a93/pkg/resource/providerconfig.go#L77-L87) + return resource.ExtractSecret(ctx, kube, credSelectors) +} + // SetAssumeRoleOptions sets options when Assuming an IAM Role -func SetAssumeRoleOptions(aro v1beta1.AssumeRoleOptions) func(*stscreds.AssumeRoleOptions) { +func SetAssumeRoleOptions(ctx context.Context, kube client.Client, aro v1beta1.AssumeRoleOptions) func(*stscreds.AssumeRoleOptions) { return func(opt *stscreds.AssumeRoleOptions) { - opt.ExternalID = aro.ExternalID + if aro.ExternalID != nil { + opt.ExternalID = aro.ExternalID + } + if aro.ExternalIDSecretRef != nil { + // Fetch secret value + secretValue, err := ExtractSecretValue(ctx, kube, aro.ExternalIDSecretRef) + if err != nil { + fmt.Printf("Error fetching ExternalID from secret: %v\n", err) + return + } + secretValueStr := string(secretValue) + opt.ExternalID = &secretValueStr + } + for _, t := range aro.Tags { opt.Tags = append( opt.Tags, diff --git a/package/crds/aws.upbound.io_providerconfigs.yaml b/package/crds/aws.upbound.io_providerconfigs.yaml index 15d1c5ffa6..f0afae3387 100644 --- a/package/crds/aws.upbound.io_providerconfigs.yaml +++ b/package/crds/aws.upbound.io_providerconfigs.yaml @@ -63,6 +63,25 @@ spec: description: ExternalID is the external ID used when assuming role. type: string + externalIDSecretRef: + description: |- + An ExternalIDSecretRef is a reference to a secret key that contains the external ID + that must be used to assume the role. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object roleARN: description: AssumeRoleARN to assume with provider credentials type: string