diff --git a/.changelog/37092.txt b/.changelog/37092.txt new file mode 100644 index 000000000000..11304787baaf --- /dev/null +++ b/.changelog/37092.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_kms_custom_key_store: Change `trust_anchor_certificate` to [ForceNew](https://developer.hashicorp.com/terraform/plugin/sdkv2/schemas/schema-behaviors#forcenew) +``` \ No newline at end of file diff --git a/go.mod b/go.mod index eeb36c40d312..5789ea3fe1fc 100644 --- a/go.mod +++ b/go.mod @@ -103,6 +103,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/kendra v1.50.1 github.com/aws/aws-sdk-go-v2/service/keyspaces v1.10.4 github.com/aws/aws-sdk-go-v2/service/kinesis v1.27.4 + github.com/aws/aws-sdk-go-v2/service/kms v1.31.0 github.com/aws/aws-sdk-go-v2/service/lakeformation v1.32.0 github.com/aws/aws-sdk-go-v2/service/lambda v1.54.0 github.com/aws/aws-sdk-go-v2/service/launchwizard v1.3.4 diff --git a/go.sum b/go.sum index b9b73619aa8c..a79ccc216b51 100644 --- a/go.sum +++ b/go.sum @@ -236,6 +236,8 @@ github.com/aws/aws-sdk-go-v2/service/keyspaces v1.10.4 h1:b8U8xht0BhuuzDlKUq/QzB github.com/aws/aws-sdk-go-v2/service/keyspaces v1.10.4/go.mod h1:K0uQVx8xnUBI3CudcERApORx5cJrVUDew1K3deRDjLU= github.com/aws/aws-sdk-go-v2/service/kinesis v1.27.4 h1:Oe8awBiS/iitcsRJB5+DHa3iCxoA0KwJJf0JNrYMINY= github.com/aws/aws-sdk-go-v2/service/kinesis v1.27.4/go.mod h1:RCZCSFbieSgNG1RKegO26opXV4EXyef/vNBVJsUyHuw= +github.com/aws/aws-sdk-go-v2/service/kms v1.31.0 h1:yl7wcqbisxPzknJVfWTLnK83McUvXba+pz2+tPbIUmQ= +github.com/aws/aws-sdk-go-v2/service/kms v1.31.0/go.mod h1:2snWQJQUKsbN66vAawJuOGX7dr37pfOq9hb0tZDGIqQ= github.com/aws/aws-sdk-go-v2/service/lakeformation v1.32.0 h1:X7ydA78B8lmKVgGS3XEVUsgMKMHoYhmIwoxl3U2S2wg= github.com/aws/aws-sdk-go-v2/service/lakeformation v1.32.0/go.mod h1:0xTSto0XwDuPvY7P3XoEwOLH7sr5EzehNvxCoBaeuPU= github.com/aws/aws-sdk-go-v2/service/lambda v1.54.0 h1:gazALVrZ7RIG6gJXut3c7NKtPgs9eQ8BFCA9uoliayk= diff --git a/internal/conns/awsclient.go b/internal/conns/awsclient.go index e9ce0525daf8..5dff89d6694a 100644 --- a/internal/conns/awsclient.go +++ b/internal/conns/awsclient.go @@ -21,7 +21,6 @@ import ( directoryservice_sdkv1 "github.com/aws/aws-sdk-go/service/directoryservice" dynamodb_sdkv1 "github.com/aws/aws-sdk-go/service/dynamodb" efs_sdkv1 "github.com/aws/aws-sdk-go/service/efs" - kms_sdkv1 "github.com/aws/aws-sdk-go/service/kms" opsworks_sdkv1 "github.com/aws/aws-sdk-go/service/opsworks" rds_sdkv1 "github.com/aws/aws-sdk-go/service/rds" baselogging "github.com/hashicorp/aws-sdk-go-base/v2/logging" @@ -95,17 +94,7 @@ func (c *AWSClient) EFSConnForRegion(ctx context.Context, region string) *efs_sd return efs_sdkv1.New(c.session, aws_sdkv1.NewConfig().WithRegion(region)) } -// KMSConnForRegion returns an AWS SDK For Go v1 KMS API client for the specified AWS Region. -// If the specified region is not the default a new "simple" client is created. -// This new client does not use any configured endpoint override. -func (c *AWSClient) KMSConnForRegion(ctx context.Context, region string) *kms_sdkv1.KMS { - if region == c.Region { - return c.KMSConn(ctx) - } - return kms_sdkv1.New(c.session, aws_sdkv1.NewConfig().WithRegion(region)) -} - -// KMSConnForRegion returns an AWS SDK For Go v1 OpsWorks API client for the specified AWS Region. +// OpsWorksConnForRegion returns an AWS SDK For Go v1 OpsWorks API client for the specified AWS Region. // If the specified region is not the default a new "simple" client is created. // This new client does not use any configured endpoint override. func (c *AWSClient) OpsWorksConnForRegion(ctx context.Context, region string) *opsworks_sdkv1.OpsWorks { diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 42636edf2823..b3ac1cd5f4a9 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -95,6 +95,7 @@ import ( kendra_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kendra" keyspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/keyspaces" kinesis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kinesis" + kms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kms" lakeformation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lakeformation" lambda_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lambda" launchwizard_sdkv2 "github.com/aws/aws-sdk-go-v2/service/launchwizard" @@ -211,7 +212,6 @@ import ( kinesisanalytics_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisanalytics" kinesisanalyticsv2_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisanalyticsv2" kinesisvideo_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisvideo" - kms_sdkv1 "github.com/aws/aws-sdk-go/service/kms" lexmodelbuildingservice_sdkv1 "github.com/aws/aws-sdk-go/service/lexmodelbuildingservice" licensemanager_sdkv1 "github.com/aws/aws-sdk-go/service/licensemanager" locationservice_sdkv1 "github.com/aws/aws-sdk-go/service/locationservice" @@ -771,8 +771,8 @@ func (c *AWSClient) IoTEventsConn(ctx context.Context) *iotevents_sdkv1.IoTEvent return errs.Must(conn[*iotevents_sdkv1.IoTEvents](ctx, c, names.IoTEvents, make(map[string]any))) } -func (c *AWSClient) KMSConn(ctx context.Context) *kms_sdkv1.KMS { - return errs.Must(conn[*kms_sdkv1.KMS](ctx, c, names.KMS, make(map[string]any))) +func (c *AWSClient) KMSClient(ctx context.Context) *kms_sdkv2.Client { + return errs.Must(client[*kms_sdkv2.Client](ctx, c, names.KMS, make(map[string]any))) } func (c *AWSClient) KafkaClient(ctx context.Context) *kafka_sdkv2.Client { diff --git a/internal/flex/flex.go b/internal/flex/flex.go index 29157ccc2685..81c9cbe7c7d2 100644 --- a/internal/flex/flex.go +++ b/internal/flex/flex.go @@ -238,6 +238,12 @@ func FlattenStringMap(m map[string]*string) map[string]interface{} { }) } +func FlattenStringValueMap(m map[string]string) map[string]interface{} { + return tfmaps.ApplyToAllValues(m, func(v string) any { + return v + }) +} + // Takes the result of schema.Set of strings and returns a []*int64 func ExpandInt64Set(configured *schema.Set) []*int64 { return ExpandInt64List(configured.List()) diff --git a/internal/service/cloudfront/distribution.go b/internal/service/cloudfront/distribution.go index 1c3edf6f9101..1d2bb493ddb3 100644 --- a/internal/service/cloudfront/distribution.go +++ b/internal/service/cloudfront/distribution.go @@ -1084,7 +1084,7 @@ func resourceDistributionDelete(ctx context.Context, d *schema.ResourceData, met const ( timeout = 1 * time.Minute ) - _, err = tfresource.RetryWhenIsOneOf[*awstypes.PreconditionFailed, *awstypes.InvalidIfMatchVersion](ctx, timeout, func() (interface{}, error) { + _, err = tfresource.RetryWhenIsOneOf2[*awstypes.PreconditionFailed, *awstypes.InvalidIfMatchVersion](ctx, timeout, func() (interface{}, error) { return nil, deleteDistribution(ctx, conn, d.Id()) }) } diff --git a/internal/service/dynamodb/table.go b/internal/service/dynamodb/table.go index 16479ad956ed..61c966606d58 100644 --- a/internal/service/dynamodb/table.go +++ b/internal/service/dynamodb/table.go @@ -1875,7 +1875,7 @@ func clearSSEDefaultKey(ctx context.Context, client *conns.AWSClient, sseList [] sse := sseList[0].(map[string]interface{}) - dk, err := kms.FindDefaultKey(ctx, client, "dynamodb", client.Region) + dk, err := kms.FindDefaultKeyARNForService(ctx, client.KMSClient(ctx), "dynamodb", client.Region) if err != nil { return sseList } @@ -1906,7 +1906,7 @@ func clearReplicaDefaultKeys(ctx context.Context, client *conns.AWSClient, repli continue } - dk, err := kms.FindDefaultKey(ctx, client, "dynamodb", replica["region_name"].(string)) + dk, err := kms.FindDefaultKeyARNForService(ctx, client.KMSClient(ctx), "dynamodb", replica["region_name"].(string)) if err != nil { continue } diff --git a/internal/service/dynamodb/table_replica.go b/internal/service/dynamodb/table_replica.go index a80c58fbffa4..1da5e0d94d77 100644 --- a/internal/service/dynamodb/table_replica.go +++ b/internal/service/dynamodb/table_replica.go @@ -247,7 +247,7 @@ func resourceTableReplicaRead(ctx context.Context, d *schema.ResourceData, meta return create.AppendDiagError(diags, names.DynamoDB, create.ErrActionReading, ResNameTableReplica, d.Id(), err) } - dk, err := kms.FindDefaultKey(ctx, meta.(*conns.AWSClient), "dynamodb", replicaRegion) + dk, err := kms.FindDefaultKeyARNForService(ctx, meta.(*conns.AWSClient).KMSClient(ctx), "dynamodb", replicaRegion) if err != nil { return create.AppendDiagError(diags, names.DynamoDB, create.ErrActionReading, ResNameTableReplica, d.Id(), err) } @@ -363,7 +363,7 @@ func resourceTableReplicaUpdate(ctx context.Context, d *schema.ResourceData, met } if d.HasChange(names.AttrKMSKeyARN) && !d.IsNewResource() { // create ends with update and sets kms_key_arn causing change that is not - dk, err := kms.FindDefaultKey(ctx, meta.(*conns.AWSClient), "dynamodb", replicaRegion) + dk, err := kms.FindDefaultKeyARNForService(ctx, meta.(*conns.AWSClient).KMSClient(ctx), "dynamodb", replicaRegion) if err != nil { return create.AppendDiagError(diags, names.DynamoDB, create.ErrActionUpdating, ResNameTableReplica, d.Id(), fmt.Errorf("region %s: %w", replicaRegion, err)) } diff --git a/internal/service/ec2/ebs_default_kms_key_test.go b/internal/service/ec2/ebs_default_kms_key_test.go index a9923f1eb577..2343ea477cf8 100644 --- a/internal/service/ec2/ebs_default_kms_key_test.go +++ b/internal/service/ec2/ebs_default_kms_key_test.go @@ -103,7 +103,7 @@ func testAccCheckEBSDefaultKMSKey(ctx context.Context, name string) resource.Tes // testAccEBSManagedDefaultKey returns' the account's AWS-managed default CMK. func testAccEBSManagedDefaultKey(ctx context.Context) (*arn.ARN, error) { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) alias, err := tfkms.FindAliasByName(ctx, conn, "alias/aws/ebs") if err != nil { diff --git a/internal/service/kms/alias.go b/internal/service/kms/alias.go index bec4e842d253..6e6b0b182d43 100644 --- a/internal/service/kms/alias.go +++ b/internal/service/kms/alias.go @@ -7,19 +7,21 @@ import ( "context" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -// @SDKResource("aws_kms_alias") -func ResourceAlias() *schema.Resource { +// @SDKResource("aws_kms_alias", name="Alias") +func resourceAlias() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceAliasCreate, ReadWithoutTimeout: resourceAliasRead, @@ -35,7 +37,6 @@ func ResourceAlias() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "name": { Type: schema.TypeString, Optional: true, @@ -44,7 +45,6 @@ func ResourceAlias() *schema.Resource { ConflictsWith: []string{"name_prefix"}, ValidateFunc: validNameForResource, }, - "name_prefix": { Type: schema.TypeString, Optional: true, @@ -53,12 +53,10 @@ func ResourceAlias() *schema.Resource { ConflictsWith: []string{"name"}, ValidateFunc: validNameForResource, }, - "target_key_arn": { Type: schema.TypeString, Computed: true, }, - "target_key_id": { Type: schema.TypeString, Required: true, @@ -70,25 +68,21 @@ func ResourceAlias() *schema.Resource { func resourceAliasCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) namePrefix := d.Get("name_prefix").(string) if namePrefix == "" { - namePrefix = AliasNamePrefix + namePrefix = aliasNamePrefix } name := create.Name(d.Get("name").(string), namePrefix) - input := &kms.CreateAliasInput{ AliasName: aws.String(name), TargetKeyId: aws.String(d.Get("target_key_id").(string)), } - // KMS is eventually consistent. - log.Printf("[DEBUG] Creating KMS Alias: %s", input) - - _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, KeyRotationUpdatedTimeout, func() (interface{}, error) { - return conn.CreateAliasWithContext(ctx, input) - }, kms.ErrCodeNotFoundException) + _, err := tfresource.RetryWhenIsA[*awstypes.NotFoundException](ctx, keyRotationUpdatedTimeout, func() (interface{}, error) { + return conn.CreateAlias(ctx, input) + }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS Alias (%s): %s", name, err) @@ -101,10 +95,10 @@ func resourceAliasCreate(ctx context.Context, d *schema.ResourceData, meta inter func resourceAliasRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) - outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return FindAliasByName(ctx, conn, d.Id()) + outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, kmsPropagationTimeout, func() (interface{}, error) { + return findAliasByName(ctx, conn, d.Id()) }, d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -117,17 +111,17 @@ func resourceAliasRead(ctx context.Context, d *schema.ResourceData, meta interfa return sdkdiag.AppendErrorf(diags, "reading KMS Alias (%s): %s", d.Id(), err) } - alias := outputRaw.(*kms.AliasListEntry) - aliasARN := aws.StringValue(alias.AliasArn) - targetKeyID := aws.StringValue(alias.TargetKeyId) - targetKeyARN, err := AliasARNToKeyARN(aliasARN, targetKeyID) + alias := outputRaw.(*awstypes.AliasListEntry) + aliasARN := aws.ToString(alias.AliasArn) + targetKeyID := aws.ToString(alias.TargetKeyId) + targetKeyARN, err := aliasARNToKeyARN(aliasARN, targetKeyID) if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Alias (%s): %s", d.Id(), err) } d.Set("arn", aliasARN) d.Set("name", alias.AliasName) - d.Set("name_prefix", create.NamePrefixFromName(aws.StringValue(alias.AliasName))) + d.Set("name_prefix", create.NamePrefixFromName(aws.ToString(alias.AliasName))) d.Set("target_key_arn", targetKeyARN) d.Set("target_key_id", targetKeyID) @@ -136,7 +130,7 @@ func resourceAliasRead(ctx context.Context, d *schema.ResourceData, meta interfa func resourceAliasUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) if d.HasChange("target_key_id") { input := &kms.UpdateAliasInput{ @@ -144,8 +138,7 @@ func resourceAliasUpdate(ctx context.Context, d *schema.ResourceData, meta inter TargetKeyId: aws.String(d.Get("target_key_id").(string)), } - log.Printf("[DEBUG] Updating KMS Alias: %s", input) - _, err := conn.UpdateAliasWithContext(ctx, input) + _, err := conn.UpdateAlias(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating KMS Alias (%s): %s", d.Id(), err) @@ -157,14 +150,14 @@ func resourceAliasUpdate(ctx context.Context, d *schema.ResourceData, meta inter func resourceAliasDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) - log.Printf("[DEBUG] Deleting KMS Alias: (%s)", d.Id()) - _, err := conn.DeleteAliasWithContext(ctx, &kms.DeleteAliasInput{ + log.Printf("[DEBUG] Deleting KMS Alias: %s", d.Id()) + _, err := conn.DeleteAlias(ctx, &kms.DeleteAliasInput{ AliasName: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } @@ -175,6 +168,45 @@ func resourceAliasDelete(ctx context.Context, d *schema.ResourceData, meta inter return diags } +func findAliasByName(ctx context.Context, conn *kms.Client, name string) (*awstypes.AliasListEntry, error) { + input := &kms.ListAliasesInput{} + + return findAlias(ctx, conn, input, func(v *awstypes.AliasListEntry) bool { + return aws.ToString(v.AliasName) == name + }) +} + +func findAlias(ctx context.Context, conn *kms.Client, input *kms.ListAliasesInput, filter tfslices.Predicate[*awstypes.AliasListEntry]) (*awstypes.AliasListEntry, error) { + output, err := findAliases(ctx, conn, input, filter) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output) +} + +func findAliases(ctx context.Context, conn *kms.Client, input *kms.ListAliasesInput, filter tfslices.Predicate[*awstypes.AliasListEntry]) ([]awstypes.AliasListEntry, error) { + var output []awstypes.AliasListEntry + + pages := kms.NewListAliasesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + return output, err + } + + for _, v := range page.Aliases { + if filter(&v) { + output = append(output, v) + } + } + } + + return output, nil +} + func suppressEquivalentKeyARNOrID(k, old, new string, d *schema.ResourceData) bool { - return KeyARNOrIDEqual(old, new) + return keyARNOrIDEqual(old, new) } diff --git a/internal/service/kms/alias_data_source.go b/internal/service/kms/alias_data_source.go index a1c89de5ba98..9f17ea26277f 100644 --- a/internal/service/kms/alias_data_source.go +++ b/internal/service/kms/alias_data_source.go @@ -13,10 +13,11 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" ) -// @SDKDataSource("aws_kms_alias") -func DataSourceAlias() *schema.Resource { +// @SDKDataSource("aws_kms_alias", name="Alias") +func dataSourceAlias() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceAliasRead, + Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, @@ -41,11 +42,10 @@ func DataSourceAlias() *schema.Resource { func dataSourceAliasRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) target := d.Get("name").(string) - - alias, err := FindAliasByName(ctx, conn, target) + alias, err := findAliasByName(ctx, conn, target) if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Alias (%s): %s", target, err) @@ -65,7 +65,7 @@ func dataSourceAliasRead(ctx context.Context, d *schema.ResourceData, meta inter // // https://docs.aws.amazon.com/kms/latest/APIReference/API_ListAliases.html - keyMetadata, err := FindKeyByID(ctx, conn, target) + keyMetadata, err := findKeyByID(ctx, conn, target) if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Key (%s): %s", target, err) diff --git a/internal/service/kms/alias_test.go b/internal/service/kms/alias_test.go index 7a2614ecc129..a43b96c3c8b7 100644 --- a/internal/service/kms/alias_test.go +++ b/internal/service/kms/alias_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -23,7 +23,7 @@ import ( func TestAccKMSAlias_basic(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" keyResourceName := "aws_kms_key.test" @@ -55,7 +55,7 @@ func TestAccKMSAlias_basic(t *testing.T) { func TestAccKMSAlias_disappears(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" @@ -79,7 +79,7 @@ func TestAccKMSAlias_disappears(t *testing.T) { func TestAccKMSAlias_Name_generated(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" @@ -108,7 +108,7 @@ func TestAccKMSAlias_Name_generated(t *testing.T) { func TestAccKMSAlias_namePrefix(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" @@ -137,7 +137,7 @@ func TestAccKMSAlias_namePrefix(t *testing.T) { func TestAccKMSAlias_updateKeyID(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" key1ResourceName := "aws_kms_key.test" @@ -176,7 +176,7 @@ func TestAccKMSAlias_updateKeyID(t *testing.T) { func TestAccKMSAlias_multipleAliasesForSameKey(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" alias2ResourceName := "aws_kms_alias.test2" @@ -210,7 +210,7 @@ func TestAccKMSAlias_multipleAliasesForSameKey(t *testing.T) { func TestAccKMSAlias_arnDiffSuppress(t *testing.T) { ctx := acctest.Context(t) - var alias kms.AliasListEntry + var alias awstypes.AliasListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_alias.test" @@ -243,7 +243,7 @@ func TestAccKMSAlias_arnDiffSuppress(t *testing.T) { func testAccCheckAliasDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_kms_alias" { @@ -267,18 +267,14 @@ func testAccCheckAliasDestroy(ctx context.Context) resource.TestCheckFunc { } } -func testAccCheckAliasExists(ctx context.Context, name string, v *kms.AliasListEntry) resource.TestCheckFunc { +func testAccCheckAliasExists(ctx context.Context, n string, v *awstypes.AliasListEntry) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", name) + return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No KMS Alias ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) output, err := tfkms.FindAliasByName(ctx, conn, rs.Primary.ID) diff --git a/internal/service/kms/arn.go b/internal/service/kms/arn.go index 078f24f72eee..72ed3d503811 100644 --- a/internal/service/kms/arn.go +++ b/internal/service/kms/arn.go @@ -7,23 +7,23 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go-v2/aws/arn" ) const ( - ARNSeparator = "/" - ARNService = "kms" + arnResourceSeparator = "/" + arnService = "kms" ) -// AliasARNToKeyARN converts an alias ARN to a CMK ARN. -func AliasARNToKeyARN(inputARN, keyID string) (string, error) { +// aliasARNToKeyARN converts an alias ARN to a CMK ARN. +func aliasARNToKeyARN(inputARN, keyID string) (string, error) { parsedARN, err := arn.Parse(inputARN) if err != nil { return "", fmt.Errorf("parsing ARN (%s): %w", inputARN, err) } - if actual, expected := parsedARN.Service, ARNService; actual != expected { + if actual, expected := parsedARN.Service, arnService; actual != expected { return "", fmt.Errorf("expected service %s in ARN (%s), got: %s", expected, inputARN, actual) } @@ -32,14 +32,14 @@ func AliasARNToKeyARN(inputARN, keyID string) (string, error) { Service: parsedARN.Service, Region: parsedARN.Region, AccountID: parsedARN.AccountID, - Resource: strings.Join([]string{"key", keyID}, ARNSeparator), + Resource: strings.Join([]string{"key", keyID}, arnResourceSeparator), }.String() return outputARN, nil } -// KeyARNOrIDEqual returns whether two CMK ARNs or IDs are equal. -func KeyARNOrIDEqual(arnOrID1, arnOrID2 string) bool { +// keyARNOrIDEqual returns whether two CMK ARNs or IDs are equal. +func keyARNOrIDEqual(arnOrID1, arnOrID2 string) bool { if arnOrID1 == arnOrID2 { return true } diff --git a/internal/service/kms/arn_test.go b/internal/service/kms/arn_test.go index 77740fb962db..048f1492aa06 100644 --- a/internal/service/kms/arn_test.go +++ b/internal/service/kms/arn_test.go @@ -1,14 +1,13 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package kms_test +package kms import ( "regexp" "testing" "github.com/YakDriver/regexache" - tfkms "github.com/hashicorp/terraform-provider-aws/internal/service/kms" ) func TestAliasARNToKeyARN(t *testing.T) { @@ -47,7 +46,7 @@ func TestAliasARNToKeyARN(t *testing.T) { t.Run(testCase.TestName, func(t *testing.T) { t.Parallel() - got, err := tfkms.AliasARNToKeyARN(testCase.InputARN, "test-key") + got, err := aliasARNToKeyARN(testCase.InputARN, "test-key") if err == nil && testCase.ExpectedError != nil { t.Fatalf("expected error %s, got no error", testCase.ExpectedError.String()) @@ -139,7 +138,7 @@ func TestKeyARNOrIDEqual(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - got := tfkms.KeyARNOrIDEqual(testCase.first, testCase.second) + got := keyARNOrIDEqual(testCase.first, testCase.second) if got != testCase.want { t.Errorf("unexpected Equal: %t", got) diff --git a/internal/service/kms/ciphertext.go b/internal/service/kms/ciphertext.go index 1a15eb68d81d..6bd84785c8e7 100644 --- a/internal/service/kms/ciphertext.go +++ b/internal/service/kms/ciphertext.go @@ -7,8 +7,8 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -17,8 +17,8 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) -// @SDKResource("aws_kms_ciphertext") -func ResourceCiphertext() *schema.Resource { +// @SDKResource("aws_kms_ciphertext", name="Ciphertext") +func resourceCiphertext() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceCiphertextCreate, ReadWithoutTimeout: schema.NoopContext, @@ -32,8 +32,8 @@ func ResourceCiphertext() *schema.Resource { "context": { Type: schema.TypeMap, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "key_id": { Type: schema.TypeString, @@ -52,7 +52,7 @@ func ResourceCiphertext() *schema.Resource { func resourceCiphertextCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) keyID := d.Get("key_id").(string) input := &kms.EncryptInput{ @@ -61,10 +61,10 @@ func resourceCiphertextCreate(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("context"); ok && len(v.(map[string]interface{})) > 0 { - input.EncryptionContext = flex.ExpandStringMap(v.(map[string]interface{})) + input.EncryptionContext = flex.ExpandStringValueMap(v.(map[string]interface{})) } - output, err := conn.EncryptWithContext(ctx, input) + output, err := conn.Encrypt(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "encrypting with KMS Key (%s): %s", keyID, err) diff --git a/internal/service/kms/ciphertext_data_source.go b/internal/service/kms/ciphertext_data_source.go index b611b717ac04..e23cdd083fe4 100644 --- a/internal/service/kms/ciphertext_data_source.go +++ b/internal/service/kms/ciphertext_data_source.go @@ -6,8 +6,8 @@ package kms import ( "context" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -16,8 +16,8 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) -// @SDKDataSource("aws_kms_ciphertext") -func DataSourceCiphertext() *schema.Resource { +// @SDKDataSource("aws_kms_ciphertext", name="Ciphertext") +func dataSourceCiphertext() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceCiphertextRead, @@ -46,7 +46,7 @@ func DataSourceCiphertext() *schema.Resource { func dataSourceCiphertextRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) keyID := d.Get("key_id").(string) input := &kms.EncryptInput{ @@ -55,16 +55,16 @@ func dataSourceCiphertextRead(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("context"); ok && len(v.(map[string]interface{})) > 0 { - input.EncryptionContext = flex.ExpandStringMap(v.(map[string]interface{})) + input.EncryptionContext = flex.ExpandStringValueMap(v.(map[string]interface{})) } - output, err := conn.EncryptWithContext(ctx, input) + output, err := conn.Encrypt(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "encrypting with KMS Key (%s): %s", keyID, err) } - d.SetId(aws.StringValue(output.KeyId)) + d.SetId(aws.ToString(output.KeyId)) d.Set("ciphertext_blob", itypes.Base64Encode(output.CiphertextBlob)) return diags diff --git a/internal/service/kms/ciphertext_data_source_test.go b/internal/service/kms/ciphertext_data_source_test.go index 1a298cb55fe3..19da5fc808d5 100644 --- a/internal/service/kms/ciphertext_data_source_test.go +++ b/internal/service/kms/ciphertext_data_source_test.go @@ -13,6 +13,7 @@ import ( func TestAccKMSCiphertextDataSource_basic(t *testing.T) { ctx := acctest.Context(t) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -22,7 +23,7 @@ func TestAccKMSCiphertextDataSource_basic(t *testing.T) { Config: testAccCiphertextDataSourceConfig_basic, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "data.aws_kms_ciphertext.foo", "ciphertext_blob"), + "data.aws_kms_ciphertext.test", "ciphertext_blob"), ), }, }, @@ -31,6 +32,7 @@ func TestAccKMSCiphertextDataSource_basic(t *testing.T) { func TestAccKMSCiphertextDataSource_validate(t *testing.T) { ctx := acctest.Context(t) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -40,7 +42,7 @@ func TestAccKMSCiphertextDataSource_validate(t *testing.T) { Config: testAccCiphertextDataSourceConfig_validate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "data.aws_kms_ciphertext.foo", "ciphertext_blob"), + "data.aws_kms_ciphertext.test", "ciphertext_blob"), ), }, }, @@ -49,6 +51,7 @@ func TestAccKMSCiphertextDataSource_validate(t *testing.T) { func TestAccKMSCiphertextDataSource_Validate_withContext(t *testing.T) { ctx := acctest.Context(t) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -58,7 +61,7 @@ func TestAccKMSCiphertextDataSource_Validate_withContext(t *testing.T) { Config: testAccCiphertextDataSourceConfig_validateContext, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "data.aws_kms_ciphertext.foo", "ciphertext_blob"), + "data.aws_kms_ciphertext.test", "ciphertext_blob"), ), }, }, @@ -66,39 +69,39 @@ func TestAccKMSCiphertextDataSource_Validate_withContext(t *testing.T) { } const testAccCiphertextDataSourceConfig_basic = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-basic" is_enabled = true } -data "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +data "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" } ` const testAccCiphertextDataSourceConfig_validate = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-validate" is_enabled = true } -data "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +data "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" } ` const testAccCiphertextDataSourceConfig_validateContext = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-validate-with-context" is_enabled = true } -data "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +data "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" diff --git a/internal/service/kms/ciphertext_test.go b/internal/service/kms/ciphertext_test.go index 98dad54f10d8..d9b44ffedd99 100644 --- a/internal/service/kms/ciphertext_test.go +++ b/internal/service/kms/ciphertext_test.go @@ -11,35 +11,36 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccKMSCiphertext_Resource_basic(t *testing.T) { +func TestAccKMSCiphertext_basic(t *testing.T) { ctx := acctest.Context(t) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: nil, + CheckDestroy: acctest.CheckDestroyNoop, Steps: []resource.TestStep{ { Config: testAccCiphertextConfig_basic, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "aws_kms_ciphertext.foo", "ciphertext_blob"), + "aws_kms_ciphertext.test", "ciphertext_blob"), ), }, }, }) } -func TestAccKMSCiphertext_Resource_validate(t *testing.T) { +func TestAccKMSCiphertext_validate(t *testing.T) { ctx := acctest.Context(t) - kmsSecretsDataSource := "data.aws_kms_secrets.foo" - resourceName := "aws_kms_ciphertext.foo" + kmsSecretsDataSource := "data.aws_kms_secrets.test" + resourceName := "aws_kms_ciphertext.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: nil, + CheckDestroy: acctest.CheckDestroyNoop, Steps: []resource.TestStep{ { Config: testAccCiphertextConfig_validate, @@ -52,16 +53,16 @@ func TestAccKMSCiphertext_Resource_validate(t *testing.T) { }) } -func TestAccKMSCiphertext_ResourceValidate_withContext(t *testing.T) { +func TestAccKMSCiphertext_Validate_withContext(t *testing.T) { ctx := acctest.Context(t) - kmsSecretsDataSource := "data.aws_kms_secrets.foo" - resourceName := "aws_kms_ciphertext.foo" + kmsSecretsDataSource := "data.aws_kms_secrets.test" + resourceName := "aws_kms_ciphertext.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: nil, + CheckDestroy: acctest.CheckDestroyNoop, Steps: []resource.TestStep{ { Config: testAccCiphertextConfig_validateContext, @@ -75,46 +76,46 @@ func TestAccKMSCiphertext_ResourceValidate_withContext(t *testing.T) { } const testAccCiphertextConfig_basic = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-basic" is_enabled = true } -resource "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +resource "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" } ` const testAccCiphertextConfig_validate = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-validate" is_enabled = true } -resource "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +resource "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" } -data "aws_kms_secrets" "foo" { +data "aws_kms_secrets" "test" { secret { name = "plaintext" - payload = aws_kms_ciphertext.foo.ciphertext_blob + payload = aws_kms_ciphertext.test.ciphertext_blob } } ` const testAccCiphertextConfig_validateContext = ` -resource "aws_kms_key" "foo" { +resource "aws_kms_key" "test" { description = "tf-test-acc-data-source-aws-kms-ciphertext-validate-with-context" is_enabled = true } -resource "aws_kms_ciphertext" "foo" { - key_id = aws_kms_key.foo.key_id +resource "aws_kms_ciphertext" "test" { + key_id = aws_kms_key.test.key_id plaintext = "Super secret data" @@ -123,10 +124,10 @@ resource "aws_kms_ciphertext" "foo" { } } -data "aws_kms_secrets" "foo" { +data "aws_kms_secrets" "test" { secret { name = "plaintext" - payload = aws_kms_ciphertext.foo.ciphertext_blob + payload = aws_kms_ciphertext.test.ciphertext_blob context = { name = "value" diff --git a/internal/service/kms/consts.go b/internal/service/kms/consts.go index e4074fbacf23..7ea54315f315 100644 --- a/internal/service/kms/consts.go +++ b/internal/service/kms/consts.go @@ -3,18 +3,11 @@ package kms -import ( - "time" -) - -const ( - AliasNamePrefix = "alias/" -) - const ( - PolicyNameDefault = "default" + aliasNamePrefix = "alias/" + cmkAliasPrefix = aliasNamePrefix + "aws/" ) const ( - propagationTimeout = 2 * time.Minute + policyNameDefault = "default" ) diff --git a/internal/service/kms/custom_key_store.go b/internal/service/kms/custom_key_store.go index b4f63bb786e9..ea31baac25f1 100644 --- a/internal/service/kms/custom_key_store.go +++ b/internal/service/kms/custom_key_store.go @@ -5,24 +5,25 @@ package kms import ( "context" - "errors" "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKResource("aws_kms_custom_key_store") -func ResourceCustomKeyStore() *schema.Resource { +// @SDKResource("aws_kms_custom_key_store", name="Custom Key Store") +func resourceCustomKeyStore() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceCustomKeyStoreCreate, ReadWithoutTimeout: resourceCustomKeyStoreRead, @@ -57,97 +58,80 @@ func ResourceCustomKeyStore() *schema.Resource { "trust_anchor_certificate": { Type: schema.TypeString, Required: true, + ForceNew: true, }, }, } } -const ( - ResNameCustomKeyStore = "Custom Key Store" -) - func resourceCustomKeyStoreCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).KMSClient(ctx) - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - in := &kms.CreateCustomKeyStoreInput{ + name := d.Get("custom_key_store_name").(string) + input := &kms.CreateCustomKeyStoreInput{ CloudHsmClusterId: aws.String(d.Get("cloud_hsm_cluster_id").(string)), - CustomKeyStoreName: aws.String(d.Get("custom_key_store_name").(string)), + CustomKeyStoreName: aws.String(name), KeyStorePassword: aws.String(d.Get("key_store_password").(string)), TrustAnchorCertificate: aws.String(d.Get("trust_anchor_certificate").(string)), } - out, err := conn.CreateCustomKeyStoreWithContext(ctx, in) - if err != nil { - return create.AppendDiagError(diags, names.KMS, create.ErrActionCreating, ResNameCustomKeyStore, d.Get("custom_key_store_name").(string), err) - } + output, err := conn.CreateCustomKeyStore(ctx, input) - if out == nil { - return create.AppendDiagError(diags, names.KMS, create.ErrActionCreating, ResNameCustomKeyStore, d.Get("custom_key_store_name").(string), errors.New("empty output")) + if err != nil { + return sdkdiag.AppendErrorf(diags, "creating KMS Custom Key Store (%s): %s", name, err) } - d.SetId(aws.StringValue(out.CustomKeyStoreId)) + d.SetId(aws.ToString(output.CustomKeyStoreId)) return append(diags, resourceCustomKeyStoreRead(ctx, d, meta)...) } func resourceCustomKeyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).KMSClient(ctx) - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - in := &kms.DescribeCustomKeyStoresInput{ - CustomKeyStoreId: aws.String(d.Id()), - } - out, err := FindCustomKeyStoreByID(ctx, conn, in) + output, err := findCustomKeyStoreByID(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { - log.Printf("[WARN] KMS CustomKeyStore (%s) not found, removing from state", d.Id()) + log.Printf("[WARN] KMS Custom Key Store (%s) not found, removing from state", d.Id()) d.SetId("") return diags } if err != nil { - return create.AppendDiagError(diags, names.KMS, create.ErrActionReading, ResNameCustomKeyStore, d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading KMS Custom Key Store (%s): %s", d.Id(), err) } - d.Set("cloud_hsm_cluster_id", out.CloudHsmClusterId) - d.Set("custom_key_store_name", out.CustomKeyStoreName) - d.Set("trust_anchor_certificate", out.TrustAnchorCertificate) + d.Set("cloud_hsm_cluster_id", output.CloudHsmClusterId) + d.Set("custom_key_store_name", output.CustomKeyStoreName) + d.Set("key_store_password", d.Get("key_store_password")) + d.Set("trust_anchor_certificate", output.TrustAnchorCertificate) return diags } func resourceCustomKeyStoreUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).KMSClient(ctx) - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - update := false - - in := &kms.UpdateCustomKeyStoreInput{ - CustomKeyStoreId: aws.String(d.Id()), + input := &kms.UpdateCustomKeyStoreInput{ CloudHsmClusterId: aws.String(d.Get("cloud_hsm_cluster_id").(string)), - } - - if d.HasChange("key_store_password") { - in.KeyStorePassword = aws.String(d.Get("key_store_password").(string)) - update = true + CustomKeyStoreId: aws.String(d.Id()), } if d.HasChange("custom_key_store_name") { - in.NewCustomKeyStoreName = aws.String(d.Get("custom_key_store_name").(string)) - update = true + input.NewCustomKeyStoreName = aws.String(d.Get("custom_key_store_name").(string)) } - if !update { - return diags + if d.HasChange("key_store_password") { + input.KeyStorePassword = aws.String(d.Get("key_store_password").(string)) } - _, err := conn.UpdateCustomKeyStoreWithContext(ctx, in) + _, err := conn.UpdateCustomKeyStore(ctx, input) + if err != nil { - return create.AppendDiagError(diags, names.KMS, create.ErrActionUpdating, ResNameCustomKeyStore, d.Id(), err) + return sdkdiag.AppendErrorf(diags, "updating KMS Custom Key Store (%s): %s", d.Id(), err) } return append(diags, resourceCustomKeyStoreRead(ctx, d, meta)...) @@ -155,18 +139,62 @@ func resourceCustomKeyStoreUpdate(ctx context.Context, d *schema.ResourceData, m func resourceCustomKeyStoreDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).KMSClient(ctx) - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - log.Printf("[INFO] Deleting KMS CustomKeyStore %s", d.Id()) - - _, err := conn.DeleteCustomKeyStoreWithContext(ctx, &kms.DeleteCustomKeyStoreInput{ + log.Printf("[INFO] Deleting KMS Custom Key Store: %s", d.Id()) + _, err := conn.DeleteCustomKeyStore(ctx, &kms.DeleteCustomKeyStoreInput{ CustomKeyStoreId: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } return diags } + +func findCustomKeyStoreByID(ctx context.Context, conn *kms.Client, id string) (*awstypes.CustomKeyStoresListEntry, error) { + input := &kms.DescribeCustomKeyStoresInput{ + CustomKeyStoreId: aws.String(id), + } + + return findCustomKeyStore(ctx, conn, input, tfslices.PredicateTrue[*awstypes.CustomKeyStoresListEntry]()) +} + +func findCustomKeyStore(ctx context.Context, conn *kms.Client, input *kms.DescribeCustomKeyStoresInput, filter tfslices.Predicate[*awstypes.CustomKeyStoresListEntry]) (*awstypes.CustomKeyStoresListEntry, error) { + output, err := findCustomKeyStores(ctx, conn, input, filter) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output) +} + +func findCustomKeyStores(ctx context.Context, conn *kms.Client, input *kms.DescribeCustomKeyStoresInput, filter tfslices.Predicate[*awstypes.CustomKeyStoresListEntry]) ([]awstypes.CustomKeyStoresListEntry, error) { + var output []awstypes.CustomKeyStoresListEntry + + pages := kms.NewDescribeCustomKeyStoresPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if errs.IsA[*awstypes.CustomKeyStoreNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return output, err + } + + for _, v := range page.CustomKeyStores { + if filter(&v) { + output = append(output, v) + } + } + } + + return output, nil +} diff --git a/internal/service/kms/custom_key_store_data_source.go b/internal/service/kms/custom_key_store_data_source.go index 466c56d08a70..98da552da837 100644 --- a/internal/service/kms/custom_key_store_data_source.go +++ b/internal/service/kms/custom_key_store_data_source.go @@ -7,32 +7,22 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/names" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" ) -// @SDKDataSource("aws_kms_custom_key_store") -func DataSourceCustomKeyStore() *schema.Resource { +// @SDKDataSource("aws_kms_custom_key_store", name="Custom Key Store") +func dataSourceCustomKeyStore() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceCustomKeyStoreRead, + Schema: map[string]*schema.Schema{ - "custom_key_store_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"custom_key_store_name"}, - }, - "custom_key_store_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"custom_key_store_id"}, - }, "cloud_hsm_cluster_id": { Type: schema.TypeString, Computed: true, @@ -45,6 +35,18 @@ func DataSourceCustomKeyStore() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "custom_key_store_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"custom_key_store_name"}, + }, + "custom_key_store_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"custom_key_store_id"}, + }, "trust_anchor_certificate": { Type: schema.TypeString, Computed: true, @@ -53,14 +55,9 @@ func DataSourceCustomKeyStore() *schema.Resource { } } -const ( - DSNameCustomKeyStore = "Custom Key Store" -) - func dataSourceCustomKeyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) input := &kms.DescribeCustomKeyStoresInput{} @@ -68,24 +65,23 @@ func dataSourceCustomKeyStoreRead(ctx context.Context, d *schema.ResourceData, m if v, ok := d.GetOk("custom_key_store_id"); ok { input.CustomKeyStoreId = aws.String(v.(string)) ksID = v.(string) - } - if v, ok := d.GetOk("custom_key_store_name"); ok { + } else if v, ok := d.GetOk("custom_key_store_name"); ok { input.CustomKeyStoreName = aws.String(v.(string)) ksID = v.(string) } - keyStore, err := FindCustomKeyStoreByID(ctx, conn, input) + keyStore, err := findCustomKeyStore(ctx, conn, input, tfslices.PredicateTrue[*awstypes.CustomKeyStoresListEntry]()) if err != nil { - return create.AppendDiagError(diags, names.KMS, create.ErrActionReading, DSNameCustomKeyStore, ksID, err) + return sdkdiag.AppendErrorf(diags, "reading KMS Custom Key Store (%s): %s", ksID, err) } - d.SetId(aws.StringValue(keyStore.CustomKeyStoreId)) - d.Set("custom_key_store_name", keyStore.CustomKeyStoreName) - d.Set("custom_key_store_id", keyStore.CustomKeyStoreId) + d.SetId(aws.ToString(keyStore.CustomKeyStoreId)) d.Set("cloud_hsm_cluster_id", keyStore.CloudHsmClusterId) d.Set("connection_state", keyStore.ConnectionState) d.Set("creation_date", keyStore.CreationDate.Format(time.RFC3339)) + d.Set("custom_key_store_id", keyStore.CustomKeyStoreId) + d.Set("custom_key_store_name", keyStore.CustomKeyStoreName) d.Set("trust_anchor_certificate", keyStore.TrustAnchorCertificate) return diags diff --git a/internal/service/kms/custom_key_store_data_source_test.go b/internal/service/kms/custom_key_store_data_source_test.go index 82de2d4b5e61..87402b16fc7f 100644 --- a/internal/service/kms/custom_key_store_data_source_test.go +++ b/internal/service/kms/custom_key_store_data_source_test.go @@ -5,7 +5,6 @@ package kms_test import ( "fmt" - "os" "testing" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -14,34 +13,30 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccKMSCustomKeyStoreDataSource_basic(t *testing.T) { +func testAccCustomKeyStoreDataSource_basic(t *testing.T) { ctx := acctest.Context(t) - if os.Getenv("CLOUD_HSM_CLUSTER_ID") == "" { - t.Skip("CLOUD_HSM_CLUSTER_ID environment variable not set") + if testing.Short() { + t.Skip("skipping long-running test in short mode") } - if os.Getenv("TRUST_ANCHOR_CERTIFICATE") == "" { - t.Skip("TRUST_ANCHOR_CERTIFICATE environment variable not set") - } - - resourceName := "aws_kms_custom_key_store.test" - dataSourceName := "data.aws_kms_custom_key_store.test" + clusterID := acctest.SkipIfEnvVarNotSet(t, "CLOUD_HSM_CLUSTER_ID") + trustAnchorCertificate := acctest.SkipIfEnvVarNotSet(t, "TRUST_ANCHOR_CERTIFICATE") rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - clusterId := os.Getenv("CLOUD_HSM_CLUSTER_ID") - trustAnchorCertificate := os.Getenv("TRUST_ANCHOR_CERTIFICATE") + dataSourceName := "data.aws_kms_custom_key_store.test" + resourceName := "aws_kms_custom_key_store.test" - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccCustomKeyStoreDataSourceConfig_basic(rName, clusterId, trustAnchorCertificate), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair(dataSourceName, "custom_key_store_name", resourceName, "custom_key_store_name"), + Config: testAccCustomKeyStoreDataSourceConfig_basic(rName, clusterID, trustAnchorCertificate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "cloud_hsm_cluster_id", resourceName, "cloud_hsm_cluster_id"), resource.TestCheckResourceAttrPair(dataSourceName, "custom_key_store_id", resourceName, "id"), + resource.TestCheckResourceAttrPair(dataSourceName, "custom_key_store_name", resourceName, "custom_key_store_name"), resource.TestCheckResourceAttrPair(dataSourceName, "trust_anchor_certificate", resourceName, "trust_anchor_certificate"), - resource.TestCheckResourceAttrPair(dataSourceName, "cloud_hsm_cluster_id", resourceName, "cloud_hsm_cluster_id"), ), }, }, diff --git a/internal/service/kms/custom_key_store_test.go b/internal/service/kms/custom_key_store_test.go index f4a52c07004a..5aaafb114ef0 100644 --- a/internal/service/kms/custom_key_store_test.go +++ b/internal/service/kms/custom_key_store_test.go @@ -5,19 +5,16 @@ package kms_test import ( "context" - "errors" "fmt" - "os" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" tfkms "github.com/hashicorp/terraform-provider-aws/internal/service/kms" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" @@ -25,29 +22,20 @@ import ( func testAccCustomKeyStore_basic(t *testing.T) { ctx := acctest.Context(t) - if os.Getenv("CLOUD_HSM_CLUSTER_ID") == "" { - t.Skip("CLOUD_HSM_CLUSTER_ID environment variable not set") - } - - if os.Getenv("TRUST_ANCHOR_CERTIFICATE") == "" { - t.Skip("TRUST_ANCHOR_CERTIFICATE environment variable not set") - } - if testing.Short() { t.Skip("skipping long-running test in short mode") } - var customkeystore kms.CustomKeyStoresListEntry + clusterID := acctest.SkipIfEnvVarNotSet(t, "CLOUD_HSM_CLUSTER_ID") + trustAnchorCertificate := acctest.SkipIfEnvVarNotSet(t, "TRUST_ANCHOR_CERTIFICATE") + var customkeystore awstypes.CustomKeyStoresListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_custom_key_store.test" - clusterId := os.Getenv("CLOUD_HSM_CLUSTER_ID") - trustAnchorCertificate := os.Getenv("TRUST_ANCHOR_CERTIFICATE") - resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, kms.EndpointsID) + acctest.PreCheckPartitionHasService(t, names.KMSEndpointID) testAccCustomKeyStoresPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -55,10 +43,10 @@ func testAccCustomKeyStore_basic(t *testing.T) { CheckDestroy: testAccCheckCustomKeyStoreDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCustomKeyStoreConfig_basic(rName, clusterId, trustAnchorCertificate), + Config: testAccCustomKeyStoreConfig_basic(rName, clusterID, trustAnchorCertificate), Check: resource.ComposeTestCheckFunc( testAccCheckCustomKeyStoreExists(ctx, resourceName, &customkeystore), - resource.TestCheckResourceAttr(resourceName, "cloud_hsm_cluster_id", clusterId), + resource.TestCheckResourceAttr(resourceName, "cloud_hsm_cluster_id", clusterID), ), }, { @@ -73,29 +61,20 @@ func testAccCustomKeyStore_basic(t *testing.T) { func testAccCustomKeyStore_update(t *testing.T) { ctx := acctest.Context(t) - if os.Getenv("CLOUD_HSM_CLUSTER_ID") == "" { - t.Skip("CLOUD_HSM_CLUSTER_ID environment variable not set") - } - - if os.Getenv("TRUST_ANCHOR_CERTIFICATE") == "" { - t.Skip("TRUST_ANCHOR_CERTIFICATE environment variable not set") - } - if testing.Short() { t.Skip("skipping long-running test in short mode") } - var customkeystore kms.CustomKeyStoresListEntry + clusterID := acctest.SkipIfEnvVarNotSet(t, "CLOUD_HSM_CLUSTER_ID") + trustAnchorCertificate := acctest.SkipIfEnvVarNotSet(t, "TRUST_ANCHOR_CERTIFICATE") + var customkeystore awstypes.CustomKeyStoresListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_custom_key_store.test" - clusterId := os.Getenv("CLOUD_HSM_CLUSTER_ID") - trustAnchorCertificate := os.Getenv("TRUST_ANCHOR_CERTIFICATE") - resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, kms.EndpointsID) + acctest.PreCheckPartitionHasService(t, names.KMSEndpointID) testAccCustomKeyStoresPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -103,10 +82,16 @@ func testAccCustomKeyStore_update(t *testing.T) { CheckDestroy: testAccCheckCustomKeyStoreDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCustomKeyStoreConfig_basic(fmt.Sprintf("%s-updated", rName), clusterId, trustAnchorCertificate), + Config: testAccCustomKeyStoreConfig_basic(rName, clusterID, trustAnchorCertificate), + Check: resource.ComposeTestCheckFunc( + testAccCheckCustomKeyStoreExists(ctx, resourceName, &customkeystore), + resource.TestCheckResourceAttr(resourceName, "custom_key_store_name", rName), + ), + }, + { + Config: testAccCustomKeyStoreConfig_basic(fmt.Sprintf("%s-updated", rName), clusterID, trustAnchorCertificate), Check: resource.ComposeTestCheckFunc( testAccCheckCustomKeyStoreExists(ctx, resourceName, &customkeystore), - resource.TestCheckResourceAttr(resourceName, "cloud_hsm_cluster_id", clusterId), resource.TestCheckResourceAttr(resourceName, "custom_key_store_name", fmt.Sprintf("%s-updated", rName)), ), }, @@ -116,29 +101,20 @@ func testAccCustomKeyStore_update(t *testing.T) { func testAccCustomKeyStore_disappears(t *testing.T) { ctx := acctest.Context(t) - if os.Getenv("CLOUD_HSM_CLUSTER_ID") == "" { - t.Skip("CLOUD_HSM_CLUSTER_ID environment variable not set") - } - - if os.Getenv("TRUST_ANCHOR_CERTIFICATE") == "" { - t.Skip("TRUST_ANCHOR_CERTIFICATE environment variable not set") - } - if testing.Short() { t.Skip("skipping long-running test in short mode") } - var customkeystore kms.CustomKeyStoresListEntry + clusterID := acctest.SkipIfEnvVarNotSet(t, "CLOUD_HSM_CLUSTER_ID") + trustAnchorCertificate := acctest.SkipIfEnvVarNotSet(t, "TRUST_ANCHOR_CERTIFICATE") + var customkeystore awstypes.CustomKeyStoresListEntry rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_custom_key_store.test" - clusterId := os.Getenv("CLOUD_HSM_CLUSTER_ID") - trustAnchorCertificate := os.Getenv("TRUST_ANCHOR_CERTIFICATE") - resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, kms.EndpointsID) + acctest.PreCheckPartitionHasService(t, names.KMSEndpointID) testAccCustomKeyStoresPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.KMSServiceID), @@ -146,7 +122,7 @@ func testAccCustomKeyStore_disappears(t *testing.T) { CheckDestroy: testAccCheckCustomKeyStoreDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCustomKeyStoreConfig_basic(rName, clusterId, trustAnchorCertificate), + Config: testAccCustomKeyStoreConfig_basic(rName, clusterID, trustAnchorCertificate), Check: resource.ComposeTestCheckFunc( testAccCheckCustomKeyStoreExists(ctx, resourceName, &customkeystore), acctest.CheckResourceDisappears(ctx, acctest.Provider, tfkms.ResourceCustomKeyStore(), resourceName), @@ -159,62 +135,55 @@ func testAccCustomKeyStore_disappears(t *testing.T) { func testAccCheckCustomKeyStoreDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_kms_custom_key_store" { continue } - in := &kms.DescribeCustomKeyStoresInput{ - CustomKeyStoreId: aws.String(rs.Primary.ID), - } - _, err := tfkms.FindCustomKeyStoreByID(ctx, conn, in) + _, err := tfkms.FindCustomKeyStoreByID(ctx, conn, rs.Primary.ID) if tfresource.NotFound(err) { continue } - return create.Error(names.KMS, create.ErrActionCheckingDestroyed, tfkms.ResNameCustomKeyStore, rs.Primary.ID, errors.New("not destroyed")) + if err != nil { + return err + } + + return fmt.Errorf("KMS Custom Key Store %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckCustomKeyStoreExists(ctx context.Context, name string, customkeystore *kms.CustomKeyStoresListEntry) resource.TestCheckFunc { +func testAccCheckCustomKeyStoreExists(ctx context.Context, n string, v *awstypes.CustomKeyStoresListEntry) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return create.Error(names.KMS, create.ErrActionCheckingExistence, tfkms.ResNameCustomKeyStore, name, errors.New("not found")) + return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return create.Error(names.KMS, create.ErrActionCheckingExistence, tfkms.ResNameCustomKeyStore, name, errors.New("not set")) - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) - in := &kms.DescribeCustomKeyStoresInput{ - CustomKeyStoreId: aws.String(rs.Primary.ID), - } - resp, err := tfkms.FindCustomKeyStoreByID(ctx, conn, in) + output, err := tfkms.FindCustomKeyStoreByID(ctx, conn, rs.Primary.ID) if err != nil { - return create.Error(names.KMS, create.ErrActionCheckingExistence, tfkms.ResNameCustomKeyStore, rs.Primary.ID, err) + return err } - *customkeystore = *resp + *v = *output return nil } } func testAccCustomKeyStoresPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) - input := &kms.DescribeCustomKeyStoresInput{} - _, err := conn.DescribeCustomKeyStoresWithContext(ctx, input) + _, err := conn.DescribeCustomKeyStores(ctx, &kms.DescribeCustomKeyStoresInput{}) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) diff --git a/internal/service/kms/diff.go b/internal/service/kms/diff.go index 087d226b4e53..da72cfd133bb 100644 --- a/internal/service/kms/diff.go +++ b/internal/service/kms/diff.go @@ -10,29 +10,29 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DiffSuppressKey(_, oldValue, newValue string, _ *schema.ResourceData) bool { +func diffSuppressKey(_, oldValue, newValue string, _ *schema.ResourceData) bool { if oldValue == newValue { return true } - oldId := oldValue + oldID := oldValue if arn.IsARN(oldValue) { - oldId = keyIdFromARN(oldValue) + oldID = keyIDFromARN(oldValue) } - newId := newValue + newID := newValue if arn.IsARN(newValue) { - newId = keyIdFromARN(newValue) + newID = keyIDFromARN(newValue) } - if oldId == newId { + if oldID == newID { return true } return false } -func DiffSuppressAlias(_, oldValue, newValue string, _ *schema.ResourceData) bool { +func diffSuppressAlias(_, oldValue, newValue string, _ *schema.ResourceData) bool { if oldValue == newValue { return true } @@ -54,30 +54,30 @@ func DiffSuppressAlias(_, oldValue, newValue string, _ *schema.ResourceData) boo return false } -func DiffSuppressKeyOrAlias(k, oldValue, newValue string, d *schema.ResourceData) bool { +func diffSuppressKeyOrAlias(k, oldValue, newValue string, d *schema.ResourceData) bool { if arn.IsARN(newValue) { if isKeyARN(newValue) { - return DiffSuppressKey(k, oldValue, newValue, d) + return diffSuppressKey(k, oldValue, newValue, d) } else { - return DiffSuppressAlias(k, oldValue, newValue, d) + return diffSuppressAlias(k, oldValue, newValue, d) } } else if isAliasName(newValue) { - return DiffSuppressAlias(k, oldValue, newValue, d) + return diffSuppressAlias(k, oldValue, newValue, d) } - return DiffSuppressKey(k, oldValue, newValue, d) + return diffSuppressKey(k, oldValue, newValue, d) } -func keyIdFromARN(s string) string { +func keyIDFromARN(s string) string { arn, err := arn.Parse(s) if err != nil { return "" } - return keyIdFromARNResource(arn.Resource) + return keyIDFromARNResource(arn.Resource) } -func keyIdFromARNResource(s string) string { - matches := keyIdResourceRegex.FindStringSubmatch(s) +func keyIDFromARNResource(s string) string { + matches := keyIDResourceRegex.FindStringSubmatch(s) if matches == nil || len(matches) != 2 { return "" } @@ -108,11 +108,11 @@ func isKeyARN(s string) bool { return false } - return keyIdFromARNResource(parsedARN.Resource) != "" + return keyIDFromARNResource(parsedARN.Resource) != "" } func isAliasName(s string) bool { - return strings.HasPrefix(s, "alias/") + return strings.HasPrefix(s, aliasNamePrefix) } func isAliasARN(s string) bool { diff --git a/internal/service/kms/diff_test.go b/internal/service/kms/diff_test.go index 91ad22e6150f..2eebf2c9916e 100644 --- a/internal/service/kms/diff_test.go +++ b/internal/service/kms/diff_test.go @@ -7,7 +7,7 @@ import ( "testing" ) -func TestDiffSuppressKeyId(t *testing.T) { +func TestDiffSuppressKeyID(t *testing.T) { t.Parallel() testcases := map[string]struct { @@ -65,7 +65,7 @@ func TestDiffSuppressKeyId(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - actual := DiffSuppressKey("field", testcase.old, testcase.new, nil) + actual := diffSuppressKey("field", testcase.old, testcase.new, nil) if e := testcase.expectSuppress; actual != e { t.Fatalf("expected %t, got %t", e, actual) diff --git a/internal/service/kms/exports.go b/internal/service/kms/exports.go index 9fcb8e2e16e9..cd4d4c22f1e4 100644 --- a/internal/service/kms/exports.go +++ b/internal/service/kms/exports.go @@ -5,5 +5,11 @@ package kms // Exports for use in other modules. var ( - FindDefaultKey = findDefaultKey + DiffSuppressKey = diffSuppressKey + DiffSuppressKeyOrAlias = diffSuppressKeyOrAlias + FindAliasByName = findAliasByName + FindDefaultKeyARNForService = findDefaultKeyARNForService + FindKeyByID = findKeyByID + ValidateKey = validateKey + ValidateKeyOrAlias = validateKeyOrAlias ) diff --git a/internal/service/kms/exports_test.go b/internal/service/kms/exports_test.go new file mode 100644 index 000000000000..9be586498afb --- /dev/null +++ b/internal/service/kms/exports_test.go @@ -0,0 +1,26 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package kms + +// Exports for use in tests only. +var ( + ResourceAlias = resourceAlias + ResourceCiphertext = resourceCiphertext + ResourceCustomKeyStore = resourceCustomKeyStore + ResourceExternalKey = resourceExternalKey + ResourceGrant = resourceGrant + ResourceKey = resourceKey + ResourceKeyPolicy = resourceKeyPolicy + ResourceReplicaExternalKey = resourceReplicaExternalKey + ResourceReplicaKey = resourceReplicaKey + + AliasNamePrefix = aliasNamePrefix + FindCustomKeyStoreByID = findCustomKeyStoreByID + FindGrantByTwoPartKey = findGrantByTwoPartKey + FindKeyPolicyByTwoPartKey = findKeyPolicyByTwoPartKey + GrantParseResourceID = grantParseResourceID + KMSPropagationTimeout = kmsPropagationTimeout // nosemgrep:ci.kms-in-var-name + PolicyNameDefault = policyNameDefault + SecretRemovedMessage = secretRemovedMessage +) diff --git a/internal/service/kms/external_key.go b/internal/service/kms/external_key.go index eaa3e1c54c85..7aae4b959270 100644 --- a/internal/service/kms/external_key.go +++ b/internal/service/kms/external_key.go @@ -13,15 +13,18 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/logging" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -33,7 +36,7 @@ import ( // @SDKResource("aws_kms_external_key", name="External Key") // @Tags(identifierAttribute="id") -func ResourceExternalKey() *schema.Resource { +func resourceExternalKey() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceExternalKeyCreate, ReadWithoutTimeout: resourceExternalKeyRead, @@ -124,12 +127,12 @@ func ResourceExternalKey() *schema.Resource { func resourceExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) input := &kms.CreateKeyInput{ - BypassPolicyLockoutSafetyCheck: aws.Bool(d.Get("bypass_policy_lockout_safety_check").(bool)), - KeyUsage: aws.String(kms.KeyUsageTypeEncryptDecrypt), - Origin: aws.String(kms.OriginTypeExternal), + BypassPolicyLockoutSafetyCheck: d.Get("bypass_policy_lockout_safety_check").(bool), + KeyUsage: awstypes.KeyUsageTypeEncryptDecrypt, + Origin: awstypes.OriginTypeExternal, Tags: getTagsIn(ctx), } @@ -144,7 +147,7 @@ func resourceExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta if v, ok := d.GetOk("policy"); ok { p, err := structure.NormalizeJsonString(v.(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", p, err) + return sdkdiag.AppendFromErr(diags, err) } input.Policy = aws.String(p) @@ -155,52 +158,52 @@ func resourceExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta // KMS will report this error until it can validate the policy itself. // They acknowledge this here: // http://docs.aws.amazon.com/kms/latest/APIReference/API_CreateKey.html - output, err := WaitIAMPropagation(ctx, propagationTimeout, func() (*kms.CreateKeyOutput, error) { - return conn.CreateKeyWithContext(ctx, input) + output, err := waitIAMPropagation(ctx, iamPropagationTimeout, func() (*kms.CreateKeyOutput, error) { + return conn.CreateKey(ctx, input) }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS External Key: %s", err) } - d.SetId(aws.StringValue(output.KeyMetadata.KeyId)) + d.SetId(aws.ToString(output.KeyMetadata.KeyId)) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) if v, ok := d.GetOk("key_material_base64"); ok { validTo := d.Get("valid_to").(string) - if err := importExternalKeyMaterial(ctx, conn, d.Id(), v.(string), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "importing KMS External Key (%s) material: %s", d.Id(), err) + if err := importExternalKeyMaterial(ctx, conn, "KMS External Key", d.Id(), v.(string), validTo); err != nil { + return sdkdiag.AppendFromErr(diags, err) } - if _, err := WaitKeyMaterialImported(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyMaterialImported(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) material import: %s", d.Id(), err) } - if err := WaitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) valid_to propagation: %s", d.Id(), err) + if err := waitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) valid_to update: %s", d.Id(), err) } // The key can only be disabled if key material has been imported, else: // "KMSInvalidStateException: arn:aws:kms:us-west-2:123456789012:key/47e3edc1-945f-413b-88b1-e7341c2d89f7 is pending import." if enabled := d.Get("enabled").(bool); !enabled { - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "creating KMS External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } } // Wait for propagation since KMS is eventually consistent. if v, ok := d.GetOk("policy"); ok { - if err := WaitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) policy propagation: %s", d.Id(), err) + if err := waitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) policy update: %s", d.Id(), err) } } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) tag propagation: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) tag update: %s", d.Id(), err) } } @@ -209,11 +212,11 @@ func resourceExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta func resourceExternalKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - key, err := findKey(ctx, conn, d.Id(), d.IsNewResource()) + key, err := findKeyInfo(ctx, conn, d.Id(), d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS External Key (%s) not found, removing from state", d.Id()) @@ -225,16 +228,15 @@ func resourceExternalKeyRead(ctx context.Context, d *schema.ResourceData, meta i return sdkdiag.AppendErrorf(diags, "reading KMS External Key (%s): %s", d.Id(), err) } - if keyManager := aws.StringValue(key.metadata.KeyManager); keyManager != kms.KeyManagerTypeCustomer { + if keyManager := key.metadata.KeyManager; keyManager != awstypes.KeyManagerTypeCustomer { return sdkdiag.AppendErrorf(diags, "KMS External Key (%s) has invalid KeyManager: %s", d.Id(), keyManager) } - if origin := aws.StringValue(key.metadata.Origin); origin != kms.OriginTypeExternal { + if origin := key.metadata.Origin; origin != awstypes.OriginTypeExternal { return sdkdiag.AppendErrorf(diags, "KMS External Key (%s) has invalid Origin: %s", d.Id(), origin) } - if aws.BoolValue(key.metadata.MultiRegion) && - aws.StringValue(key.metadata.MultiRegionConfiguration.MultiRegionKeyType) != kms.MultiRegionKeyTypePrimary { + if aws.ToBool(key.metadata.MultiRegion) && key.metadata.MultiRegionConfiguration.MultiRegionKeyType != awstypes.MultiRegionKeyTypePrimary { return sdkdiag.AppendErrorf(diags, "KMS External Key (%s) is not a multi-Region primary key", d.Id()) } @@ -248,13 +250,13 @@ func resourceExternalKeyRead(ctx context.Context, d *schema.ResourceData, meta i policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), key.policy) if err != nil { - return sdkdiag.AppendErrorf(diags, "while setting policy (%s), encountered: %s", key.policy, err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) if key.metadata.ValidTo != nil { - d.Set("valid_to", aws.TimeValue(key.metadata.ValidTo).Format(time.RFC3339)) + d.Set("valid_to", aws.ToTime(key.metadata.ValidTo).Format(time.RFC3339)) } else { d.Set("valid_to", nil) } @@ -266,49 +268,49 @@ func resourceExternalKeyRead(ctx context.Context, d *schema.ResourceData, meta i func resourceExternalKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), d.Get("key_state").(string); hasChange && enabled && state != kms.KeyStatePendingImport { + if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), awstypes.KeyState(d.Get("key_state").(string)); hasChange && enabled && state != awstypes.KeyStatePendingImport { // Enable before any attributes are modified. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("description") { - if err := updateKeyDescription(ctx, conn, d.Id(), d.Get("description").(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS External Key (%s): %s", d.Id(), err) + if err := updateKeyDescription(ctx, conn, "KMS External Key", d.Id(), d.Get("description").(string)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("policy") { - if err := updateKeyPolicy(ctx, conn, d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS External Key (%s): %s", d.Id(), err) + if err := updateKeyPolicy(ctx, conn, "KMS External Key", d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("valid_to") { validTo := d.Get("valid_to").(string) - if err := importExternalKeyMaterial(ctx, conn, d.Id(), d.Get("key_material_base64").(string), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "importing KMS External Key (%s) material: %s", d.Id(), err) + if err := importExternalKeyMaterial(ctx, conn, "KMS External Key", d.Id(), d.Get("key_material_base64").(string), validTo); err != nil { + return sdkdiag.AppendFromErr(diags, err) } - if _, err := WaitKeyMaterialImported(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyMaterialImported(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) material import: %s", d.Id(), err) } - if err := WaitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) valid_to propagation: %s", d.Id(), err) + if err := waitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) valid_to update: %s", d.Id(), err) } } - if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), d.Get("key_state").(string); hasChange && !enabled && state != kms.KeyStatePendingImport { + if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), awstypes.KeyState(d.Get("key_state").(string)); hasChange && !enabled && state != awstypes.KeyStatePendingImport { // Only disable after all attributes have been modified because we cannot modify disabled keys. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -317,7 +319,7 @@ func resourceExternalKeyUpdate(ctx context.Context, d *schema.ResourceData, meta func resourceExternalKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) @@ -326,17 +328,17 @@ func resourceExternalKeyDelete(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("deletion_window_in_days"); ok { - input.PendingWindowInDays = aws.Int64(int64(v.(int))) + input.PendingWindowInDays = aws.Int32(int32(v.(int))) } - log.Printf("[DEBUG] Deleting KMS External Key: (%s)", d.Id()) - _, err := conn.ScheduleKeyDeletionWithContext(ctx, input) + log.Printf("[DEBUG] Deleting KMS External Key: %s", d.Id()) + _, err := conn.ScheduleKeyDeletion(ctx, input) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } - if tfawserr.ErrMessageContains(err, kms.ErrCodeInvalidStateException, "is pending deletion") { + if errs.IsAErrorMessageContains[*awstypes.KMSInvalidStateException](err, "is pending deletion") { return diags } @@ -344,25 +346,25 @@ func resourceExternalKeyDelete(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "deleting KMS External Key (%s): %s", d.Id(), err) } - if _, err := WaitKeyDeleted(ctx, conn, d.Id()); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) to delete: %s", d.Id(), err) + if _, err := waitKeyDeleted(ctx, conn, d.Id()); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) delete: %s", d.Id(), err) } return diags } -func importExternalKeyMaterial(ctx context.Context, conn *kms.KMS, keyID, keyMaterialBase64, validTo string) error { +func importExternalKeyMaterial(ctx context.Context, conn *kms.Client, resourceTypeName, keyID, keyMaterialBase64, validTo string) error { // Wait for propagation since KMS is eventually consistent. - outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, PropagationTimeout, func() (interface{}, error) { - return conn.GetParametersForImportWithContext(ctx, &kms.GetParametersForImportInput{ + outputRaw, err := tfresource.RetryWhenIsA[*awstypes.NotFoundException](ctx, kmsPropagationTimeout, func() (interface{}, error) { + return conn.GetParametersForImport(ctx, &kms.GetParametersForImportInput{ KeyId: aws.String(keyID), - WrappingAlgorithm: aws.String(kms.AlgorithmSpecRsaesOaepSha256), - WrappingKeySpec: aws.String(kms.WrappingKeySpecRsa2048), + WrappingAlgorithm: awstypes.AlgorithmSpecRsaesOaepSha256, + WrappingKeySpec: awstypes.WrappingKeySpecRsa2048, }) - }, kms.ErrCodeNotFoundException) + }) if err != nil { - return fmt.Errorf("getting parameters for import: %w", err) + return fmt.Errorf("reading %s (%s) parameters for import: %w", resourceTypeName, keyID, err) } keyMaterial, err := itypes.Base64Decode(keyMaterialBase64) @@ -374,17 +376,17 @@ func importExternalKeyMaterial(ctx context.Context, conn *kms.KMS, keyID, keyMat publicKey, err := x509.ParsePKIXPublicKey(output.PublicKey) if err != nil { - return fmt.Errorf("parsing public key (PKIX): %w", err) + return fmt.Errorf("parsing %s (%s) public key (PKIX): %w", resourceTypeName, keyID, err) } encryptedKeyMaterial, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey.(*rsa.PublicKey), keyMaterial, []byte{}) if err != nil { - return fmt.Errorf("encrypting key material (RSA-OAEP): %w", err) + return fmt.Errorf("encrypting %s (%s) key material (RSA-OAEP): %w", resourceTypeName, keyID, err) } input := &kms.ImportKeyMaterialInput{ EncryptedKeyMaterial: encryptedKeyMaterial, - ExpirationModel: aws.String(kms.ExpirationModelTypeKeyMaterialDoesNotExpire), + ExpirationModel: awstypes.ExpirationModelTypeKeyMaterialDoesNotExpire, ImportToken: output.ImportToken, KeyId: aws.String(keyID), } @@ -395,18 +397,67 @@ func importExternalKeyMaterial(ctx context.Context, conn *kms.KMS, keyID, keyMat return err } - input.ExpirationModel = aws.String(kms.ExpirationModelTypeKeyMaterialExpires) + input.ExpirationModel = awstypes.ExpirationModelTypeKeyMaterialExpires input.ValidTo = aws.Time(t) } // Wait for propagation since KMS is eventually consistent. - _, err = tfresource.RetryWhenAWSErrCodeEquals(ctx, PropagationTimeout, func() (interface{}, error) { - return conn.ImportKeyMaterialWithContext(ctx, input) - }, kms.ErrCodeNotFoundException) + _, err = tfresource.RetryWhenIsA[*awstypes.NotFoundException](ctx, kmsPropagationTimeout, func() (interface{}, error) { + return conn.ImportKeyMaterial(ctx, input) + }) if err != nil { - return fmt.Errorf("importing key material: %w", err) + return fmt.Errorf("importing %s (%s) key material: %w", resourceTypeName, keyID, err) } return nil } + +func waitKeyMaterialImported(ctx context.Context, conn *kms.Client, id string) (*awstypes.KeyMetadata, error) { //nolint:unparam + const ( + timeout = 10 * time.Minute + ) + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.KeyStatePendingImport), + Target: enum.Slice(awstypes.KeyStateDisabled, awstypes.KeyStateEnabled), + Refresh: statusKeyState(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.KeyMetadata); ok { + return output, err + } + + return nil, err +} + +func waitKeyValidToPropagated(ctx context.Context, conn *kms.Client, id string, validTo string) error { + checkFunc := func() (bool, error) { + output, err := findKeyByID(ctx, conn, id) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + if output.ValidTo != nil { + return aws.ToTime(output.ValidTo).Format(time.RFC3339) == validTo, nil + } + + return validTo == "", nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 5, + MinTimeout: 2 * time.Second, + } + const ( + timeout = 5 * time.Minute + ) + + return tfresource.WaitUntil(ctx, timeout, checkFunc, opts) +} diff --git a/internal/service/kms/external_key_test.go b/internal/service/kms/external_key_test.go index 3d938d8fdfaa..4a355fd850e8 100644 --- a/internal/service/kms/external_key_test.go +++ b/internal/service/kms/external_key_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" awspolicy "github.com/hashicorp/awspolicyequivalence" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -25,7 +25,7 @@ import ( func TestAccKMSExternalKey_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata resourceName := "aws_kms_external_key.test" resource.ParallelTest(t, resource.TestCase{ @@ -67,7 +67,7 @@ func TestAccKMSExternalKey_basic(t *testing.T) { func TestAccKMSExternalKey_disappears(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata resourceName := "aws_kms_external_key.test" resource.ParallelTest(t, resource.TestCase{ @@ -90,7 +90,7 @@ func TestAccKMSExternalKey_disappears(t *testing.T) { func TestAccKMSExternalKey_multiRegion(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -122,7 +122,7 @@ func TestAccKMSExternalKey_multiRegion(t *testing.T) { func TestAccKMSExternalKey_deletionWindowInDays(t *testing.T) { ctx := acctest.Context(t) - var key1, key2 kms.KeyMetadata + var key1, key2 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -162,7 +162,7 @@ func TestAccKMSExternalKey_deletionWindowInDays(t *testing.T) { func TestAccKMSExternalKey_description(t *testing.T) { ctx := acctest.Context(t) - var key1, key2 kms.KeyMetadata + var key1, key2 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -202,7 +202,7 @@ func TestAccKMSExternalKey_description(t *testing.T) { func TestAccKMSExternalKey_enabled(t *testing.T) { ctx := acctest.Context(t) - var key1, key2, key3 kms.KeyMetadata + var key1, key2, key3 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -251,7 +251,7 @@ func TestAccKMSExternalKey_enabled(t *testing.T) { func TestAccKMSExternalKey_keyMaterialBase64(t *testing.T) { ctx := acctest.Context(t) - var key1, key2 kms.KeyMetadata + var key1, key2 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -294,7 +294,7 @@ func TestAccKMSExternalKey_keyMaterialBase64(t *testing.T) { func TestAccKMSExternalKey_policy(t *testing.T) { ctx := acctest.Context(t) - var key1, key2 kms.KeyMetadata + var key1, key2 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) policy1 := `{"Id":"kms-tf-1","Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"*","Sid":"Enable IAM User Permissions 1"}],"Version":"2012-10-17"}` policy2 := `{"Id":"kms-tf-1","Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"*","Sid":"Enable IAM User Permissions 2"}],"Version":"2012-10-17"}` @@ -336,7 +336,7 @@ func TestAccKMSExternalKey_policy(t *testing.T) { func TestAccKMSExternalKey_policyBypass(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) policy := `{"Id":"kms-tf-1","Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"*","Sid":"Enable IAM User Permissions 1"}],"Version":"2012-10-17"}` resourceName := "aws_kms_external_key.test" @@ -370,7 +370,7 @@ func TestAccKMSExternalKey_policyBypass(t *testing.T) { func TestAccKMSExternalKey_tags(t *testing.T) { ctx := acctest.Context(t) - var key1, key2, key3 kms.KeyMetadata + var key1, key2, key3 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" @@ -439,7 +439,7 @@ func TestAccKMSExternalKey_tags(t *testing.T) { func TestAccKMSExternalKey_validTo(t *testing.T) { ctx := acctest.Context(t) - var key1, key2, key3, key4 kms.KeyMetadata + var key1, key2, key3, key4 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_external_key.test" validTo1 := time.Now().UTC().Add(1 * time.Hour).Format(time.RFC3339) @@ -507,19 +507,15 @@ func testAccCheckExternalKeyHasPolicy(ctx context.Context, name string, expected return fmt.Errorf("Not found: %s", name) } - if rs.Primary.ID == "" { - return fmt.Errorf("No KMS External Key ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) - output, err := tfkms.FindKeyPolicyByKeyIDAndPolicyName(ctx, conn, rs.Primary.ID, tfkms.PolicyNameDefault) + output, err := tfkms.FindKeyPolicyByTwoPartKey(ctx, conn, rs.Primary.ID, tfkms.PolicyNameDefault) if err != nil { return err } - actualPolicyText := aws.StringValue(output) + actualPolicyText := aws.ToString(output) equivalent, err := awspolicy.PoliciesAreEquivalent(actualPolicyText, expectedPolicyText) if err != nil { @@ -536,7 +532,7 @@ func testAccCheckExternalKeyHasPolicy(ctx context.Context, name string, expected func testAccCheckExternalKeyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_kms_external_key" { @@ -560,20 +556,16 @@ func testAccCheckExternalKeyDestroy(ctx context.Context) resource.TestCheckFunc } } -func testAccCheckExternalKeyExists(ctx context.Context, name string, key *kms.KeyMetadata) resource.TestCheckFunc { +func testAccCheckExternalKeyExists(ctx context.Context, n string, v *awstypes.KeyMetadata) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", name) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No KMS External Key ID is set") + return fmt.Errorf("Not found: %s", n) } - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) - outputRaw, err := tfresource.RetryWhenNotFound(ctx, tfkms.PropagationTimeout, func() (interface{}, error) { + outputRaw, err := tfresource.RetryWhenNotFound(ctx, tfkms.KMSPropagationTimeout, func() (interface{}, error) { return tfkms.FindKeyByID(ctx, conn, rs.Primary.ID) }) @@ -581,15 +573,15 @@ func testAccCheckExternalKeyExists(ctx context.Context, name string, key *kms.Ke return err } - *key = *(outputRaw.(*kms.KeyMetadata)) + *v = *(outputRaw.(*awstypes.KeyMetadata)) return nil } } -func testAccCheckExternalKeyNotRecreated(i, j *kms.KeyMetadata) resource.TestCheckFunc { +func testAccCheckExternalKeyNotRecreated(i, j *awstypes.KeyMetadata) resource.TestCheckFunc { return func(s *terraform.State) error { - if !aws.TimeValue(i.CreationDate).Equal(aws.TimeValue(j.CreationDate)) { + if !aws.ToTime(i.CreationDate).Equal(aws.ToTime(j.CreationDate)) { return fmt.Errorf("KMS External Key recreated") } @@ -597,9 +589,9 @@ func testAccCheckExternalKeyNotRecreated(i, j *kms.KeyMetadata) resource.TestChe } } -func testAccCheckExternalKeyRecreated(i, j *kms.KeyMetadata) resource.TestCheckFunc { +func testAccCheckExternalKeyRecreated(i, j *awstypes.KeyMetadata) resource.TestCheckFunc { return func(s *terraform.State) error { - if aws.TimeValue(i.CreationDate).Equal(aws.TimeValue(j.CreationDate)) { + if aws.ToTime(i.CreationDate).Equal(aws.ToTime(j.CreationDate)) { return fmt.Errorf("KMS External Key not recreated") } diff --git a/internal/service/kms/find.go b/internal/service/kms/find.go deleted file mode 100644 index 1a88f277ec62..000000000000 --- a/internal/service/kms/find.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package kms - -import ( - "context" - "fmt" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func FindAliasByName(ctx context.Context, conn *kms.KMS, name string) (*kms.AliasListEntry, error) { - input := &kms.ListAliasesInput{} - var output *kms.AliasListEntry - - err := conn.ListAliasesPagesWithContext(ctx, input, func(page *kms.ListAliasesOutput, lastPage bool) bool { - if page == nil { - return !lastPage - } - - for _, alias := range page.Aliases { - if aws.StringValue(alias.AliasName) == name { - output = alias - - return false - } - } - - return !lastPage - }) - - if err != nil { - return nil, err - } - - if output == nil { - return nil, &retry.NotFoundError{} - } - - return output, nil -} - -func FindCustomKeyStoreByID(ctx context.Context, conn *kms.KMS, in *kms.DescribeCustomKeyStoresInput) (*kms.CustomKeyStoresListEntry, error) { - out, err := conn.DescribeCustomKeyStoresWithContext(ctx, in) - - if tfawserr.ErrCodeEquals(err, kms.ErrCodeCustomKeyStoreNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } - } - if err != nil { - return nil, err - } - - if out == nil || out.CustomKeyStores[0] == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out.CustomKeyStores[0], nil -} - -func FindKeyByID(ctx context.Context, conn *kms.KMS, id string) (*kms.KeyMetadata, error) { - input := &kms.DescribeKeyInput{ - KeyId: aws.String(id), - } - - output, err := conn.DescribeKeyWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil || output.KeyMetadata == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - keyMetadata := output.KeyMetadata - - // Once the CMK is in the pending (replica) deletion state Terraform considers it logically deleted. - if state := aws.StringValue(keyMetadata.KeyState); state == kms.KeyStatePendingDeletion || state == kms.KeyStatePendingReplicaDeletion { - return nil, &retry.NotFoundError{ - Message: state, - LastRequest: input, - } - } - - return keyMetadata, nil -} - -func findDefaultKey(ctx context.Context, client *conns.AWSClient, service, region string) (string, error) { - conn := client.KMSConnForRegion(ctx, region) - - k, err := FindKeyByID(ctx, conn, fmt.Sprintf("alias/aws/%s", service)) //default key - if err != nil { - return "", fmt.Errorf("finding default key: %s", err) - } - - return aws.StringValue(k.Arn), nil -} - -func FindKeyPolicyByKeyIDAndPolicyName(ctx context.Context, conn *kms.KMS, keyID, policyName string) (*string, error) { - input := &kms.GetKeyPolicyInput{ - KeyId: aws.String(keyID), - PolicyName: aws.String(policyName), - } - - output, err := conn.GetKeyPolicyWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.Policy, nil -} - -func FindKeyRotationEnabledByKeyID(ctx context.Context, conn *kms.KMS, keyID string) (*bool, error) { - input := &kms.GetKeyRotationStatusInput{ - KeyId: aws.String(keyID), - } - - output, err := conn.GetKeyRotationStatusWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.KeyRotationEnabled, nil -} diff --git a/internal/service/kms/generate.go b/internal/service/kms/generate.go index 9f3fb0d87fb1..5e95235996f7 100644 --- a/internal/service/kms/generate.go +++ b/internal/service/kms/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsOp=ListResourceTags -ListTagsOpPaginated -ListTagsInIDElem=KeyId -ServiceTagsSlice -TagInIDElem=KeyId -TagTypeKeyElem=TagKey -TagTypeValElem=TagValue -UpdateTags -Wait -WaitContinuousOccurence 5 -WaitMinTimeout 1s -WaitTimeout 10m -ParentNotFoundErrCode=NotFoundException +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ListTagsOp=ListResourceTags -ListTagsOpPaginated -ListTagsInIDElem=KeyId -ServiceTagsSlice -TagInIDElem=KeyId -TagTypeKeyElem=TagKey -TagTypeValElem=TagValue -UpdateTags -Wait -WaitContinuousOccurence 5 -WaitMinTimeout 1s -WaitTimeout 10m -ParentNotFoundErrCode=NotFoundException //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/kms/grant.go b/internal/service/kms/grant.go index 91f24fc556d2..d0db0eeaf813 100644 --- a/internal/service/kms/grant.go +++ b/internal/service/kms/grant.go @@ -8,28 +8,32 @@ import ( "context" "fmt" "log" - "sort" + "slices" "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/arn" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + tfmaps "github.com/hashicorp/terraform-provider-aws/internal/maps" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_kms_grant") -func ResourceGrant() *schema.Resource { +// @SDKResource("aws_kms_grant", name="Grant") +func resourceGrant() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceGrantCreate, ReadWithoutTimeout: resourceGrantRead, @@ -37,13 +41,14 @@ func ResourceGrant() *schema.Resource { Importer: &schema.ResourceImporter{ StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - keyId, grantId, err := GrantParseResourceID(d.Id()) + keyID, grantID, err := grantParseResourceID(d.Id()) if err != nil { return nil, err } - d.Set("key_id", keyId) - d.Set("grant_id", grantId) - d.SetId(fmt.Sprintf("%s:%s", keyId, grantId)) + + d.SetId(grantCreateResourceID(keyID, grantID)) + d.Set("key_id", keyID) + d.Set("grant_id", grantID) return []*schema.ResourceData{d}, nil }, @@ -74,7 +79,6 @@ func ResourceGrant() *schema.Resource { }, Set: resourceGrantConstraintsHash, }, - "grant_creation_tokens": { Type: schema.TypeSet, Optional: true, @@ -114,8 +118,8 @@ func ResourceGrant() *schema.Resource { Required: true, ForceNew: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(kms.GrantOperation_Values(), false), + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.GrantOperation](), }, }, "retire_on_delete": { @@ -139,13 +143,13 @@ func ResourceGrant() *schema.Resource { func resourceGrantCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) keyID := d.Get("key_id").(string) input := &kms.CreateGrantInput{ GranteePrincipal: aws.String(d.Get("grantee_principal").(string)), KeyId: aws.String(keyID), - Operations: flex.ExpandStringSet(d.Get("operations").(*schema.Set)), + Operations: flex.ExpandStringyValueSet[awstypes.GrantOperation](d.Get("operations").(*schema.Set)), } if v, ok := d.GetOk("constraints"); ok && v.(*schema.Set).Len() > 0 { @@ -157,7 +161,7 @@ func resourceGrantCreate(ctx context.Context, d *schema.ResourceData, meta inter } if v, ok := d.GetOk("grant_creation_tokens"); ok && v.(*schema.Set).Len() > 0 { - input.GrantTokens = flex.ExpandStringSet(v.(*schema.Set)) + input.GrantTokens = flex.ExpandStringValueSet(v.(*schema.Set)) } if v, ok := d.GetOk("name"); ok { @@ -171,37 +175,32 @@ func resourceGrantCreate(ctx context.Context, d *schema.ResourceData, meta inter // Error Codes: https://docs.aws.amazon.com/sdk-for-go/api/service/kms/#KMS.CreateGrant // Under some circumstances a newly created IAM Role doesn't show up and causes // an InvalidArnException to be thrown. - outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 3*time.Minute, func() (interface{}, error) { - return conn.CreateGrantWithContext(ctx, input) - }, kms.ErrCodeDependencyTimeoutException, kms.ErrCodeInternalException, kms.ErrCodeInvalidArnException) + outputRaw, err := tfresource.RetryWhenIsOneOf3[*awstypes.DependencyTimeoutException, *awstypes.KMSInternalException, *awstypes.InvalidArnException](ctx, kmsPropagationTimeout, func() (interface{}, error) { + return conn.CreateGrant(ctx, input) + }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS Grant for Key (%s): %s", keyID, err) } output := outputRaw.(*kms.CreateGrantOutput) - grantID := aws.StringValue(output.GrantId) - GrantCreateResourceID(keyID, grantID) - d.SetId(GrantCreateResourceID(keyID, grantID)) + grantID := aws.ToString(output.GrantId) + d.SetId(grantCreateResourceID(keyID, grantID)) d.Set("grant_token", output.GrantToken) return append(diags, resourceGrantRead(ctx, d, meta)...) } func resourceGrantRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - const ( - timeout = 3 * time.Minute - ) var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - keyID, grantID, err := GrantParseResourceID(d.Id()) + conn := meta.(*conns.AWSClient).KMSClient(ctx) + keyID, grantID, err := grantParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "parsing resource ID: %s", err) + return sdkdiag.AppendFromErr(diags, err) } - grant, err := findGrantByTwoPartKeyWithRetry(ctx, conn, keyID, grantID, timeout) + grant, err := findGrantByTwoPartKeyWithRetry(ctx, conn, keyID, grantID, kmsPropagationTimeout) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS Grant (%s) not found, removing from state", d.Id()) @@ -223,10 +222,10 @@ func resourceGrantRead(ctx context.Context, d *schema.ResourceData, meta interfa d.Set("grantee_principal", grant.GranteePrincipal) } d.Set("key_id", keyID) - if aws.StringValue(grant.Name) != "" { + if aws.ToString(grant.Name) != "" { d.Set("name", grant.Name) } - d.Set("operations", aws.StringValueSlice(grant.Operations)) + d.Set("operations", grant.Operations) if grant.RetiringPrincipal != nil { // nosemgrep:ci.helper-schema-ResourceData-Set-extraneous-nil-check d.Set("retiring_principal", grant.RetiringPrincipal) } @@ -236,29 +235,28 @@ func resourceGrantRead(ctx context.Context, d *schema.ResourceData, meta interfa func resourceGrantDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) - - keyID, grantID, err := GrantParseResourceID(d.Id()) + conn := meta.(*conns.AWSClient).KMSClient(ctx) + keyID, grantID, err := grantParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "parsing resource ID: %s", err) + return sdkdiag.AppendFromErr(diags, err) } if d.Get("retire_on_delete").(bool) { log.Printf("[DEBUG] Retiring KMS Grant: %s", d.Id()) - _, err = conn.RetireGrantWithContext(ctx, &kms.RetireGrantInput{ + _, err = conn.RetireGrant(ctx, &kms.RetireGrantInput{ GrantId: aws.String(grantID), KeyId: aws.String(keyID), }) } else { log.Printf("[DEBUG] Revoking KMS Grant: %s", d.Id()) - _, err = conn.RevokeGrantWithContext(ctx, &kms.RevokeGrantInput{ + _, err = conn.RevokeGrant(ctx, &kms.RevokeGrantInput{ GrantId: aws.String(grantID), KeyId: aws.String(keyID), }) } - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } @@ -266,8 +264,8 @@ func resourceGrantDelete(ctx context.Context, d *schema.ResourceData, meta inter return sdkdiag.AppendErrorf(diags, "deleting KMS Grant (%s): %s", d.Id(), err) } - _, err = tfresource.RetryUntilNotFound(ctx, 3*time.Minute, func() (interface{}, error) { - return FindGrantByTwoPartKey(ctx, conn, keyID, grantID) + _, err = tfresource.RetryUntilNotFound(ctx, kmsPropagationTimeout, func() (interface{}, error) { + return findGrantByTwoPartKey(ctx, conn, keyID, grantID) }) if err != nil { @@ -277,56 +275,60 @@ func resourceGrantDelete(ctx context.Context, d *schema.ResourceData, meta inter return diags } -func FindGrantByTwoPartKey(ctx context.Context, conn *kms.KMS, keyID, grantID string) (*kms.GrantListEntry, error) { - input := &kms.ListGrantsInput{ - KeyId: aws.String(keyID), - Limit: aws.Int64(100), +func findGrant(ctx context.Context, conn *kms.Client, input *kms.ListGrantsInput, filter tfslices.Predicate[*awstypes.GrantListEntry]) (*awstypes.GrantListEntry, error) { + output, err := findGrants(ctx, conn, input, filter) + + if err != nil { + return nil, err } - var output *kms.GrantListEntry - err := conn.ListGrantsPagesWithContext(ctx, input, func(page *kms.ListGrantsResponse, lastPage bool) bool { - if page == nil { - return !lastPage - } + return tfresource.AssertSingleValueResult(output) +} - for _, v := range page.Grants { - if v == nil { - continue - } +func findGrants(ctx context.Context, conn *kms.Client, input *kms.ListGrantsInput, filter tfslices.Predicate[*awstypes.GrantListEntry]) ([]awstypes.GrantListEntry, error) { + var output []awstypes.GrantListEntry - if aws.StringValue(v.GrantId) == grantID { - output = v + pages := kms.NewListGrantsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - return false + if errs.IsA[*awstypes.NotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } } - return !lastPage - }) + if err != nil { + return nil, err + } - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, + for _, v := range page.Grants { + if filter(&v) { + output = append(output, v) + } } } - if err != nil { - return nil, err - } + return output, nil +} - if output == nil { - return nil, tfresource.NewEmptyResultError(input) +func findGrantByTwoPartKey(ctx context.Context, conn *kms.Client, keyID, grantID string) (*awstypes.GrantListEntry, error) { + input := &kms.ListGrantsInput{ + KeyId: aws.String(keyID), + Limit: aws.Int32(100), } - return output, nil + return findGrant(ctx, conn, input, func(v *awstypes.GrantListEntry) bool { + return aws.ToString(v.GrantId) == grantID + }) } -func findGrantByTwoPartKeyWithRetry(ctx context.Context, conn *kms.KMS, keyID, grantID string, timeout time.Duration) (*kms.GrantListEntry, error) { - var output *kms.GrantListEntry +func findGrantByTwoPartKeyWithRetry(ctx context.Context, conn *kms.Client, keyID, grantID string, timeout time.Duration) (*awstypes.GrantListEntry, error) { + var output *awstypes.GrantListEntry err := retry.RetryContext(ctx, timeout, func() *retry.RetryError { - grant, err := FindGrantByTwoPartKey(ctx, conn, keyID, grantID) + grant, err := findGrantByTwoPartKey(ctx, conn, keyID, grantID) if tfresource.NotFound(err) { return retry.RetryableError(err) @@ -336,13 +338,13 @@ func findGrantByTwoPartKeyWithRetry(ctx context.Context, conn *kms.KMS, keyID, g return retry.NonRetryableError(err) } - if principal := aws.StringValue(grant.GranteePrincipal); principal != "" { + if principal := aws.ToString(grant.GranteePrincipal); principal != "" { if !arn.IsARN(principal) && !verify.IsServicePrincipal(principal) { return retry.RetryableError(fmt.Errorf("grantee principal (%s) is invalid. Perhaps the principal has been deleted or recreated", principal)) } } - if principal := aws.StringValue(grant.RetiringPrincipal); principal != "" { + if principal := aws.ToString(grant.RetiringPrincipal); principal != "" { if !arn.IsARN(principal) && !verify.IsServicePrincipal(principal) { return retry.RetryableError(fmt.Errorf("retiring principal (%s) is invalid. Perhaps the principal has been deleted or recreated", principal)) } @@ -354,7 +356,7 @@ func findGrantByTwoPartKeyWithRetry(ctx context.Context, conn *kms.KMS, keyID, g }) if tfresource.TimedOut(err) { - output, err = FindGrantByTwoPartKey(ctx, conn, keyID, grantID) + output, err = findGrantByTwoPartKey(ctx, conn, keyID, grantID) } if err != nil { @@ -387,118 +389,114 @@ func grantConstraintsIsValid(constraints *schema.Set) bool { return constraintCount <= 1 } -func expandGrantConstraints(configured *schema.Set) *kms.GrantConstraints { - if len(configured.List()) < 1 { +func expandGrantConstraints(tfSet *schema.Set) *awstypes.GrantConstraints { + if len(tfSet.List()) < 1 { return nil } - var constraint kms.GrantConstraints + apiObject := &awstypes.GrantConstraints{} - for _, raw := range configured.List() { - data := raw.(map[string]interface{}) - if contextEq, ok := data["encryption_context_equals"]; ok { - constraint.SetEncryptionContextEquals(flex.ExpandStringMap(contextEq.(map[string]interface{}))) + for _, tfMapRaw := range tfSet.List() { + tfMap := tfMapRaw.(map[string]interface{}) + + if v, ok := tfMap["encryption_context_equals"]; ok { + apiObject.EncryptionContextEquals = flex.ExpandStringValueMap(v.(map[string]interface{})) } - if contextSub, ok := data["encryption_context_subset"]; ok { - constraint.SetEncryptionContextSubset(flex.ExpandStringMap(contextSub.(map[string]interface{}))) + + if v, ok := tfMap["encryption_context_subset"]; ok { + apiObject.EncryptionContextSubset = flex.ExpandStringValueMap(v.(map[string]interface{})) } } - return &constraint + return apiObject } -func sortStringMapKeys(m map[string]*string) []string { - keys := make([]string, 0) - for k := range m { - keys = append(keys, k) +func flattenGrantConstraints(apiObject *awstypes.GrantConstraints) *schema.Set { + tfSet := schema.NewSet(resourceGrantConstraintsHash, []interface{}{}) + + if apiObject == nil { + return tfSet } - sort.Strings(keys) - return keys + tfMap := make(map[string]interface{}) + + if len(apiObject.EncryptionContextEquals) > 0 { + tfMap["encryption_context_equals"] = flex.FlattenStringValueMap(apiObject.EncryptionContextEquals) + } + + if len(apiObject.EncryptionContextSubset) > 0 { + tfMap["encryption_context_subset"] = flex.FlattenStringValueMap(apiObject.EncryptionContextSubset) + } + + tfSet.Add(tfMap) + + return tfSet } // NB: For the constraint hash to be deterministic the order in which // print the keys and values of the encryption context maps needs to be // determistic, so sort them. -func sortedConcatStringMap(m map[string]*string) string { - var strList []string - mapKeys := sortStringMapKeys(m) - for _, key := range mapKeys { - strList = append(strList, key, *m[key]) +func sortedConcatStringMap(m map[string]string) string { + keys := tfmaps.Keys(m) + slices.Sort(keys) + + var elems []string + for _, key := range keys { + elems = append(elems, key, m[key]) } - return strings.Join(strList, "-") + + return strings.Join(elems, "-") } // The hash needs to encapsulate what type of constraint it is // as well as the keys and values of the constraint. func resourceGrantConstraintsHash(v interface{}) int { var buf bytes.Buffer - m, castOk := v.(map[string]interface{}) - if !castOk { + + tfMap, ok := v.(map[string]interface{}) + if !ok { return 0 } - if v, ok := m["encryption_context_equals"]; ok { + if v, ok := tfMap["encryption_context_equals"]; ok { if len(v.(map[string]interface{})) > 0 { - buf.WriteString(fmt.Sprintf("encryption_context_equals-%s-", sortedConcatStringMap(flex.ExpandStringMap(v.(map[string]interface{}))))) + buf.WriteString(fmt.Sprintf("encryption_context_equals-%s-", sortedConcatStringMap(flex.ExpandStringValueMap(v.(map[string]interface{}))))) } } - if v, ok := m["encryption_context_subset"]; ok { + if v, ok := tfMap["encryption_context_subset"]; ok { if len(v.(map[string]interface{})) > 0 { - buf.WriteString(fmt.Sprintf("encryption_context_subset-%s-", sortedConcatStringMap(flex.ExpandStringMap(v.(map[string]interface{}))))) + buf.WriteString(fmt.Sprintf("encryption_context_subset-%s-", sortedConcatStringMap(flex.ExpandStringValueMap(v.(map[string]interface{}))))) } } return create.StringHashcode(buf.String()) } -func flattenGrantConstraints(constraint *kms.GrantConstraints) *schema.Set { - constraints := schema.NewSet(resourceGrantConstraintsHash, []interface{}{}) - if constraint == nil { - return constraints - } - - m := make(map[string]interface{}) - if constraint.EncryptionContextEquals != nil { - if len(constraint.EncryptionContextEquals) > 0 { - m["encryption_context_equals"] = flex.FlattenStringMap(constraint.EncryptionContextEquals) - } - } - if constraint.EncryptionContextSubset != nil { - if len(constraint.EncryptionContextSubset) > 0 { - m["encryption_context_subset"] = flex.FlattenStringMap(constraint.EncryptionContextSubset) - } - } - constraints.Add(m) - - return constraints -} - -const grantIDSeparator = ":" +const grantResourceIDSeparator = ":" -func GrantCreateResourceID(keyID, grantID string) string { +func grantCreateResourceID(keyID, grantID string) string { parts := []string{keyID, grantID} - id := strings.Join(parts, grantIDSeparator) + id := strings.Join(parts, grantResourceIDSeparator) return id } -func GrantParseResourceID(id string) (string, string, error) { +func grantParseResourceID(id string) (string, string, error) { if arn.IsARN(id) { arnParts := strings.Split(id, "/") if len(arnParts) != 2 { - return "", "", fmt.Errorf("unexpected format of ARN (%q), expected KeyID:GrantID", id) + return "", "", fmt.Errorf("unexpected format of ARN (%[1]s), expected KeyID%[2]sGrantID", id, grantResourceIDSeparator) } arnPrefix := arnParts[0] - parts := strings.Split(arnParts[1], grantIDSeparator) + parts := strings.Split(arnParts[1], grantResourceIDSeparator) if len(parts) != 2 { - return "", "", fmt.Errorf("unexpected format of ID (%q), expected KeyID:GrantID", id) + return "", "", fmt.Errorf("unexpected format of ID (%[1]s), expected KeyID%[2]sGrantID", id, grantResourceIDSeparator) } return fmt.Sprintf("%s/%s", arnPrefix, parts[0]), parts[1], nil } else { - parts := strings.Split(id, grantIDSeparator) + parts := strings.Split(id, grantResourceIDSeparator) if len(parts) != 2 { - return "", "", fmt.Errorf("unexpected format of ID (%q), expected KeyID:GrantID", id) + return "", "", fmt.Errorf("unexpected format of ID (%[1]s), expected KeyID%[2]sGrantID", id, grantResourceIDSeparator) } return parts[0], parts[1], nil } diff --git a/internal/service/kms/grant_test.go b/internal/service/kms/grant_test.go index 017c43a50965..b99d98854108 100644 --- a/internal/service/kms/grant_test.go +++ b/internal/service/kms/grant_test.go @@ -314,7 +314,7 @@ func TestAccKMSGrant_service(t *testing.T) { func testAccCheckGrantDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_kms_grant" { @@ -322,7 +322,6 @@ func testAccCheckGrantDestroy(ctx context.Context) resource.TestCheckFunc { } keyID, grantID, err := tfkms.GrantParseResourceID(rs.Primary.ID) - if err != nil { return err } @@ -337,7 +336,7 @@ func testAccCheckGrantDestroy(ctx context.Context) resource.TestCheckFunc { return err } - return fmt.Errorf("KMS Grant still exists: %s", rs.Primary.ID) + return fmt.Errorf("KMS Grant %s still exists", rs.Primary.ID) } return nil @@ -351,17 +350,12 @@ func testAccCheckGrantExists(ctx context.Context, n string) resource.TestCheckFu return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No KMS Grant ID is set") - } - keyID, grantID, err := tfkms.GrantParseResourceID(rs.Primary.ID) - if err != nil { return err } - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) _, err = tfkms.FindGrantByTwoPartKey(ctx, conn, keyID, grantID) diff --git a/internal/service/kms/key.go b/internal/service/kms/key.go index 648dc6bfaffe..03057c0a5f19 100644 --- a/internal/service/kms/key.go +++ b/internal/service/kms/key.go @@ -9,9 +9,10 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" + awspolicy "github.com/hashicorp/awspolicyequivalence" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -19,6 +20,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/logging" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -29,7 +32,7 @@ import ( // @SDKResource("aws_kms_key", name="Key") // @Tags(identifierAttribute="id") -func ResourceKey() *schema.Resource { +func resourceKey() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceKeyCreate, ReadWithoutTimeout: resourceKeyRead, @@ -41,7 +44,7 @@ func ResourceKey() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(2 * time.Minute), + Create: schema.DefaultTimeout(iamPropagationTimeout), }, CustomizeDiff: verify.SetTagsDiff, @@ -63,11 +66,11 @@ func ResourceKey() *schema.Resource { ValidateFunc: validation.StringLenBetween(1, 22), }, "customer_master_key_spec": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: kms.CustomerMasterKeySpecSymmetricDefault, - ValidateFunc: validation.StringInSlice(kms.CustomerMasterKeySpec_Values(), false), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: awstypes.CustomerMasterKeySpecSymmetricDefault, + ValidateDiagFunc: enum.Validate[awstypes.CustomerMasterKeySpec](), }, "deletion_window_in_days": { Type: schema.TypeInt, @@ -95,11 +98,11 @@ func ResourceKey() *schema.Resource { Computed: true, }, "key_usage": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: kms.KeyUsageTypeEncryptDecrypt, - ValidateFunc: validation.StringInSlice(kms.KeyUsageType_Values(), false), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: awstypes.KeyUsageTypeEncryptDecrypt, + ValidateDiagFunc: enum.Validate[awstypes.KeyUsageType](), }, "multi_region": { Type: schema.TypeBool, @@ -134,12 +137,12 @@ func ResourceKey() *schema.Resource { func resourceKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) input := &kms.CreateKeyInput{ - BypassPolicyLockoutSafetyCheck: aws.Bool(d.Get("bypass_policy_lockout_safety_check").(bool)), - CustomerMasterKeySpec: aws.String(d.Get("customer_master_key_spec").(string)), - KeyUsage: aws.String(d.Get("key_usage").(string)), + BypassPolicyLockoutSafetyCheck: d.Get("bypass_policy_lockout_safety_check").(bool), + CustomerMasterKeySpec: awstypes.CustomerMasterKeySpec(d.Get("customer_master_key_spec").(string)), + KeyUsage: awstypes.KeyUsageType(d.Get("key_usage").(string)), Tags: getTagsIn(ctx), } @@ -154,19 +157,19 @@ func resourceKeyCreate(ctx context.Context, d *schema.ResourceData, meta interfa if v, ok := d.GetOk("policy"); ok { p, err := structure.NormalizeJsonString(v.(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", p, err) + return sdkdiag.AppendFromErr(diags, err) } - input.Policy = aws.String(v.(string)) + input.Policy = aws.String(p) } if v, ok := d.GetOk("custom_key_store_id"); ok { - input.Origin = aws.String(kms.OriginTypeAwsCloudhsm) + input.Origin = awstypes.OriginTypeAwsCloudhsm input.CustomKeyStoreId = aws.String(v.(string)) } if v, ok := d.GetOk("xks_key_id"); ok { - input.Origin = aws.String(kms.OriginTypeExternalKeyStore) + input.Origin = awstypes.OriginTypeExternalKeyStore input.XksKeyId = aws.String(v.(string)) } @@ -174,40 +177,40 @@ func resourceKeyCreate(ctx context.Context, d *schema.ResourceData, meta interfa // The KMS service's awareness of principals is limited by "eventual consistency". // They acknowledge this here: // http://docs.aws.amazon.com/kms/latest/APIReference/API_CreateKey.html - output, err := WaitIAMPropagation(ctx, d.Timeout(schema.TimeoutCreate), func() (*kms.CreateKeyOutput, error) { - return conn.CreateKeyWithContext(ctx, input) + output, err := waitIAMPropagation(ctx, d.Timeout(schema.TimeoutCreate), func() (*kms.CreateKeyOutput, error) { + return conn.CreateKey(ctx, input) }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS Key: %s", err) } - d.SetId(aws.StringValue(output.KeyMetadata.KeyId)) + d.SetId(aws.ToString(output.KeyMetadata.KeyId)) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) if enableKeyRotation := d.Get("enable_key_rotation").(bool); enableKeyRotation { - if err := updateKeyRotationEnabled(ctx, conn, d.Id(), enableKeyRotation); err != nil { - return sdkdiag.AppendErrorf(diags, "creating KMS Key (%s): %s", d.Id(), err) + if err := updateKeyRotationEnabled(ctx, conn, "KMS Key", d.Id(), enableKeyRotation); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if enabled := d.Get("is_enabled").(bool); !enabled { - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "creating KMS Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } // Wait for propagation since KMS is eventually consistent. if v, ok := d.GetOk("policy"); ok { - if err := WaitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) policy propagation: %s", d.Id(), err) + if err := waitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) policy update: %s", d.Id(), err) } } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) tag propagation: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) tag update: %s", d.Id(), err) } } @@ -216,23 +219,23 @@ func resourceKeyCreate(ctx context.Context, d *schema.ResourceData, meta interfa func resourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - key, err := findKey(ctx, conn, d.Id(), d.IsNewResource()) + key, err := findKeyInfo(ctx, conn, d.Id(), d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS Key (%s) not found, removing from state", d.Id()) d.SetId("") return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Key (%s): %s", d.Id(), err) } - if aws.BoolValue(key.metadata.MultiRegion) && - aws.StringValue(key.metadata.MultiRegionConfiguration.MultiRegionKeyType) != kms.MultiRegionKeyTypePrimary { + if aws.ToBool(key.metadata.MultiRegion) && key.metadata.MultiRegionConfiguration.MultiRegionKeyType != awstypes.MultiRegionKeyTypePrimary { return sdkdiag.AppendErrorf(diags, "KMS Key (%s) is not a multi-Region primary key", d.Id()) } @@ -245,7 +248,6 @@ func resourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interface d.Set("key_id", key.metadata.KeyId) d.Set("key_usage", key.metadata.KeyUsage) d.Set("multi_region", key.metadata.MultiRegion) - if key.metadata.XksKeyConfiguration != nil { d.Set("xks_key_id", key.metadata.XksKeyConfiguration.Id) } else { @@ -254,7 +256,7 @@ func resourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interface policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), key.policy) if err != nil { - return sdkdiag.AppendErrorf(diags, "while setting policy (%s), encountered: %s", key.policy, err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -266,39 +268,39 @@ func resourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interface func resourceKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) if hasChange, enabled := d.HasChange("is_enabled"), d.Get("is_enabled").(bool); hasChange && enabled { // Enable before any attributes are modified. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } - if hasChange, enableKeyRotation := d.HasChange("enable_key_rotation"), d.Get("enable_key_rotation").(bool); hasChange { - if err := updateKeyRotationEnabled(ctx, conn, d.Id(), enableKeyRotation); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Key (%s): %s", d.Id(), err) + if hasChange, enable := d.HasChange("enable_key_rotation"), d.Get("enable_key_rotation").(bool); hasChange { + if err := updateKeyRotationEnabled(ctx, conn, "KMS Key", d.Id(), enable); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } - if d.HasChange("description") { - if err := updateKeyDescription(ctx, conn, d.Id(), d.Get("description").(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Key (%s): %s", d.Id(), err) + if hasChange, description := d.HasChange("description"), d.Get("description").(string); hasChange { + if err := updateKeyDescription(ctx, conn, "KMS Key", d.Id(), description); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } - if d.HasChange("policy") { - if err := updateKeyPolicy(ctx, conn, d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Key (%s): %s", d.Id(), err) + if hasChange, policy, bypass := d.HasChange("policy"), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool); hasChange { + if err := updateKeyPolicy(ctx, conn, "KMS Key", d.Id(), policy, bypass); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if hasChange, enabled := d.HasChange("is_enabled"), d.Get("is_enabled").(bool); hasChange && !enabled { // Only disable after all attributes have been modified because we cannot modify disabled keys. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -307,7 +309,7 @@ func resourceKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interfa func resourceKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) @@ -316,17 +318,17 @@ func resourceKeyDelete(ctx context.Context, d *schema.ResourceData, meta interfa } if v, ok := d.GetOk("deletion_window_in_days"); ok { - input.PendingWindowInDays = aws.Int64(int64(v.(int))) + input.PendingWindowInDays = aws.Int32(int32(v.(int))) } - log.Printf("[DEBUG] Deleting KMS Key: (%s)", d.Id()) - _, err := conn.ScheduleKeyDeletionWithContext(ctx, input) + log.Printf("[DEBUG] Deleting KMS Key: %s", d.Id()) + _, err := conn.ScheduleKeyDeletion(ctx, input) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } - if tfawserr.ErrMessageContains(err, kms.ErrCodeInvalidStateException, "is pending deletion") { + if errs.IsAErrorMessageContains[*awstypes.KMSInvalidStateException](err, "is pending deletion") { return diags } @@ -334,46 +336,46 @@ func resourceKeyDelete(ctx context.Context, d *schema.ResourceData, meta interfa return sdkdiag.AppendErrorf(diags, "deleting KMS Key (%s): %s", d.Id(), err) } - if _, err := WaitKeyDeleted(ctx, conn, d.Id()); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) to delete: %s", d.Id(), err) + if _, err := waitKeyDeleted(ctx, conn, d.Id()); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) delete: %s", d.Id(), err) } return diags } -type kmsKey struct { - metadata *kms.KeyMetadata +type kmsKeyInfo struct { + metadata *awstypes.KeyMetadata policy string rotation *bool - tags []*kms.Tag + tags []awstypes.Tag } -func findKey(ctx context.Context, conn *kms.KMS, keyID string, isNewResource bool) (*kmsKey, error) { +func findKeyInfo(ctx context.Context, conn *kms.Client, keyID string, isNewResource bool) (*kmsKeyInfo, error) { // Wait for propagation since KMS is eventually consistent. - outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, kmsPropagationTimeout, func() (interface{}, error) { var err error - var key kmsKey + var key kmsKeyInfo - key.metadata, err = FindKeyByID(ctx, conn, keyID) + key.metadata, err = findKeyByID(ctx, conn, keyID) if err != nil { return nil, fmt.Errorf("reading KMS Key (%s): %w", keyID, err) } - policy, err := FindKeyPolicyByKeyIDAndPolicyName(ctx, conn, keyID, PolicyNameDefault) + policy, err := findKeyPolicyByTwoPartKey(ctx, conn, keyID, policyNameDefault) if err != nil { return nil, fmt.Errorf("reading KMS Key (%s) policy: %w", keyID, err) } - key.policy, err = structure.NormalizeJsonString(aws.StringValue(policy)) + key.policy, err = structure.NormalizeJsonString(aws.ToString(policy)) if err != nil { return nil, fmt.Errorf("policy contains invalid JSON: %w", err) } - if aws.StringValue(key.metadata.Origin) == kms.OriginTypeAwsKms { - key.rotation, err = FindKeyRotationEnabledByKeyID(ctx, conn, keyID) + if key.metadata.Origin == awstypes.OriginTypeAwsKms { + key.rotation, err = findKeyRotationEnabledByKeyID(ctx, conn, keyID) if err != nil { return nil, fmt.Errorf("reading KMS Key (%s) rotation enabled: %w", keyID, err) @@ -382,7 +384,7 @@ func findKey(ctx context.Context, conn *kms.KMS, keyID string, isNewResource boo tags, err := listTags(ctx, conn, keyID) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return nil, &retry.NotFoundError{LastError: err} } @@ -399,45 +401,150 @@ func findKey(ctx context.Context, conn *kms.KMS, keyID string, isNewResource boo return nil, err } - return outputRaw.(*kmsKey), nil + return outputRaw.(*kmsKeyInfo), nil +} + +func findKeyByID(ctx context.Context, conn *kms.Client, keyID string, optFns ...func(*kms.Options)) (*awstypes.KeyMetadata, error) { + input := &kms.DescribeKeyInput{ + KeyId: aws.String(keyID), + } + + output, err := findKey(ctx, conn, input, optFns...) + + if err != nil { + return nil, err + } + + // Once the CMK is in the pending (replica) deletion state Terraform considers it logically deleted. + if state := output.KeyState; state == awstypes.KeyStatePendingDeletion || state == awstypes.KeyStatePendingReplicaDeletion { + return nil, &retry.NotFoundError{ + Message: string(state), + LastRequest: input, + } + } + + return output, nil +} + +func findKey(ctx context.Context, conn *kms.Client, input *kms.DescribeKeyInput, optFns ...func(*kms.Options)) (*awstypes.KeyMetadata, error) { + output, err := conn.DescribeKey(ctx, input, optFns...) + + if errs.IsA[*awstypes.NotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.KeyMetadata == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.KeyMetadata, nil +} + +func findDefaultKeyARNForService(ctx context.Context, conn *kms.Client, service, region string) (string, error) { + keyID := fmt.Sprintf("alias/aws/%s", service) + key, err := findKeyByID(ctx, conn, keyID, func(o *kms.Options) { + o.Region = region + }) + + if err != nil { + return "", fmt.Errorf("reading KMS Key (%s): %s", keyID, err) + } + + return aws.ToString(key.Arn), nil +} + +func findKeyPolicyByTwoPartKey(ctx context.Context, conn *kms.Client, keyID, policyName string) (*string, error) { + input := &kms.GetKeyPolicyInput{ + KeyId: aws.String(keyID), + PolicyName: aws.String(policyName), + } + + output, err := conn.GetKeyPolicy(ctx, input) + + if errs.IsA[*awstypes.NotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.Policy, nil +} + +func findKeyRotationEnabledByKeyID(ctx context.Context, conn *kms.Client, keyID string) (*bool, error) { + input := &kms.GetKeyRotationStatusInput{ + KeyId: aws.String(keyID), + } + + output, err := conn.GetKeyRotationStatus(ctx, input) + + if errs.IsA[*awstypes.NotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return aws.Bool(output.KeyRotationEnabled), nil } -func updateKeyDescription(ctx context.Context, conn *kms.KMS, keyID string, description string) error { +func updateKeyDescription(ctx context.Context, conn *kms.Client, resourceTypeName, keyID, description string) error { input := &kms.UpdateKeyDescriptionInput{ Description: aws.String(description), KeyId: aws.String(keyID), } - _, err := conn.UpdateKeyDescriptionWithContext(ctx, input) + _, err := conn.UpdateKeyDescription(ctx, input) + if err != nil { - return fmt.Errorf("updating description: %w", err) + return fmt.Errorf("updating %s (%s) description: %w", resourceTypeName, keyID, err) } // Wait for propagation since KMS is eventually consistent. - err = WaitKeyDescriptionPropagated(ctx, conn, keyID, description) - if err != nil { - return fmt.Errorf("updating description: waiting for completion: %w", err) + if err := waitKeyDescriptionPropagated(ctx, conn, keyID, description); err != nil { + return fmt.Errorf("waiting for %s (%s) description update: %w", resourceTypeName, keyID, err) } return nil } -func updateKeyEnabled(ctx context.Context, conn *kms.KMS, keyID string, enabled bool) error { +func updateKeyEnabled(ctx context.Context, conn *kms.Client, resourceTypeName, keyID string, enabled bool) error { var action string updateFunc := func() (interface{}, error) { var err error if enabled { - log.Printf("[DEBUG] Enabling KMS Key (%s)", keyID) action = "enabling" - _, err = conn.EnableKeyWithContext(ctx, &kms.EnableKeyInput{ + _, err = conn.EnableKey(ctx, &kms.EnableKeyInput{ KeyId: aws.String(keyID), }) } else { - log.Printf("[DEBUG] Disabling KMS Key (%s)", keyID) action = "disabling" - _, err = conn.DisableKeyWithContext(ctx, &kms.DisableKeyInput{ + _, err = conn.DisableKey(ctx, &kms.DisableKeyInput{ KeyId: aws.String(keyID), }) } @@ -445,22 +552,19 @@ func updateKeyEnabled(ctx context.Context, conn *kms.KMS, keyID string, enabled return nil, err } - _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, PropagationTimeout, updateFunc, kms.ErrCodeNotFoundException) - if err != nil { - return fmt.Errorf("%s KMS Key: %w", action, err) + if _, err := tfresource.RetryWhenIsA[*awstypes.NotFoundException](ctx, kmsPropagationTimeout, updateFunc); err != nil { + return fmt.Errorf("%s %s (%s): %w", action, resourceTypeName, keyID, err) } // Wait for propagation since KMS is eventually consistent. - err = WaitKeyStatePropagated(ctx, conn, keyID, enabled) - - if err != nil { - return fmt.Errorf("%s KMS Key: waiting for completion: %w", action, err) + if err := waitKeyStatePropagated(ctx, conn, keyID, enabled); err != nil { + return fmt.Errorf("waiting for %s (%s) update (enabled = %t): %w", resourceTypeName, keyID, enabled, err) } return nil } -func updateKeyPolicy(ctx context.Context, conn *kms.KMS, keyID string, policy string, bypassPolicyLockoutSafetyCheck bool) error { +func updateKeyPolicy(ctx context.Context, conn *kms.Client, resourceTypeName, keyID, policy string, bypassPolicyLockoutSafetyCheck bool) error { policy, err := structure.NormalizeJsonString(policy) if err != nil { return fmt.Errorf("policy contains invalid JSON: %w", err) @@ -470,45 +574,43 @@ func updateKeyPolicy(ctx context.Context, conn *kms.KMS, keyID string, policy st var err error input := &kms.PutKeyPolicyInput{ - BypassPolicyLockoutSafetyCheck: aws.Bool(bypassPolicyLockoutSafetyCheck), + BypassPolicyLockoutSafetyCheck: bypassPolicyLockoutSafetyCheck, KeyId: aws.String(keyID), Policy: aws.String(policy), - PolicyName: aws.String(PolicyNameDefault), + PolicyName: aws.String(policyNameDefault), } - _, err = conn.PutKeyPolicyWithContext(ctx, input) + _, err = conn.PutKeyPolicy(ctx, input) return nil, err } - _, err = tfresource.RetryWhenAWSErrCodeEquals(ctx, PropagationTimeout, updateFunc, kms.ErrCodeNotFoundException, kms.ErrCodeMalformedPolicyDocumentException) - if err != nil { - return fmt.Errorf("updating policy: %w", err) + if _, err := tfresource.RetryWhenIsOneOf2[*awstypes.NotFoundException, *awstypes.MalformedPolicyDocumentException](ctx, kmsPropagationTimeout, updateFunc); err != nil { + return fmt.Errorf("updating %s (%s) policy: %w", resourceTypeName, keyID, err) } // Wait for propagation since KMS is eventually consistent. - err = WaitKeyPolicyPropagated(ctx, conn, keyID, policy) - if err != nil { - return fmt.Errorf("updating policy: waiting for completion: %w", err) + if err := waitKeyPolicyPropagated(ctx, conn, keyID, policy); err != nil { + return fmt.Errorf("waiting for %s (%s) policy update: %w", resourceTypeName, keyID, err) } return nil } -func updateKeyRotationEnabled(ctx context.Context, conn *kms.KMS, keyID string, enabled bool) error { +func updateKeyRotationEnabled(ctx context.Context, conn *kms.Client, resourceTypeName, keyID string, enabled bool) error { var action string updateFunc := func() (interface{}, error) { var err error if enabled { - log.Printf("[DEBUG] Enabling KMS Key (%s) key rotation", keyID) - _, err = conn.EnableKeyRotationWithContext(ctx, &kms.EnableKeyRotationInput{ + action = "enabling" + _, err = conn.EnableKeyRotation(ctx, &kms.EnableKeyRotationInput{ KeyId: aws.String(keyID), }) } else { - log.Printf("[DEBUG] Disabling KMS Key (%s) key rotation", keyID) - _, err = conn.DisableKeyRotationWithContext(ctx, &kms.DisableKeyRotationInput{ + action = "disabling" + _, err = conn.DisableKeyRotation(ctx, &kms.DisableKeyRotationInput{ KeyId: aws.String(keyID), }) } @@ -516,17 +618,153 @@ func updateKeyRotationEnabled(ctx context.Context, conn *kms.KMS, keyID string, return nil, err } - _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, KeyRotationUpdatedTimeout, updateFunc, kms.ErrCodeNotFoundException, kms.ErrCodeDisabledException) - if err != nil { - return fmt.Errorf("%s key rotation: %w", action, err) + if _, err := tfresource.RetryWhenIsOneOf2[*awstypes.NotFoundException, *awstypes.DisabledException](ctx, keyRotationUpdatedTimeout, updateFunc); err != nil { + return fmt.Errorf("%s %s (%s) rotation: %w", action, resourceTypeName, keyID, err) } // Wait for propagation since KMS is eventually consistent. - err = WaitKeyRotationEnabledPropagated(ctx, conn, keyID, enabled) - - if err != nil { - return fmt.Errorf("%s key rotation: waiting for completion: %w", action, err) + if err := waitKeyRotationEnabledPropagated(ctx, conn, keyID, enabled); err != nil { + return fmt.Errorf("waiting for %s (%s) rotation update: %w", resourceTypeName, keyID, err) } return nil } + +func statusKeyState(ctx context.Context, conn *kms.Client, keyID string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findKeyByID(ctx, conn, keyID) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, string(output.KeyState), nil + } +} + +func waitKeyDescriptionPropagated(ctx context.Context, conn *kms.Client, keyID string, description string) error { + checkFunc := func() (bool, error) { + output, err := findKeyByID(ctx, conn, keyID) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + return aws.ToString(output.Description) == description, nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 5, + MinTimeout: 2 * time.Second, + } + const ( + timeout = 10 * time.Minute + ) + + return tfresource.WaitUntil(ctx, timeout, checkFunc, opts) +} + +func waitKeyDeleted(ctx context.Context, conn *kms.Client, keyID string) (*awstypes.KeyMetadata, error) { //nolint:unparam + const ( + timeout = 20 * time.Minute + ) + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.KeyStateDisabled, awstypes.KeyStateEnabled), + Target: []string{}, + Refresh: statusKeyState(ctx, conn, keyID), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.KeyMetadata); ok { + return output, err + } + + return nil, err +} + +func waitKeyPolicyPropagated(ctx context.Context, conn *kms.Client, keyID, policy string) error { + checkFunc := func() (bool, error) { + output, err := findKeyPolicyByTwoPartKey(ctx, conn, keyID, policyNameDefault) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + equivalent, err := awspolicy.PoliciesAreEquivalent(aws.ToString(output), policy) + + if err != nil { + return false, err + } + + return equivalent, nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 5, + MinTimeout: 1 * time.Second, + } + const ( + timeout = 10 * time.Minute + ) + + return tfresource.WaitUntil(ctx, timeout, checkFunc, opts) +} + +func waitKeyRotationEnabledPropagated(ctx context.Context, conn *kms.Client, keyID string, enabled bool) error { + checkFunc := func() (bool, error) { + output, err := findKeyRotationEnabledByKeyID(ctx, conn, keyID) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + return aws.ToBool(output) == enabled, nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 5, + MinTimeout: 1 * time.Second, + } + + return tfresource.WaitUntil(ctx, keyRotationUpdatedTimeout, checkFunc, opts) +} + +func waitKeyStatePropagated(ctx context.Context, conn *kms.Client, keyID string, enabled bool) error { + checkFunc := func() (bool, error) { + output, err := findKeyByID(ctx, conn, keyID) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + return output.Enabled == enabled, nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 15, + MinTimeout: 2 * time.Second, + } + const ( + timeout = 20 * time.Minute + ) + + return tfresource.WaitUntil(ctx, timeout, checkFunc, opts) +} diff --git a/internal/service/kms/key_data_source.go b/internal/service/kms/key_data_source.go index f538a51690ee..d6b993e5e541 100644 --- a/internal/service/kms/key_data_source.go +++ b/internal/service/kms/key_data_source.go @@ -7,8 +7,9 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -16,8 +17,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/flex" ) -// @SDKDataSource("aws_kms_key") -func DataSourceKey() *schema.Resource { +// @SDKDataSource("aws_kms_key", name="Key") +func dataSourceKey() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceKeyRead, Schema: map[string]*schema.Schema{ @@ -69,7 +70,7 @@ func DataSourceKey() *schema.Resource { "key_id": { Type: schema.TypeString, Required: true, - ValidateFunc: ValidateKeyOrAlias, + ValidateFunc: validateKeyOrAlias, }, "key_manager": { Type: schema.TypeString, @@ -165,7 +166,7 @@ func DataSourceKey() *schema.Resource { func dataSourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) keyID := d.Get("key_id").(string) input := &kms.DescribeKeyInput{ @@ -173,48 +174,47 @@ func dataSourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interfa } if v, ok := d.GetOk("grant_tokens"); ok && len(v.([]interface{})) > 0 { - input.GrantTokens = flex.ExpandStringList(v.([]interface{})) + input.GrantTokens = flex.ExpandStringValueList(v.([]interface{})) } - output, err := conn.DescribeKeyWithContext(ctx, input) + output, err := findKey(ctx, conn, input) if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Key (%s): %s", keyID, err) } - keyMetadata := output.KeyMetadata - d.SetId(aws.StringValue(keyMetadata.KeyId)) - d.Set("arn", keyMetadata.Arn) - d.Set("aws_account_id", keyMetadata.AWSAccountId) - d.Set("cloud_hsm_cluster_id", keyMetadata.CloudHsmClusterId) - d.Set("creation_date", aws.TimeValue(keyMetadata.CreationDate).Format(time.RFC3339)) - d.Set("customer_master_key_spec", keyMetadata.CustomerMasterKeySpec) - d.Set("custom_key_store_id", keyMetadata.CustomKeyStoreId) - if keyMetadata.DeletionDate != nil { - d.Set("deletion_date", aws.TimeValue(keyMetadata.DeletionDate).Format(time.RFC3339)) + d.SetId(aws.ToString(output.KeyId)) + d.Set("arn", output.Arn) + d.Set("aws_account_id", output.AWSAccountId) + d.Set("cloud_hsm_cluster_id", output.CloudHsmClusterId) + d.Set("creation_date", aws.ToTime(output.CreationDate).Format(time.RFC3339)) + d.Set("customer_master_key_spec", output.CustomerMasterKeySpec) + d.Set("custom_key_store_id", output.CustomKeyStoreId) + if output.DeletionDate != nil { + d.Set("deletion_date", aws.ToTime(output.DeletionDate).Format(time.RFC3339)) } - d.Set("description", keyMetadata.Description) - d.Set("enabled", keyMetadata.Enabled) - d.Set("expiration_model", keyMetadata.ExpirationModel) - d.Set("key_manager", keyMetadata.KeyManager) - d.Set("key_spec", keyMetadata.KeySpec) - d.Set("key_state", keyMetadata.KeyState) - d.Set("key_usage", keyMetadata.KeyUsage) - d.Set("multi_region", keyMetadata.MultiRegion) - if keyMetadata.MultiRegionConfiguration != nil { - if err := d.Set("multi_region_configuration", []interface{}{flattenMultiRegionConfiguration(keyMetadata.MultiRegionConfiguration)}); err != nil { + d.Set("description", output.Description) + d.Set("enabled", output.Enabled) + d.Set("expiration_model", output.ExpirationModel) + d.Set("key_manager", output.KeyManager) + d.Set("key_spec", output.KeySpec) + d.Set("key_state", output.KeyState) + d.Set("key_usage", output.KeyUsage) + d.Set("multi_region", output.MultiRegion) + if output.MultiRegionConfiguration != nil { + if err := d.Set("multi_region_configuration", []interface{}{flattenMultiRegionConfiguration(output.MultiRegionConfiguration)}); err != nil { return sdkdiag.AppendErrorf(diags, "setting multi_region_configuration: %s", err) } } else { d.Set("multi_region_configuration", nil) } - d.Set("origin", keyMetadata.Origin) - d.Set("pending_deletion_window_in_days", keyMetadata.PendingDeletionWindowInDays) - if keyMetadata.ValidTo != nil { - d.Set("valid_to", aws.TimeValue(keyMetadata.ValidTo).Format(time.RFC3339)) + d.Set("origin", output.Origin) + d.Set("pending_deletion_window_in_days", output.PendingDeletionWindowInDays) + if output.ValidTo != nil { + d.Set("valid_to", aws.ToTime(output.ValidTo).Format(time.RFC3339)) } - if keyMetadata.XksKeyConfiguration != nil { - if err := d.Set("xks_key_configuration", []interface{}{flattenXksKeyConfigurationType(keyMetadata.XksKeyConfiguration)}); err != nil { + if output.XksKeyConfiguration != nil { + if err := d.Set("xks_key_configuration", []interface{}{flattenXksKeyConfigurationType(output.XksKeyConfiguration)}); err != nil { return sdkdiag.AppendErrorf(diags, "setting xks_key_configuration: %s", err) } } else { @@ -224,15 +224,13 @@ func dataSourceKeyRead(ctx context.Context, d *schema.ResourceData, meta interfa return diags } -func flattenMultiRegionConfiguration(apiObject *kms.MultiRegionConfiguration) map[string]interface{} { +func flattenMultiRegionConfiguration(apiObject *awstypes.MultiRegionConfiguration) map[string]interface{} { if apiObject == nil { return nil } - tfMap := map[string]interface{}{} - - if v := apiObject.MultiRegionKeyType; v != nil { - tfMap["multi_region_key_type"] = aws.StringValue(v) + tfMap := map[string]interface{}{ + "multi_region_key_type": apiObject.MultiRegionKeyType, } if v := apiObject.PrimaryKey; v != nil { @@ -246,7 +244,7 @@ func flattenMultiRegionConfiguration(apiObject *kms.MultiRegionConfiguration) ma return tfMap } -func flattenMultiRegionKey(apiObject *kms.MultiRegionKey) map[string]interface{} { +func flattenMultiRegionKey(apiObject *awstypes.MultiRegionKey) map[string]interface{} { if apiObject == nil { return nil } @@ -254,17 +252,17 @@ func flattenMultiRegionKey(apiObject *kms.MultiRegionKey) map[string]interface{} tfMap := map[string]interface{}{} if v := apiObject.Arn; v != nil { - tfMap["arn"] = aws.StringValue(v) + tfMap["arn"] = aws.ToString(v) } if v := apiObject.Region; v != nil { - tfMap["region"] = aws.StringValue(v) + tfMap["region"] = aws.ToString(v) } return tfMap } -func flattenMultiRegionKeys(apiObjects []*kms.MultiRegionKey) []interface{} { +func flattenMultiRegionKeys(apiObjects []awstypes.MultiRegionKey) []interface{} { if len(apiObjects) == 0 { return nil } @@ -272,17 +270,13 @@ func flattenMultiRegionKeys(apiObjects []*kms.MultiRegionKey) []interface{} { var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenMultiRegionKey(apiObject)) + tfList = append(tfList, flattenMultiRegionKey(&apiObject)) } return tfList } -func flattenXksKeyConfigurationType(apiObject *kms.XksKeyConfigurationType) map[string]interface{} { +func flattenXksKeyConfigurationType(apiObject *awstypes.XksKeyConfigurationType) map[string]interface{} { if apiObject == nil { return nil } @@ -290,7 +284,7 @@ func flattenXksKeyConfigurationType(apiObject *kms.XksKeyConfigurationType) map[ tfMap := map[string]interface{}{} if v := apiObject.Id; v != nil { - tfMap["id"] = aws.StringValue(v) + tfMap["id"] = aws.ToString(v) } return tfMap diff --git a/internal/service/kms/key_policy.go b/internal/service/kms/key_policy.go index d6ecefa65cf4..a8bf6e20c51c 100644 --- a/internal/service/kms/key_policy.go +++ b/internal/service/kms/key_policy.go @@ -17,8 +17,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_kms_key_policy") -func ResourceKeyPolicy() *schema.Resource { +// @SDKResource("aws_kms_key_policy", name="Key Policy") +func resourceKeyPolicy() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceKeyPolicyCreate, ReadWithoutTimeout: resourceKeyPolicyRead, @@ -57,12 +57,12 @@ func ResourceKeyPolicy() *schema.Resource { func resourceKeyPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) keyID := d.Get("key_id").(string) - if err := updateKeyPolicy(ctx, conn, keyID, d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "attaching KMS Key policy (%s): %s", keyID, err) + if err := updateKeyPolicy(ctx, conn, "KMS Key Policy", keyID, d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } d.SetId(keyID) @@ -72,15 +72,16 @@ func resourceKeyPolicyCreate(ctx context.Context, d *schema.ResourceData, meta i func resourceKeyPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) - key, err := findKey(ctx, conn, d.Id(), d.IsNewResource()) + key, err := findKeyInfo(ctx, conn, d.Id(), d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS Key (%s) not found, removing from state", d.Id()) d.SetId("") return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Key (%s): %s", d.Id(), err) } @@ -89,7 +90,7 @@ func resourceKeyPolicyRead(ctx context.Context, d *schema.ResourceData, meta int policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), key.policy) if err != nil { - return sdkdiag.AppendErrorf(diags, "while setting policy (%s), encountered: %s", key.policy, err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -99,11 +100,11 @@ func resourceKeyPolicyRead(ctx context.Context, d *schema.ResourceData, meta int func resourceKeyPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) if d.HasChange("policy") { - if err := updateKeyPolicy(ctx, conn, d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "attaching KMS Key policy (%s): %s", d.Id(), err) + if err := updateKeyPolicy(ctx, conn, "KMS Key Policy", d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -112,11 +113,11 @@ func resourceKeyPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta i func resourceKeyPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) if !d.Get("bypass_policy_lockout_safety_check").(bool) { - if err := updateKeyPolicy(ctx, conn, d.Get("key_id").(string), meta.(*conns.AWSClient).DefaultKMSKeyPolicy(ctx), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "attaching KMS Key policy (%s): %s", d.Id(), err) + if err := updateKeyPolicy(ctx, conn, "KMS Key Policy", d.Get("key_id").(string), meta.(*conns.AWSClient).DefaultKMSKeyPolicy(ctx), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } else { log.Printf("[WARN] KMS Key Policy for Key (%s) does not allow PutKeyPolicy. Default Policy cannot be restored. Removing from state", d.Id()) } diff --git a/internal/service/kms/key_policy_test.go b/internal/service/kms/key_policy_test.go index b5a8a5e746f7..468119b06123 100644 --- a/internal/service/kms/key_policy_test.go +++ b/internal/service/kms/key_policy_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/acctest" @@ -18,7 +18,7 @@ import ( func TestAccKMSKeyPolicy_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" attachmentResourceName := "aws_kms_key_policy.test" @@ -55,7 +55,7 @@ func TestAccKMSKeyPolicy_basic(t *testing.T) { func TestAccKMSKeyPolicy_disappears(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) attachmentResourceName := "aws_kms_key_policy.test" resource.ParallelTest(t, resource.TestCase{ @@ -78,7 +78,7 @@ func TestAccKMSKeyPolicy_disappears(t *testing.T) { func TestAccKMSKeyPolicy_bypass(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" attachmentResourceName := "aws_kms_key_policy.test" @@ -112,7 +112,7 @@ func TestAccKMSKeyPolicy_bypass(t *testing.T) { func TestAccKMSKeyPolicy_bypassUpdate(t *testing.T) { ctx := acctest.Context(t) - var before, after kms.KeyMetadata + var before, after awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" attachmentResourceName := "aws_kms_key_policy.test" @@ -143,7 +143,7 @@ func TestAccKMSKeyPolicy_bypassUpdate(t *testing.T) { func TestAccKMSKeyPolicy_keyIsEnabled(t *testing.T) { ctx := acctest.Context(t) - var before, after kms.KeyMetadata + var before, after awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" @@ -171,7 +171,7 @@ func TestAccKMSKeyPolicy_keyIsEnabled(t *testing.T) { func TestAccKMSKeyPolicy_iamRole(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" @@ -187,19 +187,13 @@ func TestAccKMSKeyPolicy_iamRole(t *testing.T) { testAccCheckKeyExists(ctx, keyResourceName, &key), ), }, - { - ResourceName: keyResourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_window_in_days", "bypass_policy_lockout_safety_check"}, - }, }, }) } func TestAccKMSKeyPolicy_iamRoleUpdate(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" @@ -228,7 +222,7 @@ func TestAccKMSKeyPolicy_iamRoleUpdate(t *testing.T) { // // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/11801 func TestAccKMSKeyPolicy_iamRoleOrder(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" @@ -269,10 +263,10 @@ func TestAccKMSKeyPolicy_iamRoleOrder(t *testing.T) { }) } -// // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/7646 +// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/7646. func TestAccKMSKeyPolicy_iamServiceLinkedRole(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" @@ -288,19 +282,13 @@ func TestAccKMSKeyPolicy_iamServiceLinkedRole(t *testing.T) { testAccCheckKeyExists(ctx, keyResourceName, &key), ), }, - { - ResourceName: keyResourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_window_in_days", "bypass_policy_lockout_safety_check"}, - }, }, }) } func TestAccKMSKeyPolicy_booleanCondition(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) keyResourceName := "aws_kms_key.test" diff --git a/internal/service/kms/key_test.go b/internal/service/kms/key_test.go index b6a15c24b208..300e871cca98 100644 --- a/internal/service/kms/key_test.go +++ b/internal/service/kms/key_test.go @@ -9,8 +9,9 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" awspolicy "github.com/hashicorp/awspolicyequivalence" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -24,7 +25,7 @@ import ( func TestAccKMSKey_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata resourceName := "aws_kms_key.test" resource.ParallelTest(t, resource.TestCase{ @@ -62,7 +63,7 @@ func TestAccKMSKey_basic(t *testing.T) { func TestAccKMSKey_disappears(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -86,7 +87,7 @@ func TestAccKMSKey_disappears(t *testing.T) { func TestAccKMSKey_multiRegion(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -115,7 +116,7 @@ func TestAccKMSKey_multiRegion(t *testing.T) { func TestAccKMSKey_asymmetricKey(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -139,7 +140,7 @@ func TestAccKMSKey_asymmetricKey(t *testing.T) { func TestAccKMSKey_hmacKey(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -163,7 +164,7 @@ func TestAccKMSKey_hmacKey(t *testing.T) { func TestAccKMSKey_Policy_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" expectedPolicyText := fmt.Sprintf(`{"Version":"2012-10-17","Id":%[1]q,"Statement":[{"Sid":"Enable IAM User Permissions","Effect":"Allow","Principal":{"AWS":"*"},"Action":"kms:*","Resource":"*"}]}`, rName) @@ -199,7 +200,7 @@ func TestAccKMSKey_Policy_basic(t *testing.T) { func TestAccKMSKey_Policy_bypass(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -232,7 +233,7 @@ func TestAccKMSKey_Policy_bypass(t *testing.T) { func TestAccKMSKey_Policy_bypassUpdate(t *testing.T) { ctx := acctest.Context(t) - var before, after kms.KeyMetadata + var before, after awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -262,7 +263,7 @@ func TestAccKMSKey_Policy_bypassUpdate(t *testing.T) { func TestAccKMSKey_Policy_iamRole(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -290,7 +291,7 @@ func TestAccKMSKey_Policy_iamRole(t *testing.T) { func TestAccKMSKey_Policy_iamRoleUpdate(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -319,7 +320,7 @@ func TestAccKMSKey_Policy_iamRoleUpdate(t *testing.T) { // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/11801 func TestAccKMSKey_Policy_iamRoleOrder(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -363,7 +364,7 @@ func TestAccKMSKey_Policy_iamRoleOrder(t *testing.T) { // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/7646 func TestAccKMSKey_Policy_iamServiceLinkedRole(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -391,7 +392,7 @@ func TestAccKMSKey_Policy_iamServiceLinkedRole(t *testing.T) { func TestAccKMSKey_Policy_booleanCondition(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -413,7 +414,7 @@ func TestAccKMSKey_Policy_booleanCondition(t *testing.T) { func TestAccKMSKey_isEnabled(t *testing.T) { ctx := acctest.Context(t) - var key1, key2, key3 kms.KeyMetadata + var key1, key2, key3 awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -459,7 +460,7 @@ func TestAccKMSKey_isEnabled(t *testing.T) { func TestAccKMSKey_tags(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -520,7 +521,7 @@ func TestAccKMSKey_tags(t *testing.T) { // https://github.com/hashicorp/terraform-provider-aws/issues/26174. func TestAccKMSKey_ignoreTags(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -562,7 +563,7 @@ func TestAccKMSKey_ignoreTags(t *testing.T) { // https://github.com/hashicorp/terraform-provider-aws/issues/33219. func TestAccKMSKey_updateTagsEmptyValue(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_key.test" @@ -605,17 +606,15 @@ func testAccCheckKeyHasPolicy(ctx context.Context, name string, expectedPolicyTe return fmt.Errorf("No KMS Key ID is set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) + + output, err := tfkms.FindKeyPolicyByTwoPartKey(ctx, conn, rs.Primary.ID, tfkms.PolicyNameDefault) - out, err := conn.GetKeyPolicyWithContext(ctx, &kms.GetKeyPolicyInput{ - KeyId: aws.String(rs.Primary.ID), - PolicyName: aws.String("default"), - }) if err != nil { return err } - actualPolicyText := aws.StringValue(out.Policy) + actualPolicyText := aws.ToString(output) equivalent, err := awspolicy.PoliciesAreEquivalent(actualPolicyText, expectedPolicyText) if err != nil { @@ -632,7 +631,7 @@ func testAccCheckKeyHasPolicy(ctx context.Context, name string, expectedPolicyTe func testAccCheckKeyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_kms_key" { @@ -656,20 +655,16 @@ func testAccCheckKeyDestroy(ctx context.Context) resource.TestCheckFunc { } } -func testAccCheckKeyExists(ctx context.Context, name string, key *kms.KeyMetadata) resource.TestCheckFunc { +func testAccCheckKeyExists(ctx context.Context, name string, key *awstypes.KeyMetadata) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] if !ok { return fmt.Errorf("Not found: %s", name) } - if rs.Primary.ID == "" { - return fmt.Errorf("No KMS Key ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) - outputRaw, err := tfresource.RetryWhenNotFound(ctx, tfkms.PropagationTimeout, func() (interface{}, error) { + outputRaw, err := tfresource.RetryWhenNotFound(ctx, tfkms.KMSPropagationTimeout, func() (interface{}, error) { return tfkms.FindKeyByID(ctx, conn, rs.Primary.ID) }) @@ -677,25 +672,25 @@ func testAccCheckKeyExists(ctx context.Context, name string, key *kms.KeyMetadat return err } - *key = *(outputRaw.(*kms.KeyMetadata)) + *key = *(outputRaw.(*awstypes.KeyMetadata)) return nil } } -func testAccCheckKeyAddTag(ctx context.Context, key *kms.KeyMetadata, tagKey, tagValue string) resource.TestCheckFunc { +func testAccCheckKeyAddTag(ctx context.Context, key *awstypes.KeyMetadata, tagKey, tagValue string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) input := &kms.TagResourceInput{ KeyId: key.KeyId, - Tags: []*kms.Tag{{ + Tags: []awstypes.Tag{{ TagKey: aws.String(tagKey), TagValue: aws.String(tagValue), }}, } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input) return err } diff --git a/internal/service/kms/kms_test.go b/internal/service/kms/kms_test.go index afd6b2eb360c..35718724dad5 100644 --- a/internal/service/kms/kms_test.go +++ b/internal/service/kms/kms_test.go @@ -14,9 +14,10 @@ func TestAccKMS_serial(t *testing.T) { testCases := map[string]map[string]func(t *testing.T){ "CustomKeyStore": { - "basic": testAccCustomKeyStore_basic, - "update": testAccCustomKeyStore_update, - "disappears": testAccCustomKeyStore_disappears, + "basic": testAccCustomKeyStore_basic, + "update": testAccCustomKeyStore_update, + "disappears": testAccCustomKeyStore_disappears, + "DataSource_basic": testAccCustomKeyStoreDataSource_basic, }, } diff --git a/internal/service/kms/public_key_data_source.go b/internal/service/kms/public_key_data_source.go index 17cd5c8feb9f..b67fe0425384 100644 --- a/internal/service/kms/public_key_data_source.go +++ b/internal/service/kms/public_key_data_source.go @@ -7,8 +7,8 @@ import ( "context" "encoding/pem" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -17,10 +17,11 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) -// @SDKDataSource("aws_kms_public_key") -func DataSourcePublicKey() *schema.Resource { +// @SDKDataSource("aws_kms_public_key", name="Public Key") +func dataSourcePublicKey() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourcePublicKeyRead, + Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, @@ -43,7 +44,7 @@ func DataSourcePublicKey() *schema.Resource { "key_id": { Type: schema.TypeString, Required: true, - ValidateFunc: ValidateKeyOrAlias, + ValidateFunc: validateKeyOrAlias, }, "key_usage": { Type: schema.TypeString, @@ -68,41 +69,34 @@ func DataSourcePublicKey() *schema.Resource { func dataSourcePublicKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) - keyId := d.Get("key_id").(string) + conn := meta.(*conns.AWSClient).KMSClient(ctx) + keyID := d.Get("key_id").(string) input := &kms.GetPublicKeyInput{ - KeyId: aws.String(keyId), + KeyId: aws.String(keyID), } - if v, ok := d.GetOk("grant_tokens"); ok { - input.GrantTokens = aws.StringSlice(v.([]string)) + if v, ok := d.GetOk("grant_tokens"); ok && len(v.([]interface{})) > 0 { + input.GrantTokens = flex.ExpandStringValueList(v.([]interface{})) } - output, err := conn.GetPublicKeyWithContext(ctx, input) + output, err := conn.GetPublicKey(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "while describing KMS public key (%s): %s", keyId, err) + return sdkdiag.AppendErrorf(diags, "reading KMS Public Key (%s): %s", keyID, err) } - d.SetId(aws.StringValue(output.KeyId)) - + d.SetId(aws.ToString(output.KeyId)) d.Set("arn", output.KeyId) d.Set("customer_master_key_spec", output.CustomerMasterKeySpec) + d.Set("encryption_algorithms", output.EncryptionAlgorithms) d.Set("key_usage", output.KeyUsage) d.Set("public_key", itypes.Base64Encode(output.PublicKey)) d.Set("public_key_pem", string(pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: output.PublicKey, }))) - - if err := d.Set("encryption_algorithms", flex.FlattenStringList(output.EncryptionAlgorithms)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting encryption_algorithms: %s", err) - } - - if err := d.Set("signing_algorithms", flex.FlattenStringList(output.SigningAlgorithms)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting signing_algorithms: %s", err) - } + d.Set("signing_algorithms", output.SigningAlgorithms) return diags } diff --git a/internal/service/kms/replica_external_key.go b/internal/service/kms/replica_external_key.go index 527fa282595f..e3383d98e9a5 100644 --- a/internal/service/kms/replica_external_key.go +++ b/internal/service/kms/replica_external_key.go @@ -9,15 +9,18 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/arn" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/logging" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -28,7 +31,7 @@ import ( // @SDKResource("aws_kms_replica_external_key", name="Replica External Key") // @Tags(identifierAttribute="id") -func ResourceReplicaExternalKey() *schema.Resource { +func resourceReplicaExternalKey() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceReplicaExternalKeyCreate, ReadWithoutTimeout: resourceReplicaExternalKeyRead, @@ -115,7 +118,7 @@ func ResourceReplicaExternalKey() *schema.Resource { func resourceReplicaExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) // e.g. arn:aws:kms:us-east-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab primaryKeyARN, err := arn.Parse(d.Get("primary_key_arn").(string)) @@ -131,7 +134,7 @@ func resourceReplicaExternalKeyCreate(ctx context.Context, d *schema.ResourceDat } if v, ok := d.GetOk("bypass_policy_lockout_safety_check"); ok { - input.BypassPolicyLockoutSafetyCheck = aws.Bool(v.(bool)) + input.BypassPolicyLockoutSafetyCheck = v.(bool) } if v, ok := d.GetOk("description"); ok { @@ -142,59 +145,59 @@ func resourceReplicaExternalKeyCreate(ctx context.Context, d *schema.ResourceDat input.Policy = aws.String(v.(string)) } - // Replication is initiated in the primary key's region. - replicateConn := meta.(*conns.AWSClient).KMSConnForRegion(ctx, primaryKeyARN.Region) - - output, err := WaitIAMPropagation(ctx, propagationTimeout, func() (*kms.ReplicateKeyOutput, error) { - return replicateConn.ReplicateKeyWithContext(ctx, input) + output, err := waitIAMPropagation(ctx, iamPropagationTimeout, func() (*kms.ReplicateKeyOutput, error) { + // Replication is initiated in the primary key's Region. + return conn.ReplicateKey(ctx, input, func(o *kms.Options) { + o.Region = primaryKeyARN.Region + }) }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS Replica External Key: %s", err) } - d.SetId(aws.StringValue(output.ReplicaKeyMetadata.KeyId)) + d.SetId(aws.ToString(output.ReplicaKeyMetadata.KeyId)) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - if _, err := WaitReplicaExternalKeyCreated(ctx, conn, d.Id()); err != nil { + if _, err := waitReplicaExternalKeyCreated(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) create: %s", d.Id(), err) } if v, ok := d.GetOk("key_material_base64"); ok { validTo := d.Get("valid_to").(string) - if err := importExternalKeyMaterial(ctx, conn, d.Id(), v.(string), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "importing KMS Replica External Key (%s) material: %s", d.Id(), err) + if err := importExternalKeyMaterial(ctx, conn, "KMS Replica External Key", d.Id(), v.(string), validTo); err != nil { + return sdkdiag.AppendFromErr(diags, err) } - if _, err := WaitKeyMaterialImported(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyMaterialImported(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) material import: %s", d.Id(), err) } - if err := WaitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) valid_to propagation: %s", d.Id(), err) + if err := waitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) valid_to update: %s", d.Id(), err) } // The key can only be disabled if key material has been imported, else: // "KMSInvalidStateException: arn:aws:kms:us-west-2:123456789012:key/47e3edc1-945f-413b-88b1-e7341c2d89f7 is pending import." if enabled := d.Get("enabled").(bool); !enabled { - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "creating KMS Replica External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } } // Wait for propagation since KMS is eventually consistent. if v, ok := d.GetOk("policy"); ok { - if err := WaitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) policy propagation: %s", d.Id(), err) + if err := waitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) policy update: %s", d.Id(), err) } } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) tag propagation: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) tag update: %s", d.Id(), err) } } @@ -203,31 +206,31 @@ func resourceReplicaExternalKeyCreate(ctx context.Context, d *schema.ResourceDat func resourceReplicaExternalKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - key, err := findKey(ctx, conn, d.Id(), d.IsNewResource()) + key, err := findKeyInfo(ctx, conn, d.Id(), d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS External Replica Key (%s) not found, removing from state", d.Id()) d.SetId("") return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS External Replica Key (%s): %s", d.Id(), err) } - if keyManager := aws.StringValue(key.metadata.KeyManager); keyManager != kms.KeyManagerTypeCustomer { + if keyManager := key.metadata.KeyManager; keyManager != awstypes.KeyManagerTypeCustomer { return sdkdiag.AppendErrorf(diags, "KMS External Replica Key (%s) has invalid KeyManager: %s", d.Id(), keyManager) } - if origin := aws.StringValue(key.metadata.Origin); origin != kms.OriginTypeExternal { + if origin := key.metadata.Origin; origin != awstypes.OriginTypeExternal { return sdkdiag.AppendErrorf(diags, "KMS External Replica Key (%s) has invalid Origin: %s", d.Id(), origin) } - if !aws.BoolValue(key.metadata.MultiRegion) || - aws.StringValue(key.metadata.MultiRegionConfiguration.MultiRegionKeyType) != kms.MultiRegionKeyTypeReplica { + if !aws.ToBool(key.metadata.MultiRegion) || key.metadata.MultiRegionConfiguration.MultiRegionKeyType != awstypes.MultiRegionKeyTypeReplica { return sdkdiag.AppendErrorf(diags, "KMS External Replica Key (%s) is not a multi-Region replica key", d.Id()) } @@ -242,14 +245,14 @@ func resourceReplicaExternalKeyRead(ctx context.Context, d *schema.ResourceData, policyToSet, err := verify.SecondJSONUnlessEquivalent(d.Get("policy").(string), key.policy) if err != nil { - return sdkdiag.AppendErrorf(diags, "while setting policy (%s), encountered: %s", key.policy, err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) d.Set("primary_key_arn", key.metadata.MultiRegionConfiguration.PrimaryKey.Arn) if key.metadata.ValidTo != nil { - d.Set("valid_to", aws.TimeValue(key.metadata.ValidTo).Format(time.RFC3339)) + d.Set("valid_to", aws.ToTime(key.metadata.ValidTo).Format(time.RFC3339)) } else { d.Set("valid_to", nil) } @@ -261,49 +264,49 @@ func resourceReplicaExternalKeyRead(ctx context.Context, d *schema.ResourceData, func resourceReplicaExternalKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), d.Get("key_state").(string); hasChange && enabled && state != kms.KeyStatePendingImport { + if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), awstypes.KeyState(d.Get("key_state").(string)); hasChange && enabled && state != awstypes.KeyStatePendingImport { // Enable before any attributes are modified. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("description") { - if err := updateKeyDescription(ctx, conn, d.Id(), d.Get("description").(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica External Key (%s): %s", d.Id(), err) + if err := updateKeyDescription(ctx, conn, "KMS Replica External Key", d.Id(), d.Get("description").(string)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("policy") { - if err := updateKeyPolicy(ctx, conn, d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica External Key (%s): %s", d.Id(), err) + if err := updateKeyPolicy(ctx, conn, "KMS Replica External Key", d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("valid_to") { validTo := d.Get("valid_to").(string) - if err := importExternalKeyMaterial(ctx, conn, d.Id(), d.Get("key_material_base64").(string), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "importing KMS External Replica Key (%s) material: %s", d.Id(), err) + if err := importExternalKeyMaterial(ctx, conn, "KMS Replica External Key", d.Id(), d.Get("key_material_base64").(string), validTo); err != nil { + return sdkdiag.AppendFromErr(diags, err) } - if _, err := WaitKeyMaterialImported(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyMaterialImported(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS External Replica Key (%s) material import: %s", d.Id(), err) } - if err := WaitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS External Replica Key (%s) valid_to propagation: %s", d.Id(), err) + if err := waitKeyValidToPropagated(ctx, conn, d.Id(), validTo); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS External Replica Key (%s) valid_to update: %s", d.Id(), err) } } - if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), d.Get("key_state").(string); hasChange && !enabled && state != kms.KeyStatePendingImport { + if hasChange, enabled, state := d.HasChange("enabled"), d.Get("enabled").(bool), awstypes.KeyState(d.Get("key_state").(string)); hasChange && !enabled && state != awstypes.KeyStatePendingImport { // Only disable after all attributes have been modified because we cannot modify disabled keys. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica External Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica External Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -312,7 +315,7 @@ func resourceReplicaExternalKeyUpdate(ctx context.Context, d *schema.ResourceDat func resourceReplicaExternalKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) @@ -321,17 +324,17 @@ func resourceReplicaExternalKeyDelete(ctx context.Context, d *schema.ResourceDat } if v, ok := d.GetOk("deletion_window_in_days"); ok { - input.PendingWindowInDays = aws.Int64(int64(v.(int))) + input.PendingWindowInDays = aws.Int32(int32(v.(int))) } - log.Printf("[DEBUG] Deleting KMS Replica External Key: (%s)", d.Id()) - _, err := conn.ScheduleKeyDeletionWithContext(ctx, input) + log.Printf("[DEBUG] Deleting KMS Replica External Key: %s", d.Id()) + _, err := conn.ScheduleKeyDeletion(ctx, input) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } - if tfawserr.ErrMessageContains(err, kms.ErrCodeInvalidStateException, "is pending deletion") { + if errs.IsAErrorMessageContains[*awstypes.KMSInvalidStateException](err, "is pending deletion") { return diags } @@ -339,9 +342,29 @@ func resourceReplicaExternalKeyDelete(ctx context.Context, d *schema.ResourceDat return sdkdiag.AppendErrorf(diags, "deleting KMS Replica External Key (%s): %s", d.Id(), err) } - if _, err := WaitKeyDeleted(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyDeleted(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) delete: %s", d.Id(), err) } return diags } + +func waitReplicaExternalKeyCreated(ctx context.Context, conn *kms.Client, id string) (*awstypes.KeyMetadata, error) { + const ( + timeout = 2 * time.Minute + ) + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.KeyStateCreating), + Target: enum.Slice(awstypes.KeyStatePendingImport), + Refresh: statusKeyState(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.KeyMetadata); ok { + return output, err + } + + return nil, err +} diff --git a/internal/service/kms/replica_external_key_test.go b/internal/service/kms/replica_external_key_test.go index 34b9dfe9930e..45b5cd6466ab 100644 --- a/internal/service/kms/replica_external_key_test.go +++ b/internal/service/kms/replica_external_key_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/acctest" @@ -17,7 +17,7 @@ import ( func TestAccKMSReplicaExternalKey_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) primaryKeyResourceName := "aws_kms_external_key.test" resourceName := "aws_kms_replica_external_key.test" @@ -66,7 +66,7 @@ func TestAccKMSReplicaExternalKey_basic(t *testing.T) { func TestAccKMSReplicaExternalKey_descriptionAndEnabled(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rName3 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -122,7 +122,7 @@ func TestAccKMSReplicaExternalKey_descriptionAndEnabled(t *testing.T) { func TestAccKMSReplicaExternalKey_policy(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_external_key.test" policy1 := `{"Id":"kms-tf-1","Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"*","Sid":"Enable IAM User Permissions 1"}],"Version":"2012-10-17"}` @@ -169,7 +169,7 @@ func TestAccKMSReplicaExternalKey_policy(t *testing.T) { func TestAccKMSReplicaExternalKey_tags(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_external_key.test" diff --git a/internal/service/kms/replica_key.go b/internal/service/kms/replica_key.go index ccd71f4f9404..1515b34792b3 100644 --- a/internal/service/kms/replica_key.go +++ b/internal/service/kms/replica_key.go @@ -7,16 +7,20 @@ import ( "context" "log" "strings" + "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/arn" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/logging" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -27,7 +31,7 @@ import ( // @SDKResource("aws_kms_replica_key", name="Replica Key") // @Tags(identifierAttribute="id") -func ResourceReplicaKey() *schema.Resource { +func resourceReplicaKey() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceReplicaKeyCreate, ReadWithoutTimeout: resourceReplicaKeyRead, @@ -103,7 +107,7 @@ func ResourceReplicaKey() *schema.Resource { func resourceReplicaKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) // e.g. arn:aws:kms:us-east-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab primaryKeyARN, err := arn.Parse(d.Get("primary_key_arn").(string)) @@ -119,7 +123,7 @@ func resourceReplicaKeyCreate(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("bypass_policy_lockout_safety_check"); ok { - input.BypassPolicyLockoutSafetyCheck = aws.Bool(v.(bool)) + input.BypassPolicyLockoutSafetyCheck = v.(bool) } if v, ok := d.GetOk("description"); ok { @@ -130,43 +134,43 @@ func resourceReplicaKeyCreate(ctx context.Context, d *schema.ResourceData, meta input.Policy = aws.String(v.(string)) } - // Replication is initiated in the primary key's region. - replicateConn := meta.(*conns.AWSClient).KMSConnForRegion(ctx, primaryKeyARN.Region) - - output, err := WaitIAMPropagation(ctx, propagationTimeout, func() (*kms.ReplicateKeyOutput, error) { - return replicateConn.ReplicateKeyWithContext(ctx, input) + output, err := waitIAMPropagation(ctx, iamPropagationTimeout, func() (*kms.ReplicateKeyOutput, error) { + // Replication is initiated in the primary key's Region. + return conn.ReplicateKey(ctx, input, func(o *kms.Options) { + o.Region = primaryKeyARN.Region + }) }) if err != nil { return sdkdiag.AppendErrorf(diags, "creating KMS Replica Key: %s", err) } - d.SetId(aws.StringValue(output.ReplicaKeyMetadata.KeyId)) + d.SetId(aws.ToString(output.ReplicaKeyMetadata.KeyId)) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - if _, err := WaitReplicaKeyCreated(ctx, conn, d.Id()); err != nil { + if _, err := waitReplicaKeyCreated(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) create: %s", d.Id(), err) } d.Set("key_id", d.Id()) if enabled := d.Get("enabled").(bool); !enabled { - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "creating KMS Replica Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } // Wait for propagation since KMS is eventually consistent. if v, ok := d.GetOk("policy"); ok { - if err := WaitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) policy propagation: %s", d.Id(), err) + if err := waitKeyPolicyPropagated(ctx, conn, d.Id(), v.(string)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) policy update: %s", d.Id(), err) } } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) tag propagation: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) tag update: %s", d.Id(), err) } } @@ -175,31 +179,31 @@ func resourceReplicaKeyCreate(ctx context.Context, d *schema.ResourceData, meta func resourceReplicaKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) - key, err := findKey(ctx, conn, d.Id(), d.IsNewResource()) + key, err := findKeyInfo(ctx, conn, d.Id(), d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] KMS Replica Key (%s) not found, removing from state", d.Id()) d.SetId("") return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "reading KMS Replica Key (%s): %s", d.Id(), err) } - if keyManager := aws.StringValue(key.metadata.KeyManager); keyManager != kms.KeyManagerTypeCustomer { + if keyManager := key.metadata.KeyManager; keyManager != awstypes.KeyManagerTypeCustomer { return sdkdiag.AppendErrorf(diags, "KMS Replica Key (%s) has invalid KeyManager: %s", d.Id(), keyManager) } - if origin := aws.StringValue(key.metadata.Origin); origin != kms.OriginTypeAwsKms { + if origin := key.metadata.Origin; origin != awstypes.OriginTypeAwsKms { return sdkdiag.AppendErrorf(diags, "KMS Replica Key (%s) has invalid Origin: %s", d.Id(), origin) } - if !aws.BoolValue(key.metadata.MultiRegion) || - aws.StringValue(key.metadata.MultiRegionConfiguration.MultiRegionKeyType) != kms.MultiRegionKeyTypeReplica { + if !aws.ToBool(key.metadata.MultiRegion) || key.metadata.MultiRegionConfiguration.MultiRegionKeyType != awstypes.MultiRegionKeyTypeReplica { return sdkdiag.AppendErrorf(diags, "KMS Replica Key (%s) is not a multi-Region replica key", d.Id()) } @@ -214,7 +218,7 @@ func resourceReplicaKeyRead(ctx context.Context, d *schema.ResourceData, meta in policyToSet, err := verify.SecondJSONUnlessEquivalent(d.Get("policy").(string), key.policy) if err != nil { - return sdkdiag.AppendErrorf(diags, "while setting policy (%s), encountered: %s", key.policy, err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -227,33 +231,33 @@ func resourceReplicaKeyRead(ctx context.Context, d *schema.ResourceData, meta in func resourceReplicaKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) if hasChange, enabled := d.HasChange("enabled"), d.Get("enabled").(bool); hasChange && enabled { // Enable before any attributes are modified. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("description") { - if err := updateKeyDescription(ctx, conn, d.Id(), d.Get("description").(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica Key (%s): %s", d.Id(), err) + if err := updateKeyDescription(ctx, conn, "KMS Replica Key", d.Id(), d.Get("description").(string)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if d.HasChange("policy") { - if err := updateKeyPolicy(ctx, conn, d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica Key (%s): %s", d.Id(), err) + if err := updateKeyPolicy(ctx, conn, "KMS Replica Key", d.Id(), d.Get("policy").(string), d.Get("bypass_policy_lockout_safety_check").(bool)); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } if hasChange, enabled := d.HasChange("enabled"), d.Get("enabled").(bool); hasChange && !enabled { // Only disable after all attributes have been modified because we cannot modify disabled keys. - if err := updateKeyEnabled(ctx, conn, d.Id(), enabled); err != nil { - return sdkdiag.AppendErrorf(diags, "updating KMS Replica Key (%s): %s", d.Id(), err) + if err := updateKeyEnabled(ctx, conn, "KMS Replica Key", d.Id(), enabled); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -262,7 +266,7 @@ func resourceReplicaKeyUpdate(ctx context.Context, d *schema.ResourceData, meta func resourceReplicaKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KMSConn(ctx) + conn := meta.(*conns.AWSClient).KMSClient(ctx) ctx = tflog.SetField(ctx, logging.KeyResourceId, d.Id()) @@ -271,17 +275,17 @@ func resourceReplicaKeyDelete(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("deletion_window_in_days"); ok { - input.PendingWindowInDays = aws.Int64(int64(v.(int))) + input.PendingWindowInDays = aws.Int32(int32(v.(int))) } log.Printf("[DEBUG] Deleting KMS Replica Key: (%s)", d.Id()) - _, err := conn.ScheduleKeyDeletionWithContext(ctx, input) + _, err := conn.ScheduleKeyDeletion(ctx, input) - if tfawserr.ErrCodeEquals(err, kms.ErrCodeNotFoundException) { + if errs.IsA[*awstypes.NotFoundException](err) { return diags } - if tfawserr.ErrMessageContains(err, kms.ErrCodeInvalidStateException, "is pending deletion") { + if errs.IsAErrorMessageContains[*awstypes.KMSInvalidStateException](err, "is pending deletion") { return diags } @@ -289,9 +293,29 @@ func resourceReplicaKeyDelete(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "deleting KMS Replica Key (%s): %s", d.Id(), err) } - if _, err := WaitKeyDeleted(ctx, conn, d.Id()); err != nil { + if _, err := waitKeyDeleted(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) delete: %s", d.Id(), err) } return diags } + +func waitReplicaKeyCreated(ctx context.Context, conn *kms.Client, id string) (*awstypes.KeyMetadata, error) { + const ( + timeout = 2 * time.Minute + ) + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.KeyStateCreating), + Target: enum.Slice(awstypes.KeyStateEnabled), + Refresh: statusKeyState(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.KeyMetadata); ok { + return output, err + } + + return nil, err +} diff --git a/internal/service/kms/replica_key_test.go b/internal/service/kms/replica_key_test.go index 9f15391cb825..62c48bb4c72c 100644 --- a/internal/service/kms/replica_key_test.go +++ b/internal/service/kms/replica_key_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/acctest" @@ -18,7 +18,7 @@ import ( func TestAccKMSReplicaKey_basic(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) primaryKeyResourceName := "aws_kms_key.test" resourceName := "aws_kms_replica_key.test" @@ -60,7 +60,7 @@ func TestAccKMSReplicaKey_basic(t *testing.T) { func TestAccKMSReplicaKey_disappears(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_key.test" @@ -87,7 +87,7 @@ func TestAccKMSReplicaKey_disappears(t *testing.T) { func TestAccKMSReplicaKey_descriptionAndEnabled(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rName3 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -139,7 +139,7 @@ func TestAccKMSReplicaKey_descriptionAndEnabled(t *testing.T) { func TestAccKMSReplicaKey_policy(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_key.test" policy1 := `{"Id":"kms-tf-1","Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"*","Sid":"Enable IAM User Permissions 1"}],"Version":"2012-10-17"}` @@ -182,7 +182,7 @@ func TestAccKMSReplicaKey_policy(t *testing.T) { func TestAccKMSReplicaKey_tags(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_key.test" @@ -251,7 +251,7 @@ func TestAccKMSReplicaKey_tags(t *testing.T) { func TestAccKMSReplicaKey_twoReplicas(t *testing.T) { ctx := acctest.Context(t) - var key kms.KeyMetadata + var key awstypes.KeyMetadata rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_kms_replica_key.test1" diff --git a/internal/service/kms/secret_data_source.go b/internal/service/kms/secret_data_source.go index fb612f44abbc..8445b8ee799e 100644 --- a/internal/service/kms/secret_data_source.go +++ b/internal/service/kms/secret_data_source.go @@ -10,13 +10,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -const SecretRemovedMessage = "This data source has been replaced with the `aws_kms_secrets` data source. Upgrade information is available at: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-2-upgrade.html#data-source-aws_kms_secret" +const secretRemovedMessage = "This data source has been replaced with the `aws_kms_secrets` data source. Upgrade information is available at: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-2-upgrade.html#data-source-aws_kms_secret" -// @SDKDataSource("aws_kms_secret") -func DataSourceSecret() *schema.Resource { +// @SDKDataSource("aws_kms_secret", name="Secret") +func dataSourceSecret() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: func(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return diag.Errorf(SecretRemovedMessage) // nosemgrep:ci.semgrep.pluginsdk.avoid-diag_Errorf + return diag.Errorf(secretRemovedMessage) // nosemgrep:ci.semgrep.pluginsdk.avoid-diag_Errorf }, Schema: map[string]*schema.Schema{ diff --git a/internal/service/kms/secrets_data_source.go b/internal/service/kms/secrets_data_source.go index 50e2052bdc11..6e049983512f 100644 --- a/internal/service/kms/secrets_data_source.go +++ b/internal/service/kms/secrets_data_source.go @@ -6,19 +6,20 @@ package kms import ( "context" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) -// @SDKDataSource("aws_kms_secrets") -func DataSourceSecrets() *schema.Resource { +// @SDKDataSource("aws_kms_secrets", name="Secrets) +func dataSourceSecrets() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceSecretsRead, @@ -34,9 +35,9 @@ func DataSourceSecrets() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, }, "encryption_algorithm": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice(kms.EncryptionAlgorithmSpec_Values(), false), + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.EncryptionAlgorithmSpec](), }, "grant_tokens": { Type: schema.TypeList, @@ -70,48 +71,45 @@ func DataSourceSecrets() *schema.Resource { func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).KMSClient(ctx) - conn := meta.(*conns.AWSClient).KMSConn(ctx) + tfList := d.Get("secret").(*schema.Set).List() + plaintext := make(map[string]string, len(tfList)) - secrets := d.Get("secret").(*schema.Set).List() - plaintext := make(map[string]string, len(secrets)) - - for _, v := range secrets { - secret := v.(map[string]interface{}) - name := secret["name"].(string) + for _, tfMapRaw := range tfList { + tfMap := tfMapRaw.(map[string]interface{}) + name := tfMap["name"].(string) // base64 decode the payload - payload, err := itypes.Base64Decode(secret["payload"].(string)) + payload, err := itypes.Base64Decode(tfMap["payload"].(string)) if err != nil { return sdkdiag.AppendErrorf(diags, "invalid base64 value for secret (%s): %s", name, err) } - // build the kms decrypt input input := &kms.DecryptInput{ CiphertextBlob: payload, } - if v, ok := secret["context"].(map[string]interface{}); ok && len(v) > 0 { - input.EncryptionContext = flex.ExpandStringMap(v) + if v, ok := tfMap["context"].(map[string]interface{}); ok && len(v) > 0 { + input.EncryptionContext = flex.ExpandStringValueMap(v) } - if v, ok := secret["encryption_algorithm"].(string); ok && v != "" { - input.EncryptionAlgorithm = aws.String(v) + if v, ok := tfMap["encryption_algorithm"].(string); ok && v != "" { + input.EncryptionAlgorithm = awstypes.EncryptionAlgorithmSpec(v) } - if v, ok := secret["grant_tokens"].([]interface{}); ok && len(v) > 0 { - input.GrantTokens = flex.ExpandStringList(v) + if v, ok := tfMap["grant_tokens"].([]interface{}); ok && len(v) > 0 { + input.GrantTokens = flex.ExpandStringValueList(v) } - if v, ok := secret["key_id"].(string); ok && v != "" { + if v, ok := tfMap["key_id"].(string); ok && v != "" { input.KeyId = aws.String(v) } - // decrypt - output, err := conn.DecryptWithContext(ctx, input) + output, err := conn.Decrypt(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "decrypting secret (%s): %s", name, err) + return sdkdiag.AppendErrorf(diags, "decrypting KMS Secret (%s): %s", name, err) } // Set the secret via the name diff --git a/internal/service/kms/secrets_data_source_test.go b/internal/service/kms/secrets_data_source_test.go index e65f3185efd3..3a018de0335b 100644 --- a/internal/service/kms/secrets_data_source_test.go +++ b/internal/service/kms/secrets_data_source_test.go @@ -9,8 +9,8 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" @@ -21,7 +21,7 @@ import ( func TestAccKMSSecretsDataSource_basic(t *testing.T) { ctx := acctest.Context(t) var encryptedPayload string - var key kms.KeyMetadata + var key awstypes.KeyMetadata plaintext := "my-plaintext-string" resourceName := "aws_kms_key.test" @@ -36,9 +36,9 @@ func TestAccKMSSecretsDataSource_basic(t *testing.T) { Config: testAccSecretsDataSourceConfig_key, Check: resource.ComposeTestCheckFunc( testAccCheckKeyExists(ctx, resourceName, &key), - testAccSecretsEncryptDataSource(ctx, &key, plaintext, &encryptedPayload), + testAccSecretsDataSourceEncrypt(ctx, &key, plaintext, &encryptedPayload), // We need to dereference the encryptedPayload in a test Terraform configuration - testAccSecretsDecryptDataSource(ctx, t, plaintext, &encryptedPayload), + testAccSecretsDataSourceDecrypt(ctx, t, plaintext, &encryptedPayload), ), }, }, @@ -48,7 +48,7 @@ func TestAccKMSSecretsDataSource_basic(t *testing.T) { func TestAccKMSSecretsDataSource_asymmetric(t *testing.T) { ctx := acctest.Context(t) var encryptedPayload string - var key kms.KeyMetadata + var key awstypes.KeyMetadata plaintext := "my-plaintext-string" resourceName := "aws_kms_key.test" @@ -63,28 +63,28 @@ func TestAccKMSSecretsDataSource_asymmetric(t *testing.T) { Config: testAccSecretsDataSourceConfig_asymmetricKey, Check: resource.ComposeTestCheckFunc( testAccCheckKeyExists(ctx, resourceName, &key), - testAccSecretsEncryptDataSourceAsymmetric(ctx, &key, plaintext, &encryptedPayload), + testAccSecretsDataSourceEncryptAsymmetric(ctx, &key, plaintext, &encryptedPayload), // We need to dereference the encryptedPayload in a test Terraform configuration - testAccSecretsDecryptDataSourceAsym(ctx, t, &key, plaintext, &encryptedPayload), + testAccSecretsDataSourceDecryptAsymmetric(ctx, t, &key, plaintext, &encryptedPayload), ), }, }, }) } -func testAccSecretsEncryptDataSource(ctx context.Context, key *kms.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { +func testAccSecretsDataSourceEncrypt(ctx context.Context, key *awstypes.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) input := &kms.EncryptInput{ KeyId: key.Arn, Plaintext: []byte(plaintext), - EncryptionContext: map[string]*string{ - "name": aws.String("value"), + EncryptionContext: map[string]string{ + "name": "value", }, } - output, err := conn.EncryptWithContext(ctx, input) + output, err := conn.Encrypt(ctx, input) if err != nil { return err @@ -96,17 +96,17 @@ func testAccSecretsEncryptDataSource(ctx context.Context, key *kms.KeyMetadata, } } -func testAccSecretsEncryptDataSourceAsymmetric(ctx context.Context, key *kms.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { +func testAccSecretsDataSourceEncryptAsymmetric(ctx context.Context, key *awstypes.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).KMSClient(ctx) input := &kms.EncryptInput{ KeyId: key.Arn, Plaintext: []byte(plaintext), - EncryptionAlgorithm: aws.String("RSAES_OAEP_SHA_1"), + EncryptionAlgorithm: awstypes.EncryptionAlgorithmSpecRsaesOaepSha1, } - output, err := conn.EncryptWithContext(ctx, input) + output, err := conn.Encrypt(ctx, input) if err != nil { return err @@ -118,7 +118,7 @@ func testAccSecretsEncryptDataSourceAsymmetric(ctx context.Context, key *kms.Key } } -func testAccSecretsDecryptDataSource(ctx context.Context, t *testing.T, plaintext string, encryptedPayload *string) resource.TestCheckFunc { +func testAccSecretsDataSourceDecrypt(ctx context.Context, t *testing.T, plaintext string, encryptedPayload *string) resource.TestCheckFunc { return func(s *terraform.State) error { dataSourceName := "data.aws_kms_secrets.test" @@ -141,7 +141,7 @@ func testAccSecretsDecryptDataSource(ctx context.Context, t *testing.T, plaintex } } -func testAccSecretsDecryptDataSourceAsym(ctx context.Context, t *testing.T, key *kms.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { +func testAccSecretsDataSourceDecryptAsymmetric(ctx context.Context, t *testing.T, key *awstypes.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { return func(s *terraform.State) error { dataSourceName := "data.aws_kms_secrets.test" keyid := key.Arn diff --git a/internal/service/kms/service_endpoints_gen_test.go b/internal/service/kms/service_endpoints_gen_test.go index 269676b3b998..92a8b1680d80 100644 --- a/internal/service/kms/service_endpoints_gen_test.go +++ b/internal/service/kms/service_endpoints_gen_test.go @@ -4,17 +4,17 @@ package kms_test import ( "context" + "errors" "fmt" "maps" - "net/url" "os" "path/filepath" "reflect" "strings" "testing" - "github.com/aws/aws-sdk-go/aws/endpoints" - kms_sdkv1 "github.com/aws/aws-sdk-go/service/kms" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" @@ -212,32 +212,42 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } func defaultEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := kms_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(kms_sdkv1.EndpointsID, region) + ep, err := r.ResolveEndpoint(context.Background(), kms_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) string { t.Helper() - client := meta.KMSConn(ctx) - - req, _ := client.ListKeysRequest(&kms_sdkv1.ListKeysInput{}) + var endpoint string - req.HTTPRequest.URL.Path = "/" + client := meta.KMSClient(ctx) - endpoint := req.HTTPRequest.URL.String() + _, err := client.ListKeys(ctx, &kms_sdkv2.ListKeysInput{}, + func(opts *kms_sdkv2.Options) { + opts.APIOptions = append(opts.APIOptions, + addRetrieveEndpointURLMiddleware(t, &endpoint), + addCancelRequestMiddleware(), + ) + }, + ) + if err == nil { + t.Fatal("Expected an error, got none") + } else if !errors.Is(err, errCancelOperation) { + t.Fatalf("Unexpected error: %s", err) + } return endpoint } diff --git a/internal/service/kms/service_package_gen.go b/internal/service/kms/service_package_gen.go index 1f126fed777a..267747ea7ccd 100644 --- a/internal/service/kms/service_package_gen.go +++ b/internal/service/kms/service_package_gen.go @@ -5,9 +5,8 @@ package kms import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - kms_sdkv1 "github.com/aws/aws-sdk-go/service/kms" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -26,32 +25,39 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { return []*types.ServicePackageSDKDataSource{ { - Factory: DataSourceAlias, + Factory: dataSourceAlias, TypeName: "aws_kms_alias", + Name: "Alias", }, { - Factory: DataSourceCiphertext, + Factory: dataSourceCiphertext, TypeName: "aws_kms_ciphertext", + Name: "Ciphertext", }, { - Factory: DataSourceCustomKeyStore, + Factory: dataSourceCustomKeyStore, TypeName: "aws_kms_custom_key_store", + Name: "Custom Key Store", }, { - Factory: DataSourceKey, + Factory: dataSourceKey, TypeName: "aws_kms_key", + Name: "Key", }, { - Factory: DataSourcePublicKey, + Factory: dataSourcePublicKey, TypeName: "aws_kms_public_key", + Name: "Public Key", }, { - Factory: DataSourceSecret, + Factory: dataSourceSecret, TypeName: "aws_kms_secret", + Name: "Secret", }, { - Factory: DataSourceSecrets, + Factory: dataSourceSecrets, TypeName: "aws_kms_secrets", + Name: "Secrets", }, } } @@ -59,19 +65,22 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceAlias, + Factory: resourceAlias, TypeName: "aws_kms_alias", + Name: "Alias", }, { - Factory: ResourceCiphertext, + Factory: resourceCiphertext, TypeName: "aws_kms_ciphertext", + Name: "Ciphertext", }, { - Factory: ResourceCustomKeyStore, + Factory: resourceCustomKeyStore, TypeName: "aws_kms_custom_key_store", + Name: "Custom Key Store", }, { - Factory: ResourceExternalKey, + Factory: resourceExternalKey, TypeName: "aws_kms_external_key", Name: "External Key", Tags: &types.ServicePackageResourceTags{ @@ -79,11 +88,12 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceGrant, + Factory: resourceGrant, TypeName: "aws_kms_grant", + Name: "Grant", }, { - Factory: ResourceKey, + Factory: resourceKey, TypeName: "aws_kms_key", Name: "Key", Tags: &types.ServicePackageResourceTags{ @@ -91,11 +101,12 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceKeyPolicy, + Factory: resourceKeyPolicy, TypeName: "aws_kms_key_policy", + Name: "Key Policy", }, { - Factory: ResourceReplicaExternalKey, + Factory: resourceReplicaExternalKey, TypeName: "aws_kms_replica_external_key", Name: "Replica External Key", Tags: &types.ServicePackageResourceTags{ @@ -103,7 +114,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceReplicaKey, + Factory: resourceReplicaKey, TypeName: "aws_kms_replica_key", Name: "Replica Key", Tags: &types.ServicePackageResourceTags{ @@ -117,11 +128,15 @@ func (p *servicePackage) ServicePackageName() string { return names.KMS } -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*kms_sdkv1.KMS, error) { - sess := config["session"].(*session_sdkv1.Session) +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*kms_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return kms_sdkv1.New(sess.Copy(&aws_sdkv1.Config{Endpoint: aws_sdkv1.String(config["endpoint"].(string))})), nil + return kms_sdkv2.NewFromConfig(cfg, func(o *kms_sdkv2.Options) { + if endpoint := config["endpoint"].(string); endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + }), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/kms/status.go b/internal/service/kms/status.go deleted file mode 100644 index de6fe0cac449..000000000000 --- a/internal/service/kms/status.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package kms - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func StatusKeyState(ctx context.Context, conn *kms.KMS, id string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := FindKeyByID(ctx, conn, id) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, aws.StringValue(output.KeyState), nil - } -} diff --git a/internal/service/kms/sweep.go b/internal/service/kms/sweep.go index 0a1145e84600..59b70eaf5ca3 100644 --- a/internal/service/kms/sweep.go +++ b/internal/service/kms/sweep.go @@ -7,13 +7,13 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/go-multierror" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" - "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv1" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" "github.com/hashicorp/terraform-provider-aws/internal/sweep/sdk" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) @@ -31,45 +31,48 @@ func sweepKeys(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } + conn := client.KMSClient(ctx) input := &kms.ListKeysInput{ - Limit: aws.Int64(1000), + Limit: aws.Int32(1000), } - conn := client.KMSConn(ctx) - var sweeperErrs *multierror.Error sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListKeysPagesWithContext(ctx, input, func(page *kms.ListKeysOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := kms.NewListKeysPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping KMS Key sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing KMS Keys (%s): %w", region, err) } for _, v := range page.Keys { - keyID := aws.StringValue(v.KeyId) - key, err := FindKeyByID(ctx, conn, keyID) + keyID := aws.ToString(v.KeyId) + key, err := findKeyByID(ctx, conn, keyID) if tfresource.NotFound(err) { continue } - if err != nil { - if tfawserr.ErrMessageContains(err, "AccessDeniedException", "is not authorized to perform") { - log.Printf("[DEBUG] Skipping KMS Key (%s): %s", keyID, err) - continue - } - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("reading KMS Key (%s): %w", keyID, err)) + if tfawserr.ErrMessageContains(err, "AccessDeniedException", "is not authorized to perform") { + log.Printf("[DEBUG] Skipping KMS Key (%s): %s", keyID, err) continue } - if aws.StringValue(key.KeyManager) == kms.KeyManagerTypeAws { - log.Printf("[DEBUG] Skipping KMS Key (%s): managed by AWS", keyID) + if err != nil { continue } - if aws.StringValue(key.KeyState) == kms.KeyStatePendingDeletion { - log.Printf("[DEBUG] Skipping KMS Key (%s): pending deletion", keyID) + + if key.KeyManager == awstypes.KeyManagerTypeAws { + log.Printf("[DEBUG] Skipping KMS Key (%s): managed by AWS", keyID) continue } - r := ResourceKey() + r := resourceKey() d := r.Data(nil) d.SetId(keyID) d.Set("key_id", keyID) @@ -77,24 +80,13 @@ func sweepKeys(region string) error { sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping KMS Key sweep for %s: %s", region, err) - return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing KMS Keys (%s): %w", region, err)) } err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping KMS Keys (%s): %w", region, err)) + return fmt.Errorf("error sweeping KMS Keys (%s): %w", region, err) } - return sweeperErrs.ErrorOrNil() + return nil } diff --git a/internal/service/kms/tags_gen.go b/internal/service/kms/tags_gen.go index ccf4e8243e90..73b64516c75f 100644 --- a/internal/service/kms/tags_gen.go +++ b/internal/service/kms/tags_gen.go @@ -6,10 +6,10 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kms" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -23,35 +23,30 @@ import ( // listTags lists kms service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *kms.Client, identifier string, optFns ...func(*kms.Options)) (tftags.KeyValueTags, error) { input := &kms.ListResourceTagsInput{ KeyId: aws.String(identifier), } - var output []*kms.Tag + var output []awstypes.Tag - err := conn.ListResourceTagsPagesWithContext(ctx, input, func(page *kms.ListResourceTagsOutput, lastPage bool) bool { - if page == nil { - return !lastPage - } + pages := kms.NewListResourceTagsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx, optFns...) - for _, v := range page.Tags { - if v != nil { - output = append(output, v) + if tfawserr.ErrCodeEquals(err, "NotFoundException") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } } - return !lastPage - }) - - if tfawserr.ErrCodeEquals(err, "NotFoundException") { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, + if err != nil { + return tftags.New(ctx, nil), err } - } - if err != nil { - return tftags.New(ctx, nil), err + for _, v := range page.Tags { + output = append(output, v) + } } return KeyValueTags(ctx, output), nil @@ -60,7 +55,7 @@ func listTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string) (tft // ListTags lists kms service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).KMSConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).KMSClient(ctx), identifier) if err != nil { return err @@ -76,11 +71,11 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri // []*SERVICE.Tag handling // Tags returns kms service tags. -func Tags(tags tftags.KeyValueTags) []*kms.Tag { - result := make([]*kms.Tag, 0, len(tags)) +func Tags(tags tftags.KeyValueTags) []awstypes.Tag { + result := make([]awstypes.Tag, 0, len(tags)) for k, v := range tags.Map() { - tag := &kms.Tag{ + tag := awstypes.Tag{ TagKey: aws.String(k), TagValue: aws.String(v), } @@ -92,11 +87,11 @@ func Tags(tags tftags.KeyValueTags) []*kms.Tag { } // KeyValueTags creates tftags.KeyValueTags from kms service tags. -func KeyValueTags(ctx context.Context, tags []*kms.Tag) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags []awstypes.Tag) tftags.KeyValueTags { m := make(map[string]*string, len(tags)) for _, tag := range tags { - m[aws.StringValue(tag.TagKey)] = tag.TagValue + m[aws.ToString(tag.TagKey)] = tag.TagValue } return tftags.New(ctx, m) @@ -104,7 +99,7 @@ func KeyValueTags(ctx context.Context, tags []*kms.Tag) tftags.KeyValueTags { // getTagsIn returns kms service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*kms.Tag { +func getTagsIn(ctx context.Context) []awstypes.Tag { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -115,7 +110,7 @@ func getTagsIn(ctx context.Context) []*kms.Tag { } // setTagsOut sets kms service tags in Context. -func setTagsOut(ctx context.Context, tags []*kms.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -124,7 +119,7 @@ func setTagsOut(ctx context.Context, tags []*kms.Tag) { // updateTags updates kms service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *kms.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*kms.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -135,10 +130,10 @@ func updateTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string, ol if len(removedTags) > 0 { input := &kms.UntagResourceInput{ KeyId: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -153,7 +148,7 @@ func updateTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string, ol Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -161,7 +156,7 @@ func updateTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string, ol } if len(removedTags) > 0 || len(updatedTags) > 0 { - if err := waitTagsPropagated(ctx, conn, identifier, newTags); err != nil { + if err := waitTagsPropagated(ctx, conn, identifier, newTags, optFns...); err != nil { return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) } } @@ -172,19 +167,19 @@ func updateTags(ctx context.Context, conn kmsiface.KMSAPI, identifier string, ol // UpdateTags updates kms service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).KMSConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).KMSClient(ctx), identifier, oldTags, newTags) } // waitTagsPropagated waits for kms service tags to be propagated. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func waitTagsPropagated(ctx context.Context, conn kmsiface.KMSAPI, id string, tags tftags.KeyValueTags) error { +func waitTagsPropagated(ctx context.Context, conn *kms.Client, id string, tags tftags.KeyValueTags, optFns ...func(*kms.Options)) error { tflog.Debug(ctx, "Waiting for tag propagation", map[string]any{ "tags": tags, }) checkFunc := func() (bool, error) { - output, err := listTags(ctx, conn, id) + output, err := listTags(ctx, conn, id, optFns...) if tfresource.NotFound(err) { return false, nil diff --git a/internal/service/kms/validate.go b/internal/service/kms/validate.go index bc4a6e583801..49a85c90cef3 100644 --- a/internal/service/kms/validate.go +++ b/internal/service/kms/validate.go @@ -13,14 +13,14 @@ import ( ) const ( - aliasNameRegexPattern = `alias/[0-9A-Za-z_/-]+` - multiRegionKeyIdPattern = `mrk-[0-9a-f]{32}` + aliasNamePattern = aliasNamePrefix + `[0-9A-Za-z_/-]+` + multiRegionKeyIDPattern = `mrk-[0-9a-f]{32}` ) var ( - aliasNameRegex = regexache.MustCompile(`^` + aliasNameRegexPattern + `$`) - keyIdRegex = regexache.MustCompile(`^` + verify.UUIDRegexPattern + `|` + multiRegionKeyIdPattern + `$`) - keyIdResourceRegex = regexache.MustCompile(`^key/(` + verify.UUIDRegexPattern + `|` + multiRegionKeyIdPattern + `)$`) + aliasNameRegex = regexache.MustCompile(`^` + aliasNamePattern + `$`) + keyIDRegex = regexache.MustCompile(`^` + verify.UUIDRegexPattern + `|` + multiRegionKeyIDPattern + `$`) + keyIDResourceRegex = regexache.MustCompile(`^key/(` + verify.UUIDRegexPattern + `|` + multiRegionKeyIDPattern + `)$`) ) func validGrantName(v interface{}, k string) (ws []string, es []error) { @@ -50,7 +50,7 @@ func validNameForDataSource(v interface{}, k string) (ws []string, es []error) { func validNameForResource(v interface{}, k string) (ws []string, es []error) { value := v.(string) - if regexache.MustCompile(`^(alias/aws/)`).MatchString(value) { + if regexache.MustCompile(`^(` + cmkAliasPrefix + `)`).MatchString(value) { es = append(es, fmt.Errorf("%q cannot begin with reserved AWS CMK prefix 'alias/aws/'", k)) } @@ -61,19 +61,19 @@ func validNameForResource(v interface{}, k string) (ws []string, es []error) { return } -var ValidateKey = validation.Any( - validateKeyId, +var validateKey = validation.Any( + validateKeyID, validateKeyARN, ) -var ValidateKeyOrAlias = validation.Any( - validateKeyId, +var validateKeyOrAlias = validation.Any( + validateKeyID, validateKeyARN, validateKeyAliasName, validateKeyAliasARN, ) -var validateKeyId = validation.StringMatch(keyIdRegex, "must be a KMS Key ID") +var validateKeyID = validation.StringMatch(keyIDRegex, "must be a KMS Key ID") func validateKeyARN(v any, k string) (ws []string, errors []error) { value, ok := v.(string) diff --git a/internal/service/kms/wait.go b/internal/service/kms/wait.go index 7e83547b795f..68ae49e3c287 100644 --- a/internal/service/kms/wait.go +++ b/internal/service/kms/wait.go @@ -7,39 +7,28 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" - awspolicy "github.com/hashicorp/awspolicyequivalence" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + awstypes "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) const ( - // Maximum amount of time to wait for StatusKeyState to return PendingDeletion - KeyStatePendingDeletionTimeout = 20 * time.Minute + keyRotationUpdatedTimeout = 10 * time.Minute - KeyDeletedTimeout = 20 * time.Minute - KeyDescriptionPropagationTimeout = 10 * time.Minute - KeyMaterialImportedTimeout = 10 * time.Minute - KeyPolicyPropagationTimeout = 10 * time.Minute - KeyRotationUpdatedTimeout = 10 * time.Minute - KeyStatePropagationTimeout = 20 * time.Minute - KeyTagsPropagationTimeout = 10 * time.Minute - KeyValidToPropagationTimeout = 5 * time.Minute + // General timeout for KMS resource changes to propagate. + // See https://docs.aws.amazon.com/kms/latest/developerguide/programming-eventual-consistency.html + kmsPropagationTimeout = 3 * time.Minute // nosemgrep:ci.kms-in-const-name, ci.kms-in-var-name - PropagationTimeout = 2 * time.Minute - - ReplicaExternalKeyCreatedTimeout = 2 * time.Minute - ReplicaKeyCreatedTimeout = 2 * time.Minute + // General timeout for IAM resource change to propagate. + // See https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency. + // We have settled on 2 minutes as the best timeout value. + iamPropagationTimeout = 2 * time.Minute ) -// WaitIAMPropagation retries the specified function if the returned error indicates an IAM eventual consistency issue. -// If the retries time out the specified function is called one last time. -func WaitIAMPropagation[T any](ctx context.Context, timeout time.Duration, f func() (T, error)) (T, error) { - outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, timeout, func() (interface{}, error) { +// waitIAMPropagation retries the specified function if the returned error indicates an IAM eventual consistency issue. +func waitIAMPropagation[T any](ctx context.Context, timeout time.Duration, f func() (T, error)) (T, error) { + outputRaw, err := tfresource.RetryWhenIsA[*awstypes.MalformedPolicyDocumentException](ctx, timeout, func() (interface{}, error) { return f() - }, - kms.ErrCodeMalformedPolicyDocumentException) + }) if err != nil { var zero T @@ -48,191 +37,3 @@ func WaitIAMPropagation[T any](ctx context.Context, timeout time.Duration, f fun return outputRaw.(T), nil } - -func WaitKeyDeleted(ctx context.Context, conn *kms.KMS, id string) (*kms.KeyMetadata, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{kms.KeyStateDisabled, kms.KeyStateEnabled}, - Target: []string{}, - Refresh: StatusKeyState(ctx, conn, id), - Timeout: KeyDeletedTimeout, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*kms.KeyMetadata); ok { - return output, err - } - - return nil, err -} - -func WaitKeyDescriptionPropagated(ctx context.Context, conn *kms.KMS, id string, description string) error { - checkFunc := func() (bool, error) { - output, err := FindKeyByID(ctx, conn, id) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - return aws.StringValue(output.Description) == description, nil - } - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 5, - MinTimeout: 2 * time.Second, - } - - return tfresource.WaitUntil(ctx, KeyDescriptionPropagationTimeout, checkFunc, opts) -} - -func WaitKeyMaterialImported(ctx context.Context, conn *kms.KMS, id string) (*kms.KeyMetadata, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{kms.KeyStatePendingImport}, - Target: []string{kms.KeyStateDisabled, kms.KeyStateEnabled}, - Refresh: StatusKeyState(ctx, conn, id), - Timeout: KeyMaterialImportedTimeout, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*kms.KeyMetadata); ok { - return output, err - } - - return nil, err -} - -func WaitKeyPolicyPropagated(ctx context.Context, conn *kms.KMS, id, policy string) error { - checkFunc := func() (bool, error) { - output, err := FindKeyPolicyByKeyIDAndPolicyName(ctx, conn, id, PolicyNameDefault) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - equivalent, err := awspolicy.PoliciesAreEquivalent(aws.StringValue(output), policy) - - if err != nil { - return false, err - } - - return equivalent, nil - } - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 5, - MinTimeout: 1 * time.Second, - } - - return tfresource.WaitUntil(ctx, KeyPolicyPropagationTimeout, checkFunc, opts) -} - -func WaitKeyRotationEnabledPropagated(ctx context.Context, conn *kms.KMS, id string, enabled bool) error { - checkFunc := func() (bool, error) { - output, err := FindKeyRotationEnabledByKeyID(ctx, conn, id) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - return aws.BoolValue(output) == enabled, nil - } - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 5, - MinTimeout: 1 * time.Second, - } - - return tfresource.WaitUntil(ctx, KeyRotationUpdatedTimeout, checkFunc, opts) -} - -func WaitKeyStatePropagated(ctx context.Context, conn *kms.KMS, id string, enabled bool) error { - checkFunc := func() (bool, error) { - output, err := FindKeyByID(ctx, conn, id) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - return aws.BoolValue(output.Enabled) == enabled, nil - } - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 15, - MinTimeout: 2 * time.Second, - } - - return tfresource.WaitUntil(ctx, KeyStatePropagationTimeout, checkFunc, opts) -} - -func WaitKeyValidToPropagated(ctx context.Context, conn *kms.KMS, id string, validTo string) error { - checkFunc := func() (bool, error) { - output, err := FindKeyByID(ctx, conn, id) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - if output.ValidTo != nil { - return aws.TimeValue(output.ValidTo).Format(time.RFC3339) == validTo, nil - } - - return validTo == "", nil - } - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 5, - MinTimeout: 2 * time.Second, - } - - return tfresource.WaitUntil(ctx, KeyValidToPropagationTimeout, checkFunc, opts) -} - -func WaitReplicaExternalKeyCreated(ctx context.Context, conn *kms.KMS, id string) (*kms.KeyMetadata, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{kms.KeyStateCreating}, - Target: []string{kms.KeyStatePendingImport}, - Refresh: StatusKeyState(ctx, conn, id), - Timeout: ReplicaExternalKeyCreatedTimeout, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*kms.KeyMetadata); ok { - return output, err - } - - return nil, err -} - -func WaitReplicaKeyCreated(ctx context.Context, conn *kms.KMS, id string) (*kms.KeyMetadata, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{kms.KeyStateCreating}, - Target: []string{kms.KeyStateEnabled}, - Refresh: StatusKeyState(ctx, conn, id), - Timeout: ReplicaKeyCreatedTimeout, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*kms.KeyMetadata); ok { - return output, err - } - - return nil, err -} diff --git a/internal/service/lambda/permission.go b/internal/service/lambda/permission.go index 11973e58bd63..4df61599f0a9 100644 --- a/internal/service/lambda/permission.go +++ b/internal/service/lambda/permission.go @@ -157,7 +157,7 @@ func resourcePermissionCreate(ctx context.Context, d *schema.ResourceData, meta } // Retry for IAM and Lambda eventual consistency. - _, err := tfresource.RetryWhenIsOneOf[*awstypes.ResourceConflictException, *awstypes.ResourceNotFoundException](ctx, lambdaPropagationTimeout, + _, err := tfresource.RetryWhenIsOneOf2[*awstypes.ResourceConflictException, *awstypes.ResourceNotFoundException](ctx, lambdaPropagationTimeout, func() (interface{}, error) { return conn.AddPermission(ctx, input) }) diff --git a/internal/service/s3/bucket_object.go b/internal/service/s3/bucket_object.go index 59702972dc0f..524cd83d1c40 100644 --- a/internal/service/s3/bucket_object.go +++ b/internal/service/s3/bucket_object.go @@ -29,7 +29,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" - "github.com/hashicorp/terraform-provider-aws/internal/service/kms" + tfkms "github.com/hashicorp/terraform-provider-aws/internal/service/kms" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" itypes "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -508,8 +508,8 @@ func resourceBucketObjectSetKMS(ctx context.Context, d *schema.ResourceData, met // Only set non-default KMS key ID (one that doesn't match default) if sseKMSKeyId != nil { // retrieve S3 KMS Default Master Key - conn := meta.(*conns.AWSClient).KMSConn(ctx) - keyMetadata, err := kms.FindKeyByID(ctx, conn, defaultKMSKeyAlias) + conn := meta.(*conns.AWSClient).KMSClient(ctx) + keyMetadata, err := tfkms.FindKeyByID(ctx, conn, defaultKMSKeyAlias) if err != nil { return fmt.Errorf("Failed to describe default S3 KMS key (%s): %s", defaultKMSKeyAlias, err) } diff --git a/internal/service/s3/object.go b/internal/service/s3/object.go index 93b8119d054a..2153c44de4f7 100644 --- a/internal/service/s3/object.go +++ b/internal/service/s3/object.go @@ -31,7 +31,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" - "github.com/hashicorp/terraform-provider-aws/internal/service/kms" + tfkms "github.com/hashicorp/terraform-provider-aws/internal/service/kms" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" itypes "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -602,7 +602,7 @@ func setObjectKMSKeyID(ctx context.Context, meta interface{}, d *schema.Resource // Only set non-default KMS key ID (one that doesn't match default). if sseKMSKeyID != "" { // Read S3 KMS default master key. - keyMetadata, err := kms.FindKeyByID(ctx, meta.(*conns.AWSClient).KMSConn(ctx), defaultKMSKeyAlias) + keyMetadata, err := tfkms.FindKeyByID(ctx, meta.(*conns.AWSClient).KMSClient(ctx), defaultKMSKeyAlias) if err != nil { return fmt.Errorf("reading default S3 KMS key (%s): %s", defaultKMSKeyAlias, err) diff --git a/internal/tfresource/retry.go b/internal/tfresource/retry.go index 0eb968ba9c32..629c3cf7aa4f 100644 --- a/internal/tfresource/retry.go +++ b/internal/tfresource/retry.go @@ -162,7 +162,7 @@ func RetryWhenIsA[T error](ctx context.Context, timeout time.Duration, f func() }) } -func RetryWhenIsOneOf[T1, T2 error](ctx context.Context, timeout time.Duration, f func() (interface{}, error)) (interface{}, error) { +func RetryWhenIsOneOf2[T1, T2 error](ctx context.Context, timeout time.Duration, f func() (interface{}, error)) (interface{}, error) { return RetryWhen(ctx, timeout, f, func(err error) (bool, error) { if errs.IsA[T1](err) || errs.IsA[T2](err) { return true, err @@ -172,6 +172,16 @@ func RetryWhenIsOneOf[T1, T2 error](ctx context.Context, timeout time.Duration, }) } +func RetryWhenIsOneOf3[T1, T2, T3 error](ctx context.Context, timeout time.Duration, f func() (interface{}, error)) (interface{}, error) { + return RetryWhen(ctx, timeout, f, func(err error) (bool, error) { + if errs.IsA[T1](err) || errs.IsA[T2](err) || errs.IsA[T3](err) { + return true, err + } + + return false, err + }) +} + func RetryWhenIsAErrorMessageContains[T errs.ErrorWithErrorMessage](ctx context.Context, timeout time.Duration, f func() (interface{}, error), needle string) (interface{}, error) { return RetryWhen(ctx, timeout, f, func(err error) (bool, error) { if errs.IsAErrorMessageContains[T](err, needle) { diff --git a/names/data/names_data.csv b/names/data/names_data.csv index ffea25df9fe0..76199ad6f1c5 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -216,7 +216,7 @@ kinesisvideo,kinesisvideo,kinesisvideo,kinesisvideo,,kinesisvideo,,,KinesisVideo kinesis-video-archived-media,kinesisvideoarchivedmedia,kinesisvideoarchivedmedia,kinesisvideoarchivedmedia,,kinesisvideoarchivedmedia,,,KinesisVideoArchivedMedia,KinesisVideoArchivedMedia,,1,,,aws_kinesisvideoarchivedmedia_,,kinesisvideoarchivedmedia_,Kinesis Video Archived Media,Amazon,,x,,,,,Kinesis Video Archived Media,,, kinesis-video-media,kinesisvideomedia,kinesisvideomedia,kinesisvideomedia,,kinesisvideomedia,,,KinesisVideoMedia,KinesisVideoMedia,,1,,,aws_kinesisvideomedia_,,kinesisvideomedia_,Kinesis Video Media,Amazon,,x,,,,,Kinesis Video Media,,, kinesis-video-signaling,kinesisvideosignaling,kinesisvideosignalingchannels,kinesisvideosignaling,,kinesisvideosignaling,,kinesisvideosignalingchannels,KinesisVideoSignaling,KinesisVideoSignalingChannels,,1,,,aws_kinesisvideosignaling_,,kinesisvideosignaling_,Kinesis Video Signaling,Amazon,,x,,,,,Kinesis Video Signaling,,, -kms,kms,kms,kms,,kms,,,KMS,KMS,,1,,,aws_kms_,,kms_,KMS (Key Management),AWS,,,,,,,KMS,ListKeys,, +kms,kms,kms,kms,,kms,,,KMS,KMS,,,2,,aws_kms_,,kms_,KMS (Key Management),AWS,,,,,,,KMS,ListKeys,, lakeformation,lakeformation,lakeformation,lakeformation,,lakeformation,,,LakeFormation,LakeFormation,,,2,,aws_lakeformation_,,lakeformation_,Lake Formation,AWS,,,,,,,LakeFormation,ListResources,, lambda,lambda,lambda,lambda,,lambda,,,Lambda,Lambda,,,2,,aws_lambda_,,lambda_,Lambda,AWS,,,,,,,Lambda,ListFunctions,, launch-wizard,launchwizard,launchwizard,launchwizard,,launchwizard,,,LaunchWizard,LaunchWizard,,,2,,aws_launchwizard_,,launchwizard_,Launch Wizard,AWS,,,,,,,Launch Wizard,ListWorkloads,, diff --git a/names/names.go b/names/names.go index ad25c7b9d491..938491055a19 100644 --- a/names/names.go +++ b/names/names.go @@ -64,6 +64,7 @@ const ( Inspector2EndpointID = "inspector2" IVSChatEndpointID = "ivschat" KendraEndpointID = "kendra" + KMSEndpointID = "kms" LambdaEndpointID = "lambda" LexV2ModelsEndpointID = "models-v2-lex" M2EndpointID = "m2"