From 1556c29ab00e8b8379c5a6aa2c498159e92d9324 Mon Sep 17 00:00:00 2001 From: Barry Tam Date: Wed, 29 Jan 2020 06:05:27 -0800 Subject: [PATCH] resource/aws_elasticsearch_domain DomainEndpointOptions (#10430) Output from acceptance testing: ``` --- PASS: TestAccAWSElasticSearchDomain_duplicate (544.63s) --- PASS: TestAccAWSElasticSearchDomain_encrypt_at_rest_specify_key (681.50s) --- PASS: TestAccAWSElasticSearchDomain_v23 (712.83s) --- PASS: TestAccAWSElasticSearchDomain_NodeToNodeEncryption (906.35s) --- PASS: TestAccAWSElasticSearchDomain_complex (1003.67s) --- PASS: TestAccAWSElasticSearchDomainPolicy_basic (1044.35s) --- PASS: TestAccAWSElasticSearchDomain_tags (1069.02s) --- PASS: TestAccAWSElasticSearchDomain_policy (1187.09s) --- PASS: TestAccAWSElasticSearchDomain_LogPublishingOptions (1222.33s) --- PASS: TestAccAWSElasticSearchDomain_encrypt_at_rest_default_key (1366.06s) --- PASS: TestAccAWSElasticSearchDomain_vpc (1495.79s) --- PASS: TestAccAWSElasticSearchDomain_RequireHTTPS (1505.39s) --- PASS: TestAccAWSElasticSearchDomain_CognitoOptionsUpdate (1690.98s) --- PASS: TestAccAWSElasticSearchDomain_CognitoOptionsCreateAndRemove (1755.31s) --- PASS: TestAccAWSElasticSearchDomain_basic (1907.01s) --- PASS: TestAccAWSElasticSearchDomain_vpc_update (1910.87s) --- PASS: TestAccAWSElasticSearchDomain_update (2195.83s) --- PASS: TestAccAWSElasticSearchDomain_internetToVpcEndpoint (2547.44s) --- PASS: TestAccAWSElasticSearchDomain_update_volume_type (2685.22s) --- PASS: TestAccAWSElasticSearchDomain_update_version (3011.87s) --- PASS: TestAccAWSElasticSearchDomain_withDedicatedMaster (3977.83s) --- PASS: TestAccAWSElasticSearchDomain_ClusterConfig_ZoneAwarenessConfig (5310.68s) ``` --- aws/resource_aws_elasticsearch_domain.go | 35 ++++++++++ aws/resource_aws_elasticsearch_domain_test.go | 65 +++++++++++++++++++ aws/structure.go | 32 +++++++++ .../docs/r/elasticsearch_domain.html.markdown | 6 ++ 4 files changed, 138 insertions(+) diff --git a/aws/resource_aws_elasticsearch_domain.go b/aws/resource_aws_elasticsearch_domain.go index ee7e2abcd2f..fe347d155e2 100644 --- a/aws/resource_aws_elasticsearch_domain.go +++ b/aws/resource_aws_elasticsearch_domain.go @@ -87,6 +87,29 @@ func resourceAwsElasticSearchDomain() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "domain_endpoint_options": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enforce_https": { + Type: schema.TypeBool, + Required: true, + }, + "tls_security_policy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + elasticsearch.TLSSecurityPolicyPolicyMinTls10201907, + elasticsearch.TLSSecurityPolicyPolicyMinTls12201907, + }, false), + }, + }, + }, + }, "endpoint": { Type: schema.TypeString, Computed: true, @@ -444,6 +467,10 @@ func resourceAwsElasticSearchDomainCreate(d *schema.ResourceData, meta interface } } + if v, ok := d.GetOk("domain_endpoint_options"); ok { + input.DomainEndpointOptions = expandESDomainEndpointOptions(v.([]interface{})) + } + if v, ok := d.GetOk("cognito_options"); ok { input.CognitoOptions = expandESCognitoOptions(v.([]interface{})) } @@ -648,6 +675,10 @@ func resourceAwsElasticSearchDomainRead(d *schema.ResourceData, meta interface{} d.Set("log_publishing_options", m) } + if err := d.Set("domain_endpoint_options", flattenESDomainEndpointOptions(ds.DomainEndpointOptions)); err != nil { + return fmt.Errorf("error setting domain_endpoint_options: %s", err) + } + d.Set("arn", ds.ARN) tags, err := keyvaluetags.ElasticsearchserviceListTags(conn, d.Id()) @@ -686,6 +717,10 @@ func resourceAwsElasticSearchDomainUpdate(d *schema.ResourceData, meta interface input.AdvancedOptions = stringMapToPointers(d.Get("advanced_options").(map[string]interface{})) } + if d.HasChange("domain_endpoint_options") { + input.DomainEndpointOptions = expandESDomainEndpointOptions(d.Get("domain_endpoint_options").([]interface{})) + } + if d.HasChange("ebs_options") || d.HasChange("cluster_config") { options := d.Get("ebs_options").([]interface{}) diff --git a/aws/resource_aws_elasticsearch_domain_test.go b/aws/resource_aws_elasticsearch_domain_test.go index 219ac98f3b6..d884734879e 100644 --- a/aws/resource_aws_elasticsearch_domain_test.go +++ b/aws/resource_aws_elasticsearch_domain_test.go @@ -87,6 +87,40 @@ func TestAccAWSElasticSearchDomain_basic(t *testing.T) { }) } +func TestAccAWSElasticSearchDomain_RequireHTTPS(t *testing.T) { + var domain elasticsearch.ElasticsearchDomainStatus + ri := acctest.RandInt() + resourceId := fmt.Sprintf("tf-test-%d", ri) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckESDomainDestroy, + Steps: []resource.TestStep{ + { + Config: testAccESDomainConfig_DomainEndpointOptions(ri, true, "Policy-Min-TLS-1-0-2019-07"), + Check: resource.ComposeTestCheckFunc( + testAccCheckESDomainExists("aws_elasticsearch_domain.example", &domain), + testAccCheckESDomainEndpointOptions(true, "Policy-Min-TLS-1-0-2019-07", &domain), + ), + }, + { + ResourceName: "aws_elasticsearch_domain.example", + ImportState: true, + ImportStateId: resourceId, + ImportStateVerify: true, + }, + { + Config: testAccESDomainConfig_DomainEndpointOptions(ri, true, "Policy-Min-TLS-1-2-2019-07"), + Check: resource.ComposeTestCheckFunc( + testAccCheckESDomainExists("aws_elasticsearch_domain.example", &domain), + testAccCheckESDomainEndpointOptions(true, "Policy-Min-TLS-1-2-2019-07", &domain), + ), + }, + }, + }) +} + func TestAccAWSElasticSearchDomain_ClusterConfig_ZoneAwarenessConfig(t *testing.T) { var domain1, domain2, domain3, domain4 elasticsearch.ElasticsearchDomainStatus rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) // len = 28 @@ -759,6 +793,19 @@ func TestAccAWSElasticSearchDomain_update_version(t *testing.T) { }}) } +func testAccCheckESDomainEndpointOptions(enforceHTTPS bool, tls string, status *elasticsearch.ElasticsearchDomainStatus) resource.TestCheckFunc { + return func(s *terraform.State) error { + options := status.DomainEndpointOptions + if *options.EnforceHTTPS != enforceHTTPS { + return fmt.Errorf("EnforceHTTPS differ. Given: %t, Expected: %t", *options.EnforceHTTPS, enforceHTTPS) + } + if *options.TLSSecurityPolicy != tls { + return fmt.Errorf("TLSSecurityPolicy differ. Given: %s, Expected: %s", *options.TLSSecurityPolicy, tls) + } + return nil + } +} + func testAccCheckESNumberOfSecurityGroups(numberOfSecurityGroups int, status *elasticsearch.ElasticsearchDomainStatus) resource.TestCheckFunc { return func(s *terraform.State) error { count := len(status.VPCOptions.SecurityGroupIds) @@ -958,6 +1005,24 @@ resource "aws_elasticsearch_domain" "test" { `, randInt) } +func testAccESDomainConfig_DomainEndpointOptions(randInt int, enforceHttps bool, tlsSecurityPolicy string) string { + return fmt.Sprintf(` +resource "aws_elasticsearch_domain" "example" { + domain_name = "tf-test-%[1]d" + + domain_endpoint_options { + enforce_https = %[2]t + tls_security_policy = %[3]q + } + + ebs_options { + ebs_enabled = true + volume_size = 10 + } +} +`, randInt, enforceHttps, tlsSecurityPolicy) +} + func testAccESDomainConfig_ClusterConfig_ZoneAwarenessConfig_AvailabilityZoneCount(rName string, availabilityZoneCount int) string { return fmt.Sprintf(` resource "aws_elasticsearch_domain" "test" { diff --git a/aws/structure.go b/aws/structure.go index 2d9a04c4c04..438359e0854 100644 --- a/aws/structure.go +++ b/aws/structure.go @@ -1348,6 +1348,38 @@ func flattenESCognitoOptions(c *elasticsearch.CognitoOptions) []map[string]inter return []map[string]interface{}{m} } +func expandESDomainEndpointOptions(l []interface{}) *elasticsearch.DomainEndpointOptions { + if len(l) == 0 || l[0] == nil { + return nil + } + + m := l[0].(map[string]interface{}) + domainEndpointOptions := &elasticsearch.DomainEndpointOptions{} + + if v, ok := m["enforce_https"].(bool); ok { + domainEndpointOptions.EnforceHTTPS = aws.Bool(v) + } + + if v, ok := m["tls_security_policy"].(string); ok { + domainEndpointOptions.TLSSecurityPolicy = aws.String(v) + } + + return domainEndpointOptions +} + +func flattenESDomainEndpointOptions(domainEndpointOptions *elasticsearch.DomainEndpointOptions) []interface{} { + if domainEndpointOptions == nil { + return nil + } + + m := map[string]interface{}{ + "enforce_https": aws.BoolValue(domainEndpointOptions.EnforceHTTPS), + "tls_security_policy": aws.StringValue(domainEndpointOptions.TLSSecurityPolicy), + } + + return []interface{}{m} +} + func flattenESSnapshotOptions(snapshotOptions *elasticsearch.SnapshotOptions) []map[string]interface{} { if snapshotOptions == nil { return []map[string]interface{}{} diff --git a/website/docs/r/elasticsearch_domain.html.markdown b/website/docs/r/elasticsearch_domain.html.markdown index 76af91b94a7..70e014eb0f0 100644 --- a/website/docs/r/elasticsearch_domain.html.markdown +++ b/website/docs/r/elasticsearch_domain.html.markdown @@ -224,6 +224,7 @@ The following arguments are supported: * `vpc_options` - (Optional) VPC related options, see below. Adding or removing this configuration forces a new resource ([documentation](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-vpc-limitations)). * `log_publishing_options` - (Optional) Options for publishing slow logs to CloudWatch Logs. * `elasticsearch_version` - (Optional) The version of Elasticsearch to deploy. Defaults to `1.5` +* `enforce_httpsnt_options` - (Optional) Domain endpoint HTTP(S) related options. See below. * `tags` - (Optional) A mapping of tags to assign to the resource **ebs_options** supports the following attributes: @@ -240,6 +241,11 @@ The following arguments are supported: * `enabled` - (Required) Whether to enable encryption at rest. If the `encrypt_at_rest` block is not provided then this defaults to `false`. * `kms_key_id` - (Optional) The KMS key id to encrypt the Elasticsearch domain with. If not specified then it defaults to using the `aws/es` service KMS key. +**domain_endpoint_options** supports the following attributes: + +* `require_https` - (Required) Whether or not to require HTTPS +* `tls_security_policy` - (Optional) The name of the TLS security policy that needs to be applied to the HTTPS endpoint. Valid values: `Policy-Min-TLS-1-0-2019-07` and `Policy-Min-TLS-1-2-2019-07`. Terraform will only perform drift detection if a configuration value is provided. + **cluster_config** supports the following attributes: * `instance_type` - (Optional) Instance type of data nodes in the cluster.