Skip to content

Commit

Permalink
use native tf provider configure function for no-fork client config
Browse files Browse the repository at this point in the history
Signed-off-by: Erhan Cagirici <[email protected]>
  • Loading branch information
erhancagirici committed Dec 7, 2023
1 parent a1e8b3d commit 7a61c51
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 117 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/aws/aws-sdk-go-v2 v1.18.0
github.com/aws/aws-sdk-go-v2/config v1.18.12
github.com/aws/aws-sdk-go-v2/credentials v1.13.12
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3
github.com/aws/aws-sdk-go-v2/service/eks v1.22.0
github.com/aws/aws-sdk-go-v2/service/sts v1.18.11
github.com/aws/smithy-go v1.13.5
Expand All @@ -16,7 +15,6 @@ require (
github.com/crossplane/upjet v1.0.0
github.com/go-ini/ini v1.46.0
github.com/google/go-cmp v0.6.0
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.25
github.com/hashicorp/terraform-json v0.17.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
github.com/hashicorp/terraform-provider-aws v0.0.0-00010101000000-000000000000
Expand All @@ -40,6 +38,7 @@ require (
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.44.261 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 // indirect
Expand Down Expand Up @@ -111,6 +110,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.20.0 // indirect
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.25 // indirect
github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2 v2.0.0-beta.26 // indirect
github.com/hashicorp/awspolicyequivalence v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand Down
129 changes: 14 additions & 115 deletions internal/clients/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,10 @@ package clients
import (
"context"
"os"
"reflect"
"unsafe"

"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"

tfawsbase "github.com/hashicorp/aws-sdk-go-base/v2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/xpprovider"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
tfsdk "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"k8s.io/apimachinery/pkg/types"

"github.com/crossplane/crossplane-runtime/pkg/logging"
Expand Down Expand Up @@ -104,21 +98,11 @@ func SelectTerraformSetup(log logging.Logger, config *SetupConfig) terraform.Set
}
}

awsConfig, err := configureNoForkAWSClient(ctx, c, mg, pc, &ps)
if err != nil {
return terraform.Setup{}, errors.Wrap(err, "could not configure no-fork AWS client")
}
p := config.TerraformProvider.Meta()
tfClient, diag := awsConfig.GetClient(ctx, &xpprovider.AWSClient{
// #nosec G103
ServicePackages: (*xpprovider.AWSClient)(unsafe.Pointer(reflect.ValueOf(p).Pointer())).ServicePackages,
})
if diag != nil && diag.HasError() {
return terraform.Setup{}, errors.Errorf("failed to configure the AWS client: %v", diag)
if config.TerraformProvider == nil {
return terraform.Setup{}, errors.New("terraform provider cannot be nil")
}
ps.Meta = tfClient

return ps, nil
return ps, errors.Wrap(configureNoForkAWSClient(ctx, &ps, *config.TerraformProvider), "could not configure no-fork AWS client")
}
}

Expand Down Expand Up @@ -255,99 +239,14 @@ func getAWSConfig(ctx context.Context, c client.Client, mg resource.Managed) (*a
return cfg, nil
}

func configureNoForkAWSClient(ctx context.Context, c client.Client, mg resource.Managed, pc *v1beta1.ProviderConfig, ps *terraform.Setup) (xpprovider.AWSConfig, error) { //nolint:gocyclo
cfg, err := getAWSConfig(ctx, c, mg)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrap(err, "cannot get AWS config")
}

awsConfig := xpprovider.AWSConfig{
Region: cfg.Region,
TerraformVersion: ps.Version,
}

switch s := pc.Spec.Credentials.Source; s { //nolint:exhaustive
case authKeyWebIdentity:
if pc.Spec.Credentials.WebIdentity == nil {
return xpprovider.AWSConfig{}, errors.New(`spec.credentials.webIdentity of ProviderConfig cannot be nil when the credential source is "WebIdentity"`)
}
awsConfig.AssumeRoleWithWebIdentity = &tfawsbase.AssumeRoleWithWebIdentity{
RoleARN: aws.ToString(pc.Spec.Credentials.WebIdentity.RoleARN),
WebIdentityTokenFile: os.Getenv(envWebIdentityTokenFile),
}
if pc.Spec.Credentials.WebIdentity.RoleSessionName != "" {
awsConfig.AssumeRoleWithWebIdentity.SessionName = pc.Spec.Credentials.WebIdentity.RoleSessionName
}
case authKeyUpbound:
if pc.Spec.Credentials.Upbound == nil || pc.Spec.Credentials.Upbound.WebIdentity == nil {
return xpprovider.AWSConfig{}, errors.New(`spec.credentials.upbound.webIdentity of ProviderConfig cannot be nil when the credential source is "Upbound"`)
}
awsConfig.AssumeRoleWithWebIdentity = &tfawsbase.AssumeRoleWithWebIdentity{
RoleARN: aws.ToString(pc.Spec.Credentials.Upbound.WebIdentity.RoleARN),
WebIdentityTokenFile: upboundProviderIdentityTokenFile,
}

if pc.Spec.Credentials.Upbound.WebIdentity.RoleSessionName != "" {
awsConfig.AssumeRoleWithWebIdentity.SessionName = pc.Spec.Credentials.WebIdentity.RoleSessionName
}
case authKeySecret:
data, err := resource.CommonCredentialExtractor(ctx, s, c, pc.Spec.Credentials.CommonCredentialSelectors)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrap(err, "cannot get credentials")
}
cfgWithPs, err := UseProviderSecret(ctx, data, DefaultSection, cfg.Region)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrap(err, errAWSConfig)
}
creds, err := cfgWithPs.Credentials.Retrieve(ctx)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrap(err, "failed to retrieve aws credentials from aws config")
}

awsConfig.Region = cfgWithPs.Region
awsConfig.AccessKey = creds.AccessKeyID
awsConfig.SecretKey = creds.SecretAccessKey
awsConfig.Token = creds.SessionToken
}

if len(pc.Spec.AssumeRoleChain) != 0 {
credentials, err := cfg.Credentials.Retrieve(ctx)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrap(err, "failed to retrieve aws credentials from aws config")
}
awsConfig.Token = credentials.SessionToken
awsConfig.SecretKey = credentials.SecretAccessKey
awsConfig.AccessKey = credentials.AccessKeyID
}

if pc.Spec.Endpoint != nil {
if pc.Spec.Endpoint.URL.Static != nil {
if len(pc.Spec.Endpoint.Services) > 0 && *pc.Spec.Endpoint.URL.Static == "" {
return xpprovider.AWSConfig{}, errors.New("endpoint URL cannot be empty")
} else {
awsConfig.Endpoints = make(map[string]string)
for _, service := range pc.Spec.Endpoint.Services {
awsConfig.Endpoints[service] = aws.ToString(pc.Spec.Endpoint.URL.Static)
}
}
} else if pc.Spec.Endpoint.URL.Dynamic != nil && cfg.EndpointResolverWithOptions != nil {
for _, service := range pc.Spec.Endpoint.Services {
svcEndpoint, err := cfg.EndpointResolverWithOptions.ResolveEndpoint(service, cfg.Region, nil)
if err != nil {
return xpprovider.AWSConfig{}, errors.Wrapf(err, "cannot resolve dynamic endpoint URL for AWS service: %s", service)
}
awsConfig.Endpoints[service] = svcEndpoint.URL
}
}
func configureNoForkAWSClient(_ context.Context, ps *terraform.Setup, p schema.Provider) error { //nolint:gocyclo
// TODO: use context.WithoutCancel(ctx) after switching to Go >=1.21
diag := p.Configure(context.TODO(), &tfsdk.ResourceConfig{ //nolint:contextcheck
Config: ps.Configuration,
})
if diag != nil && diag.HasError() {
return errors.Errorf("failed to configure the provider: %v", diag)
}

awsConfig.SkipCredsValidation = pc.Spec.SkipCredsValidation
awsConfig.S3UsePathStyle = pc.Spec.S3UsePathStyle
awsConfig.SkipRegionValidation = pc.Spec.SkipRegionValidation
if pc.Spec.SkipMetadataApiCheck {
awsConfig.EC2MetadataServiceEnableState = imds.ClientDisabled
}
awsConfig.SkipRequestingAccountId = pc.Spec.SkipReqAccountId

return awsConfig, nil
ps.Meta = p.Meta()
return nil
}

0 comments on commit 7a61c51

Please sign in to comment.