Skip to content

Commit

Permalink
provider/aws: Add aws_elasticsearch_domain_policy
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Feb 8, 2017
1 parent 2319ea6 commit 50d3ebb
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 0 deletions.
38 changes: 38 additions & 0 deletions builtin/providers/aws/diff_aws_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package aws

import (
"fmt"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/jen20/awspolicyequivalence"
)

func testAccCheckAwsPolicyMatch(resource, attr, expectedPolicy string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resource]
if !ok {
return fmt.Errorf("Not found: %s", resource)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

given, ok := rs.Primary.Attributes[attr]
if !ok {
return fmt.Errorf("Attribute %q not found for %q", attr, resource)
}

areEquivalent, err := awspolicy.PoliciesAreEquivalent(given, expectedPolicy)
if err != nil {
return fmt.Errorf("Comparing AWS Policies failed: %s", err)
}

if !areEquivalent {
return fmt.Errorf("AWS policies differ.\nGiven: %s\nExpected: %s", given, expectedPolicy)
}

return nil
}
}
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ func Provider() terraform.ResourceProvider {
"aws_elastic_beanstalk_configuration_template": resourceAwsElasticBeanstalkConfigurationTemplate(),
"aws_elastic_beanstalk_environment": resourceAwsElasticBeanstalkEnvironment(),
"aws_elasticsearch_domain": resourceAwsElasticSearchDomain(),
"aws_elasticsearch_domain_policy": resourceAwsElasticSearchDomainPolicy(),
"aws_elastictranscoder_pipeline": resourceAwsElasticTranscoderPipeline(),
"aws_elastictranscoder_preset": resourceAwsElasticTranscoderPreset(),
"aws_elb": resourceAwsElb(),
Expand Down
1 change: 1 addition & 0 deletions builtin/providers/aws/resource_aws_elasticsearch_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func resourceAwsElasticSearchDomain() *schema.Resource {
"access_policies": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateJsonString,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
Expand Down
127 changes: 127 additions & 0 deletions builtin/providers/aws/resource_aws_elasticsearch_domain_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package aws

import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsElasticSearchDomainPolicy() *schema.Resource {
return &schema.Resource{
Create: resourceAwsElasticSearchDomainPolicyUpsert,
Read: resourceAwsElasticSearchDomainPolicyRead,
Update: resourceAwsElasticSearchDomainPolicyUpsert,
Delete: resourceAwsElasticSearchDomainPolicyDelete,

Schema: map[string]*schema.Schema{
"domain_name": {
Type: schema.TypeString,
Required: true,
},
"access_policies": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
},
}
}

func resourceAwsElasticSearchDomainPolicyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).esconn
name := d.Get("domain_name").(string)
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
DomainName: aws.String(name),
})
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFound" {
log.Printf("[WARN] ElasticSearch Domain %q not found, removing", name)
d.SetId("")
return nil
}
return err
}

log.Printf("[DEBUG] Received ElasticSearch domain: %s", out)

ds := out.DomainStatus
d.Set("access_policies", ds.AccessPolicies)

return nil
}

func resourceAwsElasticSearchDomainPolicyUpsert(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).esconn
domainName := d.Get("domain_name").(string)
_, err := conn.UpdateElasticsearchDomainConfig(&elasticsearch.UpdateElasticsearchDomainConfigInput{
DomainName: aws.String(domainName),
AccessPolicies: aws.String(d.Get("access_policies").(string)),
})
if err != nil {
return err
}

d.SetId("esd-policy-" + domainName)

err = resource.Retry(50*time.Minute, func() *resource.RetryError {
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
DomainName: aws.String(d.Get("domain_name").(string)),
})
if err != nil {
return resource.NonRetryableError(err)
}

if *out.DomainStatus.Processing == false {
return nil
}

return resource.RetryableError(
fmt.Errorf("%q: Timeout while waiting for changes to be processed", d.Id()))
})
if err != nil {
return err
}

return resourceAwsElasticSearchDomainPolicyRead(d, meta)
}

func resourceAwsElasticSearchDomainPolicyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).esconn

_, err := conn.UpdateElasticsearchDomainConfig(&elasticsearch.UpdateElasticsearchDomainConfigInput{
DomainName: aws.String(d.Get("domain_name").(string)),
AccessPolicies: aws.String(""),
})
if err != nil {
return err
}

log.Printf("[DEBUG] Waiting for ElasticSearch domain policy %q to be deleted", d.Get("domain_name").(string))
err = resource.Retry(60*time.Minute, func() *resource.RetryError {
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
DomainName: aws.String(d.Get("domain_name").(string)),
})
if err != nil {
return resource.NonRetryableError(err)
}

if *out.DomainStatus.Processing == false {
return nil
}

return resource.RetryableError(
fmt.Errorf("%q: Timeout while waiting for policy to be deleted", d.Id()))
})
if err != nil {
return err
}

d.SetId("")
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package aws

import (
"fmt"
"testing"

elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)

func TestAccAWSElasticSearchDomainPolicy_basic(t *testing.T) {
var domain elasticsearch.ElasticsearchDomainStatus
ri := acctest.RandInt()
policy := `{
"Version": "2012-10-17",
"Statement": [
{
"Action": "es:*",
"Principal": "*",
"Effect": "Allow",
"Condition": {
"IpAddress": {"aws:SourceIp": "127.0.0.1/32"}
},
"Resource": "${aws_elasticsearch_domain.example.arn}"
}
]
}`
expectedPolicyTpl := `{
"Version": "2012-10-17",
"Statement": [
{
"Action": "es:*",
"Principal": "*",
"Effect": "Allow",
"Condition": {
"IpAddress": {"aws:SourceIp": "127.0.0.1/32"}
},
"Resource": "%s"
}
]
}`
name := fmt.Sprintf("tf-test-%d", ri)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckESDomainDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccESDomainPolicyConfig(ri, policy),
Check: resource.ComposeTestCheckFunc(
testAccCheckESDomainExists("aws_elasticsearch_domain.example", &domain),
resource.TestCheckResourceAttr("aws_elasticsearch_domain.example", "elasticsearch_version", "2.3"),
func(s *terraform.State) error {
awsClient := testAccProvider.Meta().(*AWSClient)
expectedArn, err := buildESDomainArn(name, awsClient.partition, awsClient.accountid, awsClient.region)
if err != nil {
return err
}
expectedPolicy := fmt.Sprintf(expectedPolicyTpl, expectedArn)

return testAccCheckAwsPolicyMatch("aws_elasticsearch_domain_policy.main", "access_policies", expectedPolicy)(s)
},
),
},
},
})
}

func buildESDomainArn(name, partition, accId, region string) (string, error) {
if partition == "" {
return "", fmt.Errorf("Unable to construct ES Domain ARN because of missing AWS partition")
}
if accId == "" {
return "", fmt.Errorf("Unable to construct ES Domain ARN because of missing AWS Account ID")
}
// arn:aws:es:us-west-2:187416307283:domain/example-name
return fmt.Sprintf("arn:%s:es:%s:%s:domain/%s", partition, region, accId, name), nil
}

func testAccESDomainPolicyConfig(randInt int, policy string) string {
return fmt.Sprintf(`
resource "aws_elasticsearch_domain" "example" {
domain_name = "tf-test-%d"
elasticsearch_version = "2.3"
}
resource "aws_elasticsearch_domain_policy" "main" {
domain_name = "${aws_elasticsearch_domain.example.domain_name}"
access_policies = <<POLICIES
%s
POLICIES
}
`, randInt, policy)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
layout: "aws"
page_title: "AWS: aws_elasticsearch_domain"
sidebar_current: "docs-aws-resource-elasticsearch-domain"
description: |-
Provides an ElasticSearch Domain.
---

# aws\_elasticsearch\_domain\_policy

Allows setting policy to an ElasticSearch domain while referencing domain attributes (e.g. ARN)

## Example Usage

```
resource "aws_elasticsearch_domain" "example" {
domain_name = "tf-test"
elasticsearch_version = "2.3"
}
resource "aws_elasticsearch_domain_policy" "main" {
domain_name = "${aws_elasticsearch_domain.example.domain_name}"
access_policies = <<POLICIES
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "es:*",
"Principal": "*",
"Effect": "Allow",
"Condition": {
"IpAddress": {"aws:SourceIp": "127.0.0.1/32"}
},
"Resource": "${aws_elasticsearch_domain.example.arn}"
}
]
}
POLICIES
}
```

## Argument Reference

The following arguments are supported:

* `domain_name` - (Required) Name of the domain.
* `access_policies` - (Optional) IAM policy document specifying the access policies for the domain
4 changes: 4 additions & 0 deletions website/source/layouts/aws.erb
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,10 @@
<a href="/docs/providers/aws/r/elasticsearch_domain.html">aws_elasticsearch_domain</a>
</li>

<li<%= sidebar_current("docs-aws-resource-elasticsearch-domain-policy") %>>
<a href="/docs/providers/aws/r/elasticsearch_domain_policy.html">aws_elasticsearch_domain_policy</a>
</li>

</ul>
</li>

Expand Down

0 comments on commit 50d3ebb

Please sign in to comment.