From 4f391caef7283233b3b956ed38a06a6d19b00434 Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Sun, 17 Mar 2024 18:01:05 -0700 Subject: [PATCH 1/6] Add providerconfig field for specifying aws partition Signed-off-by: Matt Bush --- apis/v1beta1/types.go | 4 ++++ internal/clients/aws.go | 2 ++ package/crds/aws.upbound.io_providerconfigs.yaml | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/apis/v1beta1/types.go b/apis/v1beta1/types.go index 81b956080c..a154f767ab 100644 --- a/apis/v1beta1/types.go +++ b/apis/v1beta1/types.go @@ -21,6 +21,10 @@ type ProviderConfigSpec struct { // of AWS calls made by the provider. // +optional Endpoint *EndpointConfig `json:"endpoint,omitempty"` + // Partition defines the aws partition id to use when constructing ARNs. Most AWS regions use the commercial + // partition, simply named aws. + // +kubebuilder:default=aws + Partition string `json:"partition,omitempty"` // Whether to skip credentials validation via the STS API. // This can be useful for testing and for AWS API implementations that do not have STS available. // +optional diff --git a/internal/clients/aws.go b/internal/clients/aws.go index 13fa90b9ab..80b5be5a0f 100644 --- a/internal/clients/aws.go +++ b/internal/clients/aws.go @@ -25,6 +25,7 @@ import ( const ( keyAccountID = "account_id" + keyPartition = "partition" keyRegion = "region" ) @@ -64,6 +65,7 @@ func SelectTerraformSetup(config *SetupConfig) terraform.SetupFn { // nolint:goc } ps.ClientMetadata = map[string]string{ keyAccountID: account, + keyPartition: pc.Spec.Partition, } // several external name configs depend on the setup.Configuration for templating region ps.Configuration = map[string]any{ diff --git a/package/crds/aws.upbound.io_providerconfigs.yaml b/package/crds/aws.upbound.io_providerconfigs.yaml index fe521d4ff8..dcf02f7509 100644 --- a/package/crds/aws.upbound.io_providerconfigs.yaml +++ b/package/crds/aws.upbound.io_providerconfigs.yaml @@ -400,6 +400,12 @@ spec: required: - url type: object + partition: + default: aws + description: |- + Partition defines the aws partition id to use when constructing ARNs. Most AWS regions use the commercial + partition, simply named aws. + type: string s3_use_path_style: description: Whether to enable the request to use path-style addressing, i.e., https://s3.amazonaws.com/BUCKET/KEY. From 037458c161a1ce6e1dfd30846a287366bd92fb0b Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Sun, 17 Mar 2024 18:20:35 -0700 Subject: [PATCH 2/6] Refactor arns built through string interpolations to consider the partition Signed-off-by: Matt Bush --- config/externalname.go | 97 +++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/config/externalname.go b/config/externalname.go index 7ef6a5acf3..64a9a01fdb 100644 --- a/config/externalname.go +++ b/config/externalname.go @@ -94,7 +94,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // // ID is a random UUID. "aws_prometheus_workspace": config.IdentifierFromProvider, - "aws_prometheus_rule_group_namespace": config.TemplatedStringAsIdentifier("name", "arn:aws:aps:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:rulegroupsnamespace/{{ .parameters.workspace_id }}/{{ .external_name }}"), + "aws_prometheus_rule_group_namespace": config.TemplatedStringAsIdentifier("name", fullArnTemplate("aps", "rulegroupsnamespace/{{ .parameters.workspace_id }}/{{ .external_name }}")), // Uses the ID of workspace, workspace_id parameter. "aws_prometheus_alert_manager_definition": config.IdentifierFromProvider, @@ -141,7 +141,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // cloudtrail // // Cloudtrails can be imported using the name arn:aws:cloudtrail:us-west-1:153891904029:trail/foobar - "aws_cloudtrail": config.TemplatedStringAsIdentifier("name", "arn:aws:cloudtrail:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:trail/{{ .external_name }}"), + "aws_cloudtrail": config.TemplatedStringAsIdentifier("name", fullArnTemplate("cloudtrail", "trail/{{ .external_name }}")), // Event data stores can be imported using their arn "aws_cloudtrail_event_data_store": config.IdentifierFromProvider, @@ -419,9 +419,11 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // ecs // + // unlike all other resources, ecs cluster and service overwrite their external name configs in ecs/config.go. + // TODO: centralize the external name configs to this file. "aws_ecs_cluster": config.TemplatedStringAsIdentifier("name", "arn:aws:ecs:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:cluster/{{ .external_name }}"), "aws_ecs_service": config.NameAsIdentifier, - "aws_ecs_capacity_provider": config.TemplatedStringAsIdentifier("name", "arn:aws:ecs:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:capacity-provider/{{ .external_name }}"), + "aws_ecs_capacity_provider": config.TemplatedStringAsIdentifier("name", fullArnTemplate("ecs", "capacity-provider/{{ .external_name }}")), // Imported using ARN that has a random substring, revision at the end: // arn:aws:ecs:us-east-1:012345678910:task-definition/mytaskfamily:123 "aws_ecs_task_definition": config.IdentifierFromProvider, @@ -518,7 +520,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // each with their own name. // "aws_glue_partition_index": config.IdentifierFromProvider, // Imported using ARN: arn:aws:glue:us-west-2:123456789012:registry/example - "aws_glue_registry": config.TemplatedStringAsIdentifier("registry_name", "arn:aws:glue:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:registry/{{ .external_name }}"), + "aws_glue_registry": config.TemplatedStringAsIdentifier("registry_name", fullArnTemplate("glue", "registry/{{ .external_name }}")), // Glue Registries can be imported using arn // Example: arn:aws:glue:us-west-2:123456789012:schema/example/example "aws_glue_schema": config.IdentifierFromProvider, @@ -558,7 +560,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // No import "aws_iam_group_membership": config.IdentifierFromProvider, // IAM SAML Providers can be imported using the arn - "aws_iam_saml_provider": config.TemplatedStringAsIdentifier("name", "arn:aws:iam::{{ .setup.client_metadata.account_id }}:saml-provider/{{ .external_name }}"), + "aws_iam_saml_provider": config.TemplatedStringAsIdentifier("name", regionlessArnTemplate("iam", "saml-provider/{{ .external_name }}")), // IAM Server Certificates can be imported using the name "aws_iam_server_certificate": config.NameAsIdentifier, // IAM service-linked roles can be imported using role ARN that contains the @@ -899,14 +901,6 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // aws_dynamodb_tag can be imported by using the DynamoDB resource identifier and key, separated by a comma (,) "aws_dynamodb_tag": config.TemplatedStringAsIdentifier("", "{{ .parameters.resource_arn }},{{ .parameters.key }}"), - // sns - // - // SNS Topics can be imported using the topic arn - "aws_sns_topic": config.TemplatedStringAsIdentifier("name", "arn:aws:sns:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:{{ .external_name }}"), - // SNS Topic Subscriptions can be imported using the subscription arn that - // contains a random substring in the end. - "aws_sns_topic_subscription": config.IdentifierFromProvider, - // backup // // Backup Framework can be imported using the id which corresponds to the name of the Backup Framework @@ -955,18 +949,18 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // kinesis // // Even though the documentation says the ID is name, it uses ARN.. - "aws_kinesis_stream": config.TemplatedStringAsIdentifier("name", "arn:aws:kinesis:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:stream/{{ .external_name }}"), + "aws_kinesis_stream": config.TemplatedStringAsIdentifier("name", fullArnTemplate("kinesis", "stream/{{ .external_name }}")), // Kinesis Stream Consumers can be imported using the Amazon Resource Name (ARN) // that has a random substring. "aws_kinesis_stream_consumer": config.IdentifierFromProvider, // kinesisanalytics // - "aws_kinesis_analytics_application": config.TemplatedStringAsIdentifier("name", "arn:aws:kinesisanalytics:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:application/{{ .external_name }}"), + "aws_kinesis_analytics_application": config.TemplatedStringAsIdentifier("name", fullArnTemplate("kinesisanalytics", "application/{{ .external_name }}")), // kinesisanalyticsv2 // - "aws_kinesisanalyticsv2_application": config.TemplatedStringAsIdentifier("name", "arn:aws:kinesisanalytics:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:application/{{ .external_name }}"), + "aws_kinesisanalyticsv2_application": config.TemplatedStringAsIdentifier("name", fullArnTemplate("kinesisanalytics", "application/{{ .external_name }}")), // aws_kinesisanalyticsv2_application can be imported by using application_name together with snapshot_name // e.g. example-application/example-snapshot "aws_kinesisanalyticsv2_application_snapshot": FormattedIdentifierUserDefinedNameLast("snapshot_name", "/", "application_name"), @@ -1012,7 +1006,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // lambda // // Lambda Function Aliases are identified by their ARN, like arn:aws:lambda:eu-west-1:123456789012:function:lambda-function:alias - "aws_lambda_alias": config.TemplatedStringAsIdentifier("name", "arn:aws:lambda:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:function:{{ .parameters.function_name }}:{{ .external_name }}"), + "aws_lambda_alias": config.TemplatedStringAsIdentifier("name", fullArnTemplate("lambda", "function:{{ .parameters.function_name }}:{{ .external_name }}")), // Code Signing Configs can be imported using their ARN that has a random // substring in the end. // arn:aws:lambda:us-west-2:123456789012:code-signing-config:csc-0f6c334abcdea4d8b @@ -1226,8 +1220,8 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // sfn // - "aws_sfn_activity": config.TemplatedStringAsIdentifier("name", "arn:aws:states:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:activity/{{ .external_name }}"), - "aws_sfn_state_machine": config.TemplatedStringAsIdentifier("name", "arn:aws:states:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:stateMachine:{{ .external_name }}"), + "aws_sfn_activity": config.TemplatedStringAsIdentifier("name", fullArnTemplate("states", "activity/{{ .external_name }}")), + "aws_sfn_state_machine": config.TemplatedStringAsIdentifier("name", fullArnTemplate("states", "stateMachine:{{ .external_name }}")), // dax // @@ -1377,7 +1371,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // CodePipelines can be imported using the name "aws_codepipeline": config.NameAsIdentifier, // CodePipeline Webhooks can be imported by their ARN: arn:aws:codepipeline:us-west-2:123456789012:webhook:example - "aws_codepipeline_webhook": config.TemplatedStringAsIdentifier("name", "arn:aws:codepipeline:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:webhook:{{ .external_name }}"), + "aws_codepipeline_webhook": config.TemplatedStringAsIdentifier("name", fullArnTemplate("codepipeline", "webhook:{{ .external_name }}")), // CodeDeploy CustomActionType can be imported using the id "aws_codepipeline_custom_action_type": config.IdentifierFromProvider, @@ -1606,7 +1600,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // batch // // Batch Scheduling Policy can be imported using the arn: arn:aws:batch:us-east-1:123456789012:scheduling-policy/sample - "aws_batch_scheduling_policy": config.TemplatedStringAsIdentifier("name", "arn:aws:batch:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:scheduling-policy/{{ .external_name }}"), + "aws_batch_scheduling_policy": config.TemplatedStringAsIdentifier("name", fullArnTemplate("batch", "scheduling-policy/{{ .external_name }}")), // Batch Job Definition can be imported using ARN that has a random substring, revision at the end: // arn:aws:batch:us-east-1:123456789012:job-definition/sample:1 "aws_batch_job_definition": config.IdentifierFromProvider, @@ -1684,7 +1678,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // arn:aws:securityhub:eu-west-1:312940875350:action/custom/a // TODO: following configuration assumes the `a` in the above ARN // is the security hub custom action identifier - "aws_securityhub_action_target": config.TemplatedStringAsIdentifier("identifier", "arn:aws:securityhub:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:action/custom/{{ .external_name }}"), + "aws_securityhub_action_target": config.TemplatedStringAsIdentifier("identifier", fullArnTemplate("securityhub", "action/custom/{{ .external_name }}")), // imported using the arn that has a random substring: // arn:aws:securityhub:eu-west-1:123456789098:finding-aggregator/abcd1234-abcd-1234-1234-abcdef123456 "aws_securityhub_finding_aggregator": config.IdentifierFromProvider, @@ -1724,7 +1718,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // // config.NameAsIdentifier did not work, the identifier for the resource turned out to be an ARN // arn:aws:cloudformation:us-west-1:123456789123:stack/networking-stack/1e691240-6f2c-11ed-8f91-06094dc221f3 - "aws_cloudformation_stack": TemplatedStringAsIdentifierWithNoName("arn:aws:cloudformation:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:stack/{{ .parameters.name }}/{{ .external_name }}"), + "aws_cloudformation_stack": TemplatedStringAsIdentifierWithNoName(fullArnTemplate("cloudformation", "stack/{{ .parameters.name }}/{{ .external_name }}")), // CloudFormation StackSets can be imported using the name "aws_cloudformation_stack_set": config.NameAsIdentifier, // Cloudformation Stacks Instances imported using the StackSet name, target @@ -1834,19 +1828,24 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ // appflow // // arn:aws:appflow:us-west-2:123456789012:flow/example-flow - "aws_appflow_flow": config.TemplatedStringAsIdentifier("name", "arn:aws:appflow:{{ .setup.configuration.region }}:{{ .client_metadata.account_id }}:flow/{{ .external_name }}"), + "aws_appflow_flow": config.TemplatedStringAsIdentifier("name", fullArnTemplate("appflow", "flow/{{ .external_name }}")), // sns // // SNS platform applications can be imported using the ARN: // arn:aws:sns:us-west-2:0123456789012:app/GCM/gcm_application - "aws_sns_platform_application": config.TemplatedStringAsIdentifier("name", "arn:aws:sns:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:app/GCM/{{ .external_name }}"), + "aws_sns_platform_application": config.TemplatedStringAsIdentifier("name", fullArnTemplate("sns", "app/GCM/{{ .external_name }}")), // no import documentation is provided // TODO: we will need to check if normalization is possible "aws_sns_sms_preferences": config.IdentifierFromProvider, + // SNS Topics can be imported using the topic arn + "aws_sns_topic": config.TemplatedStringAsIdentifier("name", fullArnTemplate("sns", "{{ .external_name }}")), // SNS Topic Policy can be imported using the topic ARN: // arn:aws:sns:us-west-2:0123456789012:my-topic "aws_sns_topic_policy": FormattedIdentifierFromProvider("", "arn"), + // SNS Topic Subscriptions can be imported using the subscription arn that + // contains a random substring in the end. + "aws_sns_topic_subscription": config.IdentifierFromProvider, // servicecatalog // @@ -2133,7 +2132,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ "aws_iot_topic_rule": config.NameAsIdentifier, // IoT topic rule destinations can be imported using the arn // arn:aws:iot:us-west-2:123456789012:ruledestination/vpc/2ce781c8-68a6-4c52-9c62-63fe489ecc60 - "aws_iot_topic_rule_destination": TemplatedStringAsProviderDefinedIdentifier("arn:aws:iot:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:ruledestination/vpc/{{ .external_name }}"), + "aws_iot_topic_rule_destination": TemplatedStringAsProviderDefinedIdentifier(fullArnTemplate("iot", "ruledestination/vpc/{{ .external_name }}")), // sagemaker // @@ -2316,10 +2315,10 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ "aws_networkfirewall_firewall": config.IdentifierFromProvider, // Network Firewall Policies can be imported using their ARN // Example: arn:aws:network-firewall:us-west-1:123456789012:firewall-policy/example - "aws_networkfirewall_firewall_policy": config.TemplatedStringAsIdentifier("name", "arn:aws:network-firewall:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:firewall-policy/{{ .external_name }}"), + "aws_networkfirewall_firewall_policy": config.TemplatedStringAsIdentifier("name", fullArnTemplate("network-firewall", "firewall-policy/{{ .external_name }}")), // Network Firewall Rule Groups can be imported using their ARN // Example: arn:aws:network-firewall:us-west-1:123456789012:stateful-rulegroup/example - "aws_networkfirewall_rule_group": config.TemplatedStringAsIdentifier("", "arn:aws:network-firewall:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:{{ .parameters.type | ToLower }}-rulegroup/{{ .external_name }}"), + "aws_networkfirewall_rule_group": config.TemplatedStringAsIdentifier("", fullArnTemplate("network-firewall", "{{ .parameters.type | ToLower }}-rulegroup/{{ .external_name }}")), // Network Firewall Logging Configurations can be imported using the firewall_arn // Example: arn:aws:network-firewall:us-west-1:123456789012:firewall/example "aws_networkfirewall_logging_configuration": config.IdentifierFromProvider, @@ -2696,7 +2695,7 @@ var TerraformPluginSDKExternalNameConfigs = map[string]config.ExternalName{ "aws_evidently_project": config.IdentifierFromProvider, // CloudWatch Evidently Segment can be imported using the arn // Example: arn:aws:evidently:us-west-2:123456789012:segment/example - "aws_evidently_segment": config.TemplatedStringAsIdentifier("name", "arn:aws:evidently:{{ .setup.configuration.region }}:{{ .setup.client_metadata.account_id }}:segment/{{ .external_name }}"), + "aws_evidently_segment": config.TemplatedStringAsIdentifier("name", fullArnTemplate("evidently", "segment/{{ .external_name }}")), // fis // @@ -3169,3 +3168,43 @@ func eksPodIdentityAssociation() config.ExternalName { } return e } + +// fullArnTemplate builds a templated string for constructing a terraform id component which is an ARN, which includes +// the aws partition, service, region, account id, and resource. This is by far the most common form of ARN. +// e.g. arn:aws:ec2:ap-south-1:123456789012:instance/i-1234567890ab +func fullArnTemplate(service string, resource string) string { + return genericArnTemplate(service, resource, false, false) + +} + +// globalArnTemplate builds a templated string for constructing a terraform id component which is an ARN of a resource +// which is global to the entire AWS partition, including only the partition, service, and resource. +// e.g. arn:aws:s3:::name-of-my-bucket +func globalArnTemplate(service string, resource string) string { + return genericArnTemplate(service, resource, true, true) +} + +// regionlessArnTemplate builds a templated string for constructing a terraform id component which is an ARN of a +// resource which is regionless, but specific to your account id. It includes the partition, service, account id, and +// resource. +// e.g. arn:aws:iam::123456789012:role/example +func regionlessArnTemplate(service string, resource string) string { + return genericArnTemplate(service, resource, false, true) +} + +// genericArnTemplate builds a templated string for constructing a terraform id component which is an ARN of any format. +// It always includes the aws partition, service, and resource. Unless you specify to elide them, it will also include +// templates which resolve to the region (from the spec.forProvider) and the account id (calculated from the provider +// config). +func genericArnTemplate(service string, resource string, elideAccountId bool, elideRegion bool) string { + region := "{{ .setup.configuration.region }}" + if elideRegion { + region = "" + } + accountId := "{{ .setup.client_metadata.account_id }}" + if elideAccountId { + accountId = "" + } + partition := "{{ .setup.configuration.partition }}" + return fmt.Sprintf("arn:%s:%s:%s:%s:%s", partition, service, region, accountId, resource) +} From 955e2c528a3e351ae23556b56af46b20f8a45026 Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Sun, 17 Mar 2024 23:35:15 -0700 Subject: [PATCH 3/6] Use existing partition id Signed-off-by: Matt Bush --- apis/v1beta1/types.go | 4 ---- internal/clients/aws.go | 7 ++++++- package/crds/aws.upbound.io_providerconfigs.yaml | 6 ------ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/apis/v1beta1/types.go b/apis/v1beta1/types.go index a154f767ab..81b956080c 100644 --- a/apis/v1beta1/types.go +++ b/apis/v1beta1/types.go @@ -21,10 +21,6 @@ type ProviderConfigSpec struct { // of AWS calls made by the provider. // +optional Endpoint *EndpointConfig `json:"endpoint,omitempty"` - // Partition defines the aws partition id to use when constructing ARNs. Most AWS regions use the commercial - // partition, simply named aws. - // +kubebuilder:default=aws - Partition string `json:"partition,omitempty"` // Whether to skip credentials validation via the STS API. // This can be useful for testing and for AWS API implementations that do not have STS available. // +optional diff --git a/internal/clients/aws.go b/internal/clients/aws.go index 80b5be5a0f..161987e670 100644 --- a/internal/clients/aws.go +++ b/internal/clients/aws.go @@ -65,8 +65,13 @@ func SelectTerraformSetup(config *SetupConfig) terraform.SetupFn { // nolint:goc } ps.ClientMetadata = map[string]string{ keyAccountID: account, - keyPartition: pc.Spec.Partition, + keyPartition: "aws", } + + if pc.Spec.Endpoint != nil && pc.Spec.Endpoint.PartitionID != nil { + ps.ClientMetadata[keyPartition] = *pc.Spec.Endpoint.PartitionID + } + // several external name configs depend on the setup.Configuration for templating region ps.Configuration = map[string]any{ keyRegion: awsCfg.Region, diff --git a/package/crds/aws.upbound.io_providerconfigs.yaml b/package/crds/aws.upbound.io_providerconfigs.yaml index dcf02f7509..fe521d4ff8 100644 --- a/package/crds/aws.upbound.io_providerconfigs.yaml +++ b/package/crds/aws.upbound.io_providerconfigs.yaml @@ -400,12 +400,6 @@ spec: required: - url type: object - partition: - default: aws - description: |- - Partition defines the aws partition id to use when constructing ARNs. Most AWS regions use the commercial - partition, simply named aws. - type: string s3_use_path_style: description: Whether to enable the request to use path-style addressing, i.e., https://s3.amazonaws.com/BUCKET/KEY. From 7e59855a27d426d3a391b05d075f0db0748326bf Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Sun, 17 Mar 2024 23:36:21 -0700 Subject: [PATCH 4/6] Use appropriate IAM signing region for non-commercial partitions Signed-off-by: Matt Bush --- internal/clients/aws.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/clients/aws.go b/internal/clients/aws.go index 161987e670..0d37caac73 100644 --- a/internal/clients/aws.go +++ b/internal/clients/aws.go @@ -33,6 +33,15 @@ type SetupConfig struct { TerraformProvider *schema.Provider } +// iamRegions holds the region used for signing IAM credentials for each AWS partition. +var iamRegions = map[string]string{ + "aws": "us-east-1", + "aws-gov": "us-gov-west-1", + "aws-cn": "cn-northeast-1", + "aws-iso": "us-iso-east-1", + "aws-iosb": "us-isob-east-1", +} + func SelectTerraformSetup(config *SetupConfig) terraform.SetupFn { // nolint:gocyclo return func(ctx context.Context, c client.Client, mg resource.Managed) (terraform.Setup, error) { pc := &v1beta1.ProviderConfig{} @@ -105,11 +114,22 @@ func getAWSConfigWithDefaultRegion(ctx context.Context, c client.Client, obj run return nil, err } if cfg.Region == "" && obj.GetObjectKind().GroupVersionKind().Group == "iam.aws.upbound.io" { - cfg.Region = "us-east-1" + cfg.Region = getIAMRegion(pc) } return cfg, nil } +func getIAMRegion(pc *v1beta1.ProviderConfig) string { + defaultRegion := "us-east-1" + if pc == nil || pc.Spec.Endpoint == nil || pc.Spec.Endpoint.PartitionID == nil { + return defaultRegion + } + if region, ok := iamRegions[*pc.Spec.Endpoint.PartitionID]; ok { + return region + } + return defaultRegion +} + type metaOnlyPrimary struct { meta any } From 4e5030814d97dc1999b954a921386a0d4ab40578 Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Mon, 18 Mar 2024 11:21:53 -0700 Subject: [PATCH 5/6] remove unused function Signed-off-by: Matt Bush --- config/externalname.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/config/externalname.go b/config/externalname.go index 64a9a01fdb..bf6b875ae7 100644 --- a/config/externalname.go +++ b/config/externalname.go @@ -3177,13 +3177,6 @@ func fullArnTemplate(service string, resource string) string { } -// globalArnTemplate builds a templated string for constructing a terraform id component which is an ARN of a resource -// which is global to the entire AWS partition, including only the partition, service, and resource. -// e.g. arn:aws:s3:::name-of-my-bucket -func globalArnTemplate(service string, resource string) string { - return genericArnTemplate(service, resource, true, true) -} - // regionlessArnTemplate builds a templated string for constructing a terraform id component which is an ARN of a // resource which is regionless, but specific to your account id. It includes the partition, service, account id, and // resource. From 31e9c036b5659b9ce893198d058fa20204586c4f Mon Sep 17 00:00:00 2001 From: Matt Bush Date: Sun, 24 Mar 2024 14:12:35 -0700 Subject: [PATCH 6/6] Update build module Signed-off-by: Matt Bush --- build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build b/build index 75a9fe3ae6..f1fc264601 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 75a9fe3ae6b6de82c5f7ddc6a267617940f16b83 +Subproject commit f1fc264601a2293b39313e5e15573d87106ce172