Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read external ID for assume role authentication from k8s Secret #1602

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apis/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion build
Submodule build updated 1 files
+104 −3 makelib/uptest.mk
38 changes: 33 additions & 5 deletions internal/clients/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
19 changes: 19 additions & 0 deletions package/crds/aws.upbound.io_providerconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down