From 8facd7187f87b2bd2603c29c5de8a1dba779bce7 Mon Sep 17 00:00:00 2001 From: Michael Ericksen Date: Wed, 15 Jan 2020 09:35:39 -0600 Subject: [PATCH] enable aws organizations TAG_POLICY and attach to target --- aws/resource_aws_organizations_policy.go | 1 + ...rce_aws_organizations_policy_attachment.go | 14 ++--- ...ws_organizations_policy_attachment_test.go | 36 ++++++++---- aws/resource_aws_organizations_policy_test.go | 57 +++++++++++++++++++ aws/resource_aws_organizations_test.go | 1 + .../docs/r/organizations_policy.html.markdown | 4 +- 6 files changed, 92 insertions(+), 21 deletions(-) diff --git a/aws/resource_aws_organizations_policy.go b/aws/resource_aws_organizations_policy.go index c0d3b0ea34f..739a7448a7a 100644 --- a/aws/resource_aws_organizations_policy.go +++ b/aws/resource_aws_organizations_policy.go @@ -48,6 +48,7 @@ func resourceAwsOrganizationsPolicy() *schema.Resource { Default: organizations.PolicyTypeServiceControlPolicy, ValidateFunc: validation.StringInSlice([]string{ organizations.PolicyTypeServiceControlPolicy, + organizations.PolicyTypeTagPolicy, }, false), }, }, diff --git a/aws/resource_aws_organizations_policy_attachment.go b/aws/resource_aws_organizations_policy_attachment.go index c2a47540d1b..8834511ec5c 100644 --- a/aws/resource_aws_organizations_policy_attachment.go +++ b/aws/resource_aws_organizations_policy_attachment.go @@ -84,16 +84,16 @@ func resourceAwsOrganizationsPolicyAttachmentRead(d *schema.ResourceData, meta i return err } - input := &organizations.ListPoliciesForTargetInput{ - Filter: aws.String(organizations.PolicyTypeServiceControlPolicy), - TargetId: aws.String(targetID), + input := &organizations.ListTargetsForPolicyInput{ + PolicyId: aws.String(policyID), } log.Printf("[DEBUG] Listing Organizations Policies for Target: %s", input) - var output *organizations.PolicySummary - err = conn.ListPoliciesForTargetPages(input, func(page *organizations.ListPoliciesForTargetOutput, lastPage bool) bool { - for _, policySummary := range page.Policies { - if aws.StringValue(policySummary.Id) == policyID { + var output *organizations.PolicyTargetSummary + + err = conn.ListTargetsForPolicyPages(input, func(page *organizations.ListTargetsForPolicyOutput, lastPage bool) bool { + for _, policySummary := range page.Targets { + if aws.StringValue(policySummary.TargetId) == targetID { output = policySummary return true } diff --git a/aws/resource_aws_organizations_policy_attachment_test.go b/aws/resource_aws_organizations_policy_attachment_test.go index 51b3df522bc..4db48c1e39b 100644 --- a/aws/resource_aws_organizations_policy_attachment_test.go +++ b/aws/resource_aws_organizations_policy_attachment_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strconv" "testing" "github.com/aws/aws-sdk-go/aws" @@ -18,13 +19,24 @@ func testAccAwsOrganizationsPolicyAttachment_Account(t *testing.T) { policyIdResourceName := "aws_organizations_policy.test" targetIdResourceName := "aws_organizations_organization.test" + serviceControlPolicyContent := `{"Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "*", "Resource": "*"}}` + tagPolicyContent := `{ "tags": { "Product": { "tag_key": { "@@assign": "Product" }, "enforced_for": { "@@assign": [ "ec2:instance" ] } } } }` + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccOrganizationsAccountPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAwsOrganizationsPolicyAttachmentDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsOrganizationsPolicyAttachmentConfig_Account(rName), + Config: testAccAwsOrganizationsPolicyAttachmentConfig_Account(rName, organizations.PolicyTypeServiceControlPolicy, serviceControlPolicyContent), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsOrganizationsPolicyAttachmentExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "policy_id", policyIdResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "target_id", targetIdResourceName, "master_account_id"), + ), + }, + { + Config: testAccAwsOrganizationsPolicyAttachmentConfig_Account(rName, organizations.PolicyTypeTagPolicy, tagPolicyContent), Check: resource.ComposeTestCheckFunc( testAccCheckAwsOrganizationsPolicyAttachmentExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "policy_id", policyIdResourceName, "id"), @@ -163,16 +175,15 @@ func testAccCheckAwsOrganizationsPolicyAttachmentExists(resourceName string) res return err } - input := &organizations.ListPoliciesForTargetInput{ - Filter: aws.String(organizations.PolicyTypeServiceControlPolicy), - TargetId: aws.String(targetID), + input := &organizations.ListTargetsForPolicyInput{ + PolicyId: aws.String(policyID), } log.Printf("[DEBUG] Listing Organizations Policies for Target: %s", input) - var output *organizations.PolicySummary - err = conn.ListPoliciesForTargetPages(input, func(page *organizations.ListPoliciesForTargetOutput, lastPage bool) bool { - for _, policySummary := range page.Policies { - if aws.StringValue(policySummary.Id) == policyID { + var output *organizations.PolicyTargetSummary + err = conn.ListTargetsForPolicyPages(input, func(page *organizations.ListTargetsForPolicyOutput, lastPage bool) bool { + for _, policySummary := range page.Targets { + if aws.StringValue(policySummary.TargetId) == targetID { output = policySummary return true } @@ -192,24 +203,25 @@ func testAccCheckAwsOrganizationsPolicyAttachmentExists(resourceName string) res } } -func testAccAwsOrganizationsPolicyAttachmentConfig_Account(rName string) string { +func testAccAwsOrganizationsPolicyAttachmentConfig_Account(rName, policyType, policyContent string) string { return fmt.Sprintf(` resource "aws_organizations_organization" "test" { - enabled_policy_types = ["SERVICE_CONTROL_POLICY"] + enabled_policy_types = ["SERVICE_CONTROL_POLICY", "TAG_POLICY"] } resource "aws_organizations_policy" "test" { depends_on = ["aws_organizations_organization.test"] - content = "{\"Version\": \"2012-10-17\", \"Statement\": { \"Effect\": \"Allow\", \"Action\": \"*\", \"Resource\": \"*\"}}" name = "%s" + type = "%s" + content = %s } resource "aws_organizations_policy_attachment" "test" { policy_id = "${aws_organizations_policy.test.id}" target_id = "${aws_organizations_organization.test.master_account_id}" } -`, rName) +`, rName, policyType, strconv.Quote(policyContent)) } func testAccAwsOrganizationsPolicyAttachmentConfig_OrganizationalUnit(rName string) string { diff --git a/aws/resource_aws_organizations_policy_test.go b/aws/resource_aws_organizations_policy_test.go index d9879bf9433..0f619d99e3a 100644 --- a/aws/resource_aws_organizations_policy_test.go +++ b/aws/resource_aws_organizations_policy_test.go @@ -113,6 +113,49 @@ func testAccAwsOrganizationsPolicy_description(t *testing.T) { }) } +func testAccAwsOrganizationsPolicy_type(t *testing.T) { + var policy organizations.Policy + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_organizations_policy.test" + + serviceControlPolicyContent := `{"Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "*", "Resource": "*"}}` + tagPolicyContent := `{ "tags": { "Product": { "tag_key": { "@@assign": "Product" }, "enforced_for": { "@@assign": [ "ec2:instance" ] } } } }` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsOrganizationsPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsOrganizationsPolicyConfig_Type(rName, serviceControlPolicyContent, organizations.PolicyTypeServiceControlPolicy), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsOrganizationsPolicyExists(resourceName, &policy), + resource.TestCheckResourceAttr(resourceName, "type", organizations.PolicyTypeServiceControlPolicy), + ), + }, + { + Config: testAccAwsOrganizationsPolicyConfig_Type(rName, tagPolicyContent, organizations.PolicyTypeTagPolicy), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsOrganizationsPolicyExists(resourceName, &policy), + resource.TestCheckResourceAttr(resourceName, "type", organizations.PolicyTypeTagPolicy), + ), + }, + { + Config: testAccAwsOrganizationsPolicyConfig_Required(rName, serviceControlPolicyContent), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsOrganizationsPolicyExists(resourceName, &policy), + resource.TestCheckResourceAttr(resourceName, "type", organizations.PolicyTypeServiceControlPolicy), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAwsOrganizationsPolicyDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).organizationsconn @@ -243,3 +286,17 @@ resource "aws_organizations_policy" "test5" { } `, rName) } + +func testAccAwsOrganizationsPolicyConfig_Type(rName, content, policyType string) string { + return fmt.Sprintf(` +resource "aws_organizations_organization" "test" {} + +resource "aws_organizations_policy" "test" { + content = %s + name = "%s" + type = "%s" + + depends_on = ["aws_organizations_organization.test"] +} +`, strconv.Quote(content), rName, policyType) +} diff --git a/aws/resource_aws_organizations_test.go b/aws/resource_aws_organizations_test.go index 2dcf93686aa..b2ed655f5e0 100644 --- a/aws/resource_aws_organizations_test.go +++ b/aws/resource_aws_organizations_test.go @@ -29,6 +29,7 @@ func TestAccAWSOrganizations(t *testing.T) { "basic": testAccAwsOrganizationsPolicy_basic, "concurrent": testAccAwsOrganizationsPolicy_concurrent, "Description": testAccAwsOrganizationsPolicy_description, + "Type": testAccAwsOrganizationsPolicy_type, }, "PolicyAttachment": { "Account": testAccAwsOrganizationsPolicyAttachment_Account, diff --git a/website/docs/r/organizations_policy.html.markdown b/website/docs/r/organizations_policy.html.markdown index df0794925ac..fc02d28af24 100644 --- a/website/docs/r/organizations_policy.html.markdown +++ b/website/docs/r/organizations_policy.html.markdown @@ -33,10 +33,10 @@ CONTENT The following arguments are supported: -* `content` - (Required) The policy content to add to the new policy. For example, if you create a [service control policy (SCP)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scp.html), this string must be JSON text that specifies the permissions that admins in attached accounts can delegate to their users, groups, and roles. For more information about the SCP syntax, see the [Service Control Policy Syntax documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_reference_scp-syntax.html). +* `content` - (Required) The policy content to add to the new policy. For example, if you create a [service control policy (SCP)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scp.html), this string must be JSON text that specifies the permissions that admins in attached accounts can delegate to their users, groups, and roles. For more information about the SCP syntax, see the [Service Control Policy Syntax documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_reference_scp-syntax.html) and for more information on the Tag Policy syntax, see the [Tag Policy Syntax documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_example-tag-policies.html). * `name` - (Required) The friendly name to assign to the policy. * `description` - (Optional) A description to assign to the policy. -* `type` - (Optional) The type of policy to create. Currently, the only valid value is `SERVICE_CONTROL_POLICY` (SCP). +* `type` - (Optional) The type of policy to create. Currently, the only valid values are `SERVICE_CONTROL_POLICY` (SCP) and `TAG_POLICY`. Defaults to `SERVICE_CONTROL_POLICY`. ## Attribute Reference