Skip to content

Commit

Permalink
Merge pull request #6052 from YakDriver/iam-pol-doc-opt-stmt
Browse files Browse the repository at this point in the history
data_source/aws_iam_policy_document: Make statement optional
  • Loading branch information
bflad authored Oct 4, 2018
2 parents 4748fe9 + 56f79a3 commit ad23f70
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 46 deletions.
91 changes: 47 additions & 44 deletions aws/data_source_aws_iam_policy_document.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func dataSourceAwsIamPolicyDocument() *schema.Resource {
},
"statement": {
Type: schema.TypeList,
Required: true,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sid": {
Expand Down Expand Up @@ -96,8 +96,8 @@ func dataSourceAwsIamPolicyDocumentRead(d *schema.ResourceData, meta interface{}
mergedDoc := &IAMPolicyDoc{}

// populate mergedDoc directly with any source_json
if sourceJson, hasSourceJson := d.GetOk("source_json"); hasSourceJson {
if err := json.Unmarshal([]byte(sourceJson.(string)), mergedDoc); err != nil {
if sourceJSON, hasSourceJSON := d.GetOk("source_json"); hasSourceJSON {
if err := json.Unmarshal([]byte(sourceJSON.(string)), mergedDoc); err != nil {
return err
}
}
Expand All @@ -107,64 +107,67 @@ func dataSourceAwsIamPolicyDocumentRead(d *schema.ResourceData, meta interface{}

doc.Version = "2012-10-17"

if policyId, hasPolicyId := d.GetOk("policy_id"); hasPolicyId {
doc.Id = policyId.(string)
if policyID, hasPolicyID := d.GetOk("policy_id"); hasPolicyID {
doc.Id = policyID.(string)
}

var cfgStmts = d.Get("statement").([]interface{})
stmts := make([]*IAMPolicyStatement, len(cfgStmts))
for i, stmtI := range cfgStmts {
cfgStmt := stmtI.(map[string]interface{})
stmt := &IAMPolicyStatement{
Effect: cfgStmt["effect"].(string),
}
if cfgStmts, hasCfgStmts := d.GetOk("statement"); hasCfgStmts {
var cfgStmtIntf = cfgStmts.([]interface{})
stmts := make([]*IAMPolicyStatement, len(cfgStmtIntf))
for i, stmtI := range cfgStmtIntf {
cfgStmt := stmtI.(map[string]interface{})
stmt := &IAMPolicyStatement{
Effect: cfgStmt["effect"].(string),
}

if sid, ok := cfgStmt["sid"]; ok {
stmt.Sid = sid.(string)
}
if sid, ok := cfgStmt["sid"]; ok {
stmt.Sid = sid.(string)
}

if actions := cfgStmt["actions"].(*schema.Set).List(); len(actions) > 0 {
stmt.Actions = iamPolicyDecodeConfigStringList(actions)
}
if actions := cfgStmt["not_actions"].(*schema.Set).List(); len(actions) > 0 {
stmt.NotActions = iamPolicyDecodeConfigStringList(actions)
}
if actions := cfgStmt["actions"].(*schema.Set).List(); len(actions) > 0 {
stmt.Actions = iamPolicyDecodeConfigStringList(actions)
}
if actions := cfgStmt["not_actions"].(*schema.Set).List(); len(actions) > 0 {
stmt.NotActions = iamPolicyDecodeConfigStringList(actions)
}

if resources := cfgStmt["resources"].(*schema.Set).List(); len(resources) > 0 {
stmt.Resources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
iamPolicyDecodeConfigStringList(resources),
)
}
if resources := cfgStmt["not_resources"].(*schema.Set).List(); len(resources) > 0 {
stmt.NotResources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
iamPolicyDecodeConfigStringList(resources),
)
}
if resources := cfgStmt["resources"].(*schema.Set).List(); len(resources) > 0 {
stmt.Resources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
iamPolicyDecodeConfigStringList(resources),
)
}
if resources := cfgStmt["not_resources"].(*schema.Set).List(); len(resources) > 0 {
stmt.NotResources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
iamPolicyDecodeConfigStringList(resources),
)
}

if principals := cfgStmt["principals"].(*schema.Set).List(); len(principals) > 0 {
stmt.Principals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
}
if principals := cfgStmt["principals"].(*schema.Set).List(); len(principals) > 0 {
stmt.Principals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
}

if principals := cfgStmt["not_principals"].(*schema.Set).List(); len(principals) > 0 {
stmt.NotPrincipals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
}
if principals := cfgStmt["not_principals"].(*schema.Set).List(); len(principals) > 0 {
stmt.NotPrincipals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
}

if conditions := cfgStmt["condition"].(*schema.Set).List(); len(conditions) > 0 {
stmt.Conditions = dataSourceAwsIamPolicyDocumentMakeConditions(conditions)
if conditions := cfgStmt["condition"].(*schema.Set).List(); len(conditions) > 0 {
stmt.Conditions = dataSourceAwsIamPolicyDocumentMakeConditions(conditions)
}

stmts[i] = stmt
}

stmts[i] = stmt
}
doc.Statements = stmts

doc.Statements = stmts
}

// merge our current document into mergedDoc
mergedDoc.Merge(doc)

// merge in override_json
if overrideJson, hasOverrideJson := d.GetOk("override_json"); hasOverrideJson {
if overrideJSON, hasOverrideJSON := d.GetOk("override_json"); hasOverrideJSON {
overrideDoc := &IAMPolicyDoc{}
if err := json.Unmarshal([]byte(overrideJson.(string)), overrideDoc); err != nil {
if err := json.Unmarshal([]byte(overrideJSON.(string)), overrideDoc); err != nil {
return err
}

Expand Down
110 changes: 110 additions & 0 deletions aws/data_source_aws_iam_policy_document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,40 @@ func TestAccAWSDataSourceIAMPolicyDocument_override(t *testing.T) {
})
}

func TestAccAWSDataSourceIAMPolicyDocument_noStatementMerge(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMPolicyDocumentNoStatementMergeConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckStateValue("data.aws_iam_policy_document.yak_politik", "json",
testAccAWSIAMPolicyDocumentNoStatementMergeExpectedJSON,
),
),
},
},
})
}

func TestAccAWSDataSourceIAMPolicyDocument_noStatementOverride(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMPolicyDocumentNoStatementOverrideConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckStateValue("data.aws_iam_policy_document.yak_politik", "json",
testAccAWSIAMPolicyDocumentNoStatementOverrideExpectedJSON,
),
),
},
},
})
}

func testAccCheckStateValue(id, name, value string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[id]
Expand Down Expand Up @@ -520,3 +554,79 @@ var testAccAWSIAMPolicyDocumentOverrideExpectedJSON = `{
}
]
}`

var testAccAWSIAMPolicyDocumentNoStatementMergeConfig = `
data "aws_iam_policy_document" "source" {
statement {
sid = ""
actions = ["ec2:DescribeAccountAttributes"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "override" {
statement {
sid = "OverridePlaceholder"
actions = ["s3:GetObject"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "yak_politik" {
source_json = "${data.aws_iam_policy_document.source.json}"
override_json = "${data.aws_iam_policy_document.override.json}"
}
`

var testAccAWSIAMPolicyDocumentNoStatementMergeExpectedJSON = `{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": "ec2:DescribeAccountAttributes",
"Resource": "*"
},
{
"Sid": "OverridePlaceholder",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}`

var testAccAWSIAMPolicyDocumentNoStatementOverrideConfig = `
data "aws_iam_policy_document" "source" {
statement {
sid = "OverridePlaceholder"
actions = ["ec2:DescribeAccountAttributes"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "override" {
statement {
sid = "OverridePlaceholder"
actions = ["s3:GetObject"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "yak_politik" {
source_json = "${data.aws_iam_policy_document.source.json}"
override_json = "${data.aws_iam_policy_document.override.json}"
}
`

var testAccAWSIAMPolicyDocumentNoStatementOverrideExpectedJSON = `{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OverridePlaceholder",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}`
47 changes: 45 additions & 2 deletions website/docs/d/iam_policy_document.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ The following arguments are supported:
current policy document. Statements with non-blank `sid`s in the override
document will overwrite statements with the same `sid` in the current document.
Statements without an `sid` cannot be overwritten.
* `statement` (Required) - A nested configuration block (described below)
* `statement` (Optional) - A nested configuration block (described below)
configuring one *statement* to be included in the policy document.

Each document configuration must have one or more `statement` blocks, which
Each document configuration may have one or more `statement` blocks, which
each accept the following arguments:

* `sid` (Optional) - An ID for the policy statement.
Expand Down Expand Up @@ -297,3 +297,46 @@ data "aws_iam_policy_document" "override_json_example" {
```

You can also combine `source_json` and `override_json` in the same document.

## Example without Statement

Use without a `statement`:

```hcl
data "aws_iam_policy_document" "source" {
statement {
sid = "OverridePlaceholder"
actions = ["ec2:DescribeAccountAttributes"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "override" {
statement {
sid = "OverridePlaceholder"
actions = ["s3:GetObject"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "politik" {
source_json = "${data.aws_iam_policy_document.source.json}"
override_json = "${data.aws_iam_policy_document.override.json}"
}
```

`data.aws_iam_policy_document.politik.json` will evaluate to:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OverridePlaceholder",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}
```

0 comments on commit ad23f70

Please sign in to comment.