diff --git a/aws/internal/service/xray/waiter/status.go b/aws/internal/service/xray/waiter/status.go new file mode 100644 index 00000000000..935321da8d8 --- /dev/null +++ b/aws/internal/service/xray/waiter/status.go @@ -0,0 +1,25 @@ +package waiter + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/xray" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const ( + EncryptionConfigStatusUnknown = "Unknown" +) + +// EncryptionConfigStatus fetches the Encryption Config and its Status +func EncryptionConfigStatus(conn *xray.XRay) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + + output, _ := conn.GetEncryptionConfig(&xray.GetEncryptionConfigInput{}) + + if output == nil || output.EncryptionConfig == nil { + return output, EncryptionConfigStatusUnknown, nil + } + + return output, aws.StringValue(output.EncryptionConfig.Status), nil + } +} diff --git a/aws/internal/service/xray/waiter/waiter.go b/aws/internal/service/xray/waiter/waiter.go new file mode 100644 index 00000000000..dde602a6b00 --- /dev/null +++ b/aws/internal/service/xray/waiter/waiter.go @@ -0,0 +1,30 @@ +package waiter + +import ( + "time" + + "github.com/aws/aws-sdk-go/service/xray" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const ( + EncryptionConfigAvailableTimeout = 15 * time.Minute +) + +// EncryptionConfigAvailable waits for a EncryptionConfig to return Available +func EncryptionConfigAvailable(conn *xray.XRay) (*xray.EncryptionConfig, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{xray.EncryptionStatusUpdating}, + Target: []string{xray.EncryptionStatusActive}, + Refresh: EncryptionConfigStatus(conn), + Timeout: EncryptionConfigAvailableTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if v, ok := outputRaw.(*xray.EncryptionConfig); ok { + return v, err + } + + return nil, err +} diff --git a/aws/provider.go b/aws/provider.go index c0c91672f10..abfe7176e05 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -937,6 +937,7 @@ func Provider() *schema.Provider { "aws_pinpoint_event_stream": resourceAwsPinpointEventStream(), "aws_pinpoint_gcm_channel": resourceAwsPinpointGCMChannel(), "aws_pinpoint_sms_channel": resourceAwsPinpointSMSChannel(), + "aws_xray_encryption_config": resourceAwsXrayEncryptionConfig(), "aws_xray_group": resourceAwsXrayGroup(), "aws_xray_sampling_rule": resourceAwsXraySamplingRule(), "aws_workspaces_ip_group": resourceAwsWorkspacesIpGroup(), diff --git a/aws/resource_aws_xray_encryption_config.go b/aws/resource_aws_xray_encryption_config.go new file mode 100644 index 00000000000..7435e3c5800 --- /dev/null +++ b/aws/resource_aws_xray_encryption_config.go @@ -0,0 +1,80 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/xray" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/xray/waiter" +) + +func resourceAwsXrayEncryptionConfig() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsXrayEncryptionConfigPut, + Read: resourceAwsXrayEncryptionConfigRead, + Update: resourceAwsXrayEncryptionConfigPut, + Delete: schema.Noop, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "key_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + xray.EncryptionTypeKms, + xray.EncryptionTypeNone, + }, false), + }, + }, + } +} + +func resourceAwsXrayEncryptionConfigPut(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).xrayconn + + input := &xray.PutEncryptionConfigInput{ + Type: aws.String(d.Get("type").(string)), + } + + if v, ok := d.GetOk("key_id"); ok { + input.KeyId = aws.String(v.(string)) + } + + _, err := conn.PutEncryptionConfig(input) + if err != nil { + return fmt.Errorf("error creating XRay Encryption Config: %w", err) + } + + d.SetId(meta.(*AWSClient).region) + + if _, err := waiter.EncryptionConfigAvailable(conn); err != nil { + return fmt.Errorf("error waiting for Xray Encryption Config (%s) to Available: %w", d.Id(), err) + } + + return resourceAwsXrayEncryptionConfigRead(d, meta) +} + +func resourceAwsXrayEncryptionConfigRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).xrayconn + + config, err := conn.GetEncryptionConfig(&xray.GetEncryptionConfigInput{}) + + if err != nil { + return fmt.Errorf("error reading XRay Encryption Config: %w", err) + } + + d.Set("key_id", config.EncryptionConfig.KeyId) + d.Set("type", config.EncryptionConfig.Type) + + return nil +} diff --git a/aws/resource_aws_xray_encryption_config_test.go b/aws/resource_aws_xray_encryption_config_test.go new file mode 100644 index 00000000000..b3f2a62f0d0 --- /dev/null +++ b/aws/resource_aws_xray_encryption_config_test.go @@ -0,0 +1,116 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/xray" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSXrayEncryptionConfig_basic(t *testing.T) { + var EncryptionConfig xray.EncryptionConfig + resourceName := "aws_xray_encryption_config.test" + keyResourceName := "aws_kms_key.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAWSXrayEncryptionConfigBasicConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckXrayEncryptionConfigExists(resourceName, &EncryptionConfig), + resource.TestCheckResourceAttr(resourceName, "type", "NONE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSXrayEncryptionConfigWithKeyConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckXrayEncryptionConfigExists(resourceName, &EncryptionConfig), + resource.TestCheckResourceAttr(resourceName, "type", "KMS"), + resource.TestCheckResourceAttrPair(resourceName, "key_id", keyResourceName, "arn"), + ), + }, + { + Config: testAccAWSXrayEncryptionConfigBasicConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckXrayEncryptionConfigExists(resourceName, &EncryptionConfig), + resource.TestCheckResourceAttr(resourceName, "type", "NONE"), + ), + }, + }, + }) +} + +func testAccCheckXrayEncryptionConfigExists(n string, EncryptionConfig *xray.EncryptionConfig) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No XRay Encryption Config ID is set") + } + conn := testAccProvider.Meta().(*AWSClient).xrayconn + + config, err := conn.GetEncryptionConfig(&xray.GetEncryptionConfigInput{}) + + if err != nil { + return err + } + + *EncryptionConfig = *config.EncryptionConfig + + return nil + } +} + +func testAccAWSXrayEncryptionConfigBasicConfig() string { + return fmt.Sprintf(` +resource "aws_xray_encryption_config" "test" { + type = "NONE" +} +`) +} + +func testAccAWSXrayEncryptionConfigWithKeyConfig() string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = "Terraform acc test %s" + deletion_window_in_days = 7 + + policy = < **NOTE:** Removing this resource from Terraform has no effect to the encryption configuration within X-Ray. + +## Example Usage + +```hcl +resource "aws_xray_encryption_config" "example" { + type = "NONE" +} +``` + +## Example Usage with KMS Key + +```hcl +resource "aws_kms_key" "example" { + description = "Some Key" + deletion_window_in_days = 7 + + policy = <