terraform/builtin/providers/aws/resource_aws_iam_role_polic...

153 lines
3.8 KiB
Go
Raw Normal View History

package aws
import (
"fmt"
"net/url"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsIamRolePolicy() *schema.Resource {
return &schema.Resource{
// PutRolePolicy API is idempotent, so these can be the same.
Create: resourceAwsIamRolePolicyPut,
Update: resourceAwsIamRolePolicyPut,
Read: resourceAwsIamRolePolicyRead,
Delete: resourceAwsIamRolePolicyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
provider/aws: validation: Add validation function for IAM Policies The previous JSON validator that we were using for IAM policy documents wouldn't catch AWS IAM Policy errors. The supplied policy document would pass our validator, then fail with the following API error: ``` * aws_iam_role_policy.foo: Error putting IAM role policy tf_test_policy_ymw7hbil9w: MalformedPolicyDocument: The policy failed legacy parsing status code: 400, request id: e7615d90-3c99-11e7-babc-c14e741605bf ``` This happens if the Policy Document doesn't start with the opening JSON bracket, and often happens in the following case: ``` policy = <<EOF { "Version": "2012-10-17", "Statement": [ { ... } ] } EOF ``` Where, when using a HEREDOC, the policy document is indented incorrectly. The new validation function for the IAM policies verifies that the first character of the supplied policy document is the leading JSON bracket, prior to validating the JSON string. Test Output: ``` $ make test TEST=./builtin/providers/aws/ TESTARGS="-v -run=TestValidateIAMPolicyJsonString" ==> Checking that code complies with gofmt requirements... ==> Checking AWS provider for unchecked errors... ==> NOTE: at this time we only look for uncheck errors in the AWS package go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:56:32 Generated command/internal_plugin_list.go go test -i ./builtin/providers/aws/ || exit 1 echo ./builtin/providers/aws/ | \ xargs -t -n4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 ./builtin/providers/aws/ === RUN TestValidateIAMPolicyJsonString --- PASS: TestValidateIAMPolicyJsonString (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.009s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAWSPolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:38:43 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAWSPolicy_ -timeout 120m === RUN TestAWSPolicy_namePrefix --- PASS: TestAWSPolicy_namePrefix (20.01s) === RUN TestAWSPolicy_invalidJson --- PASS: TestAWSPolicy_invalidJson (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 20.027s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSIAMRolePolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 11:02:56 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSIAMRolePolicy_ -timeout 120m === RUN TestAccAWSIAMRolePolicy_importBasic --- PASS: TestAccAWSIAMRolePolicy_importBasic (18.45s) === RUN TestAccAWSIAMRolePolicy_basic --- PASS: TestAccAWSIAMRolePolicy_basic (35.92s) === RUN TestAccAWSIAMRolePolicy_namePrefix --- PASS: TestAccAWSIAMRolePolicy_namePrefix (14.78s) === RUN TestAccAWSIAMRolePolicy_generatedName --- PASS: TestAccAWSIAMRolePolicy_generatedName (20.20s) === RUN TestAccAWSIAMRolePolicy_invalidJSON --- PASS: TestAccAWSIAMRolePolicy_invalidJSON (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 89.363s ```
2017-05-19 17:11:44 +02:00
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateIAMPolicyJson,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
provider/aws: validation: Add validation function for IAM Policies The previous JSON validator that we were using for IAM policy documents wouldn't catch AWS IAM Policy errors. The supplied policy document would pass our validator, then fail with the following API error: ``` * aws_iam_role_policy.foo: Error putting IAM role policy tf_test_policy_ymw7hbil9w: MalformedPolicyDocument: The policy failed legacy parsing status code: 400, request id: e7615d90-3c99-11e7-babc-c14e741605bf ``` This happens if the Policy Document doesn't start with the opening JSON bracket, and often happens in the following case: ``` policy = <<EOF { "Version": "2012-10-17", "Statement": [ { ... } ] } EOF ``` Where, when using a HEREDOC, the policy document is indented incorrectly. The new validation function for the IAM policies verifies that the first character of the supplied policy document is the leading JSON bracket, prior to validating the JSON string. Test Output: ``` $ make test TEST=./builtin/providers/aws/ TESTARGS="-v -run=TestValidateIAMPolicyJsonString" ==> Checking that code complies with gofmt requirements... ==> Checking AWS provider for unchecked errors... ==> NOTE: at this time we only look for uncheck errors in the AWS package go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:56:32 Generated command/internal_plugin_list.go go test -i ./builtin/providers/aws/ || exit 1 echo ./builtin/providers/aws/ | \ xargs -t -n4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 ./builtin/providers/aws/ === RUN TestValidateIAMPolicyJsonString --- PASS: TestValidateIAMPolicyJsonString (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.009s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAWSPolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:38:43 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAWSPolicy_ -timeout 120m === RUN TestAWSPolicy_namePrefix --- PASS: TestAWSPolicy_namePrefix (20.01s) === RUN TestAWSPolicy_invalidJson --- PASS: TestAWSPolicy_invalidJson (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 20.027s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSIAMRolePolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 11:02:56 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSIAMRolePolicy_ -timeout 120m === RUN TestAccAWSIAMRolePolicy_importBasic --- PASS: TestAccAWSIAMRolePolicy_importBasic (18.45s) === RUN TestAccAWSIAMRolePolicy_basic --- PASS: TestAccAWSIAMRolePolicy_basic (35.92s) === RUN TestAccAWSIAMRolePolicy_namePrefix --- PASS: TestAccAWSIAMRolePolicy_namePrefix (14.78s) === RUN TestAccAWSIAMRolePolicy_generatedName --- PASS: TestAccAWSIAMRolePolicy_generatedName (20.20s) === RUN TestAccAWSIAMRolePolicy_invalidJSON --- PASS: TestAccAWSIAMRolePolicy_invalidJSON (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 89.363s ```
2017-05-19 17:11:44 +02:00
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name_prefix"},
ValidateFunc: validateIamRolePolicyName,
},
provider/aws: validation: Add validation function for IAM Policies The previous JSON validator that we were using for IAM policy documents wouldn't catch AWS IAM Policy errors. The supplied policy document would pass our validator, then fail with the following API error: ``` * aws_iam_role_policy.foo: Error putting IAM role policy tf_test_policy_ymw7hbil9w: MalformedPolicyDocument: The policy failed legacy parsing status code: 400, request id: e7615d90-3c99-11e7-babc-c14e741605bf ``` This happens if the Policy Document doesn't start with the opening JSON bracket, and often happens in the following case: ``` policy = <<EOF { "Version": "2012-10-17", "Statement": [ { ... } ] } EOF ``` Where, when using a HEREDOC, the policy document is indented incorrectly. The new validation function for the IAM policies verifies that the first character of the supplied policy document is the leading JSON bracket, prior to validating the JSON string. Test Output: ``` $ make test TEST=./builtin/providers/aws/ TESTARGS="-v -run=TestValidateIAMPolicyJsonString" ==> Checking that code complies with gofmt requirements... ==> Checking AWS provider for unchecked errors... ==> NOTE: at this time we only look for uncheck errors in the AWS package go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:56:32 Generated command/internal_plugin_list.go go test -i ./builtin/providers/aws/ || exit 1 echo ./builtin/providers/aws/ | \ xargs -t -n4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 ./builtin/providers/aws/ === RUN TestValidateIAMPolicyJsonString --- PASS: TestValidateIAMPolicyJsonString (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.009s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAWSPolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:38:43 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAWSPolicy_ -timeout 120m === RUN TestAWSPolicy_namePrefix --- PASS: TestAWSPolicy_namePrefix (20.01s) === RUN TestAWSPolicy_invalidJson --- PASS: TestAWSPolicy_invalidJson (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 20.027s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSIAMRolePolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 11:02:56 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSIAMRolePolicy_ -timeout 120m === RUN TestAccAWSIAMRolePolicy_importBasic --- PASS: TestAccAWSIAMRolePolicy_importBasic (18.45s) === RUN TestAccAWSIAMRolePolicy_basic --- PASS: TestAccAWSIAMRolePolicy_basic (35.92s) === RUN TestAccAWSIAMRolePolicy_namePrefix --- PASS: TestAccAWSIAMRolePolicy_namePrefix (14.78s) === RUN TestAccAWSIAMRolePolicy_generatedName --- PASS: TestAccAWSIAMRolePolicy_generatedName (20.20s) === RUN TestAccAWSIAMRolePolicy_invalidJSON --- PASS: TestAccAWSIAMRolePolicy_invalidJSON (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 89.363s ```
2017-05-19 17:11:44 +02:00
"name_prefix": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validateIamRolePolicyNamePrefix,
},
provider/aws: validation: Add validation function for IAM Policies The previous JSON validator that we were using for IAM policy documents wouldn't catch AWS IAM Policy errors. The supplied policy document would pass our validator, then fail with the following API error: ``` * aws_iam_role_policy.foo: Error putting IAM role policy tf_test_policy_ymw7hbil9w: MalformedPolicyDocument: The policy failed legacy parsing status code: 400, request id: e7615d90-3c99-11e7-babc-c14e741605bf ``` This happens if the Policy Document doesn't start with the opening JSON bracket, and often happens in the following case: ``` policy = <<EOF { "Version": "2012-10-17", "Statement": [ { ... } ] } EOF ``` Where, when using a HEREDOC, the policy document is indented incorrectly. The new validation function for the IAM policies verifies that the first character of the supplied policy document is the leading JSON bracket, prior to validating the JSON string. Test Output: ``` $ make test TEST=./builtin/providers/aws/ TESTARGS="-v -run=TestValidateIAMPolicyJsonString" ==> Checking that code complies with gofmt requirements... ==> Checking AWS provider for unchecked errors... ==> NOTE: at this time we only look for uncheck errors in the AWS package go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:56:32 Generated command/internal_plugin_list.go go test -i ./builtin/providers/aws/ || exit 1 echo ./builtin/providers/aws/ | \ xargs -t -n4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 go test -v -run=TestValidateIAMPolicyJsonString -timeout=60s -parallel=4 ./builtin/providers/aws/ === RUN TestValidateIAMPolicyJsonString --- PASS: TestValidateIAMPolicyJsonString (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.009s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAWSPolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 10:38:43 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAWSPolicy_ -timeout 120m === RUN TestAWSPolicy_namePrefix --- PASS: TestAWSPolicy_namePrefix (20.01s) === RUN TestAWSPolicy_invalidJson --- PASS: TestAWSPolicy_invalidJson (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 20.027s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSIAMRolePolicy_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/05/19 11:02:56 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSIAMRolePolicy_ -timeout 120m === RUN TestAccAWSIAMRolePolicy_importBasic --- PASS: TestAccAWSIAMRolePolicy_importBasic (18.45s) === RUN TestAccAWSIAMRolePolicy_basic --- PASS: TestAccAWSIAMRolePolicy_basic (35.92s) === RUN TestAccAWSIAMRolePolicy_namePrefix --- PASS: TestAccAWSIAMRolePolicy_namePrefix (14.78s) === RUN TestAccAWSIAMRolePolicy_generatedName --- PASS: TestAccAWSIAMRolePolicy_generatedName (20.20s) === RUN TestAccAWSIAMRolePolicy_invalidJSON --- PASS: TestAccAWSIAMRolePolicy_invalidJSON (0.00s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 89.363s ```
2017-05-19 17:11:44 +02:00
"role": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceAwsIamRolePolicyPut(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
request := &iam.PutRolePolicyInput{
RoleName: aws.String(d.Get("role").(string)),
PolicyDocument: aws.String(d.Get("policy").(string)),
}
var policyName string
if v, ok := d.GetOk("name"); ok {
policyName = v.(string)
} else if v, ok := d.GetOk("name_prefix"); ok {
policyName = resource.PrefixedUniqueId(v.(string))
} else {
policyName = resource.UniqueId()
}
request.PolicyName = aws.String(policyName)
if _, err := iamconn.PutRolePolicy(request); err != nil {
return fmt.Errorf("Error putting IAM role policy %s: %s", *request.PolicyName, err)
}
d.SetId(fmt.Sprintf("%s:%s", *request.RoleName, *request.PolicyName))
return nil
}
func resourceAwsIamRolePolicyRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
role, name, err := resourceAwsIamRolePolicyParseId(d.Id())
if err != nil {
return err
}
request := &iam.GetRolePolicyInput{
PolicyName: aws.String(name),
RoleName: aws.String(role),
}
getResp, err := iamconn.GetRolePolicy(request)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IAM policy %s from role %s: %s", name, role, err)
}
if getResp.PolicyDocument == nil {
return fmt.Errorf("GetRolePolicy returned a nil policy document")
}
policy, err := url.QueryUnescape(*getResp.PolicyDocument)
if err != nil {
return err
}
if err := d.Set("policy", policy); err != nil {
return err
}
if err := d.Set("name", name); err != nil {
return err
}
return d.Set("role", role)
}
func resourceAwsIamRolePolicyDelete(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
role, name, err := resourceAwsIamRolePolicyParseId(d.Id())
if err != nil {
return err
}
request := &iam.DeleteRolePolicyInput{
PolicyName: aws.String(name),
RoleName: aws.String(role),
}
if _, err := iamconn.DeleteRolePolicy(request); err != nil {
return fmt.Errorf("Error deleting IAM role policy %s: %s", d.Id(), err)
}
return nil
}
func resourceAwsIamRolePolicyParseId(id string) (roleName, policyName string, err error) {
2015-04-18 22:58:08 +02:00
parts := strings.SplitN(id, ":", 2)
if len(parts) != 2 {
err = fmt.Errorf("role_policy id must be of the form <role name>:<policy name>")
return
}
2015-04-18 22:58:08 +02:00
roleName = parts[0]
policyName = parts[1]
return
}