Skip to content

feat: retrieve aws partition from callerIdentity #196

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

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
3 changes: 3 additions & 0 deletions apis/core/v1alpha1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ package v1alpha1
// AWSRegion represents an AWS regional identifier
type AWSRegion string

// AWSPartition represents an AWS partition identifier
type AWSPartition string

// AWSAccountID represents an AWS account identifier
type AWSAccountID string

Expand Down
2 changes: 2 additions & 0 deletions apis/core/v1alpha1/resource_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ type ResourceMetadata struct {
OwnerAccountID *AWSAccountID `json:"ownerAccountID"`
// Region is the AWS region in which the resource exists or will exist.
Region *AWSRegion `json:"region"`
// Partition is the AWS partition in which the resource exists or will exist
Partition *AWSPartition `json:"partition"`
}
20 changes: 20 additions & 0 deletions mocks/pkg/types/aws_resource_identifiers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 29 additions & 9 deletions mocks/pkg/types/aws_resource_manager_factory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 19 additions & 12 deletions mocks/pkg/types/service_controller.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions pkg/runtime/adoption_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,19 @@ func (r *adoptionReconciler) reconcile(ctx context.Context, req ctrlrt.Request)
targetDescriptor := rmf.ResourceDescriptor()
endpointURL := r.getEndpointURL(res)
gvk := targetDescriptor.GroupVersionKind()
partition := ""

awsconfig, err := r.sc.NewAWSConfig(ctx, region, &endpointURL, roleARN, gvk)
// The config pivot to the roleARN will happen if it is not empty.
// in the NewResourceManager
awsconfig, partition, err := r.sc.NewAWSConfig(ctx, region, &endpointURL, roleARN, gvk, partition)
if err != nil {
return err
}

ackrtlog.InfoAdoptedResource(r.log, res, "starting adoption reconciliation")

rm, err := rmf.ManagerFor(
r.cfg, awsconfig, r.log, r.metrics, r, acctID, region, roleARN,
r.cfg, awsconfig, r.log, r.metrics, r, acctID, region, ackv1alpha1.AWSPartition(partition), roleARN,
)
if err != nil {
return err
Expand Down
33 changes: 28 additions & 5 deletions pkg/runtime/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/aws/aws-sdk-go-v2/service/sts"
Expand Down Expand Up @@ -47,7 +48,8 @@ func (c *serviceController) NewAWSConfig(
endpointURL *string,
roleARN ackv1alpha1.AWSResourceName,
groupVersionKind schema.GroupVersionKind,
) (aws.Config, error) {
partition string,
) (aws.Config, string, error) {

val := formatUserAgent(
appName,
Expand All @@ -69,19 +71,25 @@ func (c *serviceController) NewAWSConfig(
config.WithHTTPClient(client),
)
if err != nil {
return awsCfg, err
return awsCfg, partition, err
}

if endpointURL != nil && *endpointURL != "" {
awsCfg.BaseEndpoint = endpointURL
}

stsclient := sts.NewFromConfig(awsCfg)
if roleARN != "" {
client := sts.NewFromConfig(awsCfg)
creds := stscreds.NewAssumeRoleProvider(client, string(roleARN))
creds := stscreds.NewAssumeRoleProvider(stsclient, string(roleARN))
awsCfg.Credentials = aws.NewCredentialsCache(creds)
}
return awsCfg, nil
if partition == "" {
partition, err = c.getPartition(ctx, stsclient)
if err != nil {
return awsCfg, partition, nil
}
}
return awsCfg, partition, nil
}

func formatUserAgent(name, version string, extra ...string) string {
Expand All @@ -91,3 +99,18 @@ func formatUserAgent(name, version string, extra ...string) string {
}
return ua
}

// getPartition gets the partition of the caller identity
func (c *serviceController) getPartition(ctx context.Context, client *sts.Client) (string, error) {
identity, err := client.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
// what od we do if ARN is nil?
if err != nil || identity.Arn == nil {
return "", err
}
clientArn, err := arn.Parse(*identity.Arn)
if err != nil {
return "", err
}

return clientArn.Partition, nil
}
41 changes: 30 additions & 11 deletions pkg/runtime/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,25 +262,30 @@ func (r *resourceReconciler) Reconcile(ctx context.Context, req ctrlrt.Request)
region := r.getRegion(desired)
endpointURL := r.getEndpointURL(desired)
gvk := r.rd.GroupVersionKind()
// The config pivot to the roleARN will happen if it is not empty.
// in the NewResourceManager
clientConfig, err := r.sc.NewAWSConfig(ctx, region, &endpointURL, roleARN, gvk)
if err != nil {
return ctrlrt.Result{}, err
}
partition := r.getPartition(desired)

rlog.WithValues(
"account", acctID,
"role", roleARN,
"region", region,
)

rm, err := r.rmf.ManagerFor(
r.cfg, clientConfig, r.log, r.metrics, r, acctID, region, roleARN,
)
if err != nil {
return ctrlrt.Result{}, err
rm := r.rmf.GetCachedManager(acctID, region, roleARN)
if rm == nil {
// The config pivot to the roleARN will happen if it is not empty.
// in the NewResourceManager
clientConfig, partition, err := r.sc.NewAWSConfig(ctx, region, &endpointURL, roleARN, gvk, partition)
if err != nil {
return ctrlrt.Result{}, err
}
rm, err = r.rmf.ManagerFor(
r.cfg, clientConfig, r.log, r.metrics, r, acctID, region, ackv1alpha1.AWSPartition(partition), roleARN,
)
if err != nil {
return ctrlrt.Result{}, err
}
}

latest, err := r.reconcile(ctx, rm, desired)
return r.HandleReconcileError(ctx, desired, latest, err)
}
Expand Down Expand Up @@ -1313,6 +1318,20 @@ func (r *resourceReconciler) getRegion(
return ackv1alpha1.AWSRegion(r.cfg.Region)
}

// getPartition attempts getting the partition from the resource status
// if it exists
func (r *resourceReconciler) getPartition(
res acktypes.AWSResource,
) string {
// first try to get the region from the status.resourceMetadata
metadataRegion := res.Identifiers().Partition()
if metadataRegion != nil {
return string(*metadataRegion)
}

return ""
}

// getDeletionPolicy returns the resource's deletion policy based on the default
// behaviour or any other overriding annotations.
//
Expand Down
2 changes: 2 additions & 0 deletions pkg/types/aws_resource_identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ type AWSResourceIdentifiers interface {
ARN() *ackv1alpha1.AWSResourceName
// Region is the AWS region in which the resource exists or will exist.
Region() *ackv1alpha1.AWSRegion
// Partition is the AWS partition in which the resource exists or will exist.
Partition() *ackv1alpha1.AWSPartition
}
8 changes: 8 additions & 0 deletions pkg/types/aws_resource_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,16 @@ type AWSResourceManagerFactory interface {
Reconciler,
ackv1alpha1.AWSAccountID,
ackv1alpha1.AWSRegion,
ackv1alpha1.AWSPartition,
ackv1alpha1.AWSResourceName,
) (AWSResourceManager, error)
// GetCachedManager returns an AWSResourceManager if it has previously been created
// and cahced, or returns nil if not
GetCachedManager(
ackv1alpha1.AWSAccountID,
ackv1alpha1.AWSRegion,
ackv1alpha1.AWSResourceName,
) AWSResourceManager
// IsAdoptable returns true if the resource is able to be adopted
IsAdoptable() bool
// RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds
Expand Down
3 changes: 2 additions & 1 deletion pkg/types/service_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ type ServiceController interface {
*string,
ackv1alpha1.AWSResourceName,
schema.GroupVersionKind,
) (aws.Config, error)
string,
) (aws.Config, string, error)

// GetMetadata returns the metadata associated with the service controller.
GetMetadata() ServiceControllerMetadata
Expand Down