/vendor/github.com/terraform-providers/terraform-provider-aws/aws/resource_aws_iam_policy.go
https://github.com/openshift/installer · Go · 316 lines · 256 code · 51 blank · 9 comment · 57 complexity · 8de61d5fc5f331a9814888fa9a8b5fbf MD5 · raw file
- package aws
- import (
- "fmt"
- "log"
- "net/url"
- "regexp"
- "time"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/service/iam"
- "github.com/hashicorp/terraform-plugin-sdk/helper/resource"
- "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
- "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
- )
- func resourceAwsIamPolicy() *schema.Resource {
- return &schema.Resource{
- Create: resourceAwsIamPolicyCreate,
- Read: resourceAwsIamPolicyRead,
- Update: resourceAwsIamPolicyUpdate,
- Delete: resourceAwsIamPolicyDelete,
- Importer: &schema.ResourceImporter{
- State: schema.ImportStatePassthrough,
- },
- Schema: map[string]*schema.Schema{
- "description": {
- Type: schema.TypeString,
- ForceNew: true,
- Optional: true,
- },
- "path": {
- Type: schema.TypeString,
- Optional: true,
- Default: "/",
- ForceNew: true,
- },
- "policy": {
- Type: schema.TypeString,
- Required: true,
- ValidateFunc: validateIAMPolicyJson,
- DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
- },
- "name": {
- Type: schema.TypeString,
- Optional: true,
- Computed: true,
- ForceNew: true,
- ConflictsWith: []string{"name_prefix"},
- ValidateFunc: validation.All(
- validation.StringLenBetween(1, 128),
- validation.StringMatch(regexp.MustCompile(`^[\w+=,.@-]*$`), "must match [\\w+=,.@-]"),
- ),
- },
- "name_prefix": {
- Type: schema.TypeString,
- Optional: true,
- ForceNew: true,
- ConflictsWith: []string{"name"},
- ValidateFunc: validation.All(
- validation.StringLenBetween(1, 96),
- validation.StringMatch(regexp.MustCompile(`^[\w+=,.@-]*$`), "must match [\\w+=,.@-]"),
- ),
- },
- "arn": {
- Type: schema.TypeString,
- Computed: true,
- },
- },
- }
- }
- func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error {
- iamconn := meta.(*AWSClient).iamconn
- var name string
- if v, ok := d.GetOk("name"); ok {
- name = v.(string)
- } else if v, ok := d.GetOk("name_prefix"); ok {
- name = resource.PrefixedUniqueId(v.(string))
- } else {
- name = resource.UniqueId()
- }
- request := &iam.CreatePolicyInput{
- Description: aws.String(d.Get("description").(string)),
- Path: aws.String(d.Get("path").(string)),
- PolicyDocument: aws.String(d.Get("policy").(string)),
- PolicyName: aws.String(name),
- }
- response, err := iamconn.CreatePolicy(request)
- if err != nil {
- return fmt.Errorf("Error creating IAM policy %s: %s", name, err)
- }
- d.SetId(*response.Policy.Arn)
- return resourceAwsIamPolicyRead(d, meta)
- }
- func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
- iamconn := meta.(*AWSClient).iamconn
- getPolicyRequest := &iam.GetPolicyInput{
- PolicyArn: aws.String(d.Id()),
- }
- log.Printf("[DEBUG] Getting IAM Policy: %s", getPolicyRequest)
- // Handle IAM eventual consistency
- var getPolicyResponse *iam.GetPolicyOutput
- err := resource.Retry(1*time.Minute, func() *resource.RetryError {
- var err error
- getPolicyResponse, err = iamconn.GetPolicy(getPolicyRequest)
- if d.IsNewResource() && isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
- return resource.RetryableError(err)
- }
- if err != nil {
- return resource.NonRetryableError(err)
- }
- return nil
- })
- if isResourceTimeoutError(err) {
- getPolicyResponse, err = iamconn.GetPolicy(getPolicyRequest)
- }
- if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
- log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
- d.SetId("")
- return nil
- }
- if err != nil {
- return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err)
- }
- if getPolicyResponse == nil || getPolicyResponse.Policy == nil {
- log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
- d.SetId("")
- return nil
- }
- d.Set("arn", getPolicyResponse.Policy.Arn)
- d.Set("description", getPolicyResponse.Policy.Description)
- d.Set("name", getPolicyResponse.Policy.PolicyName)
- d.Set("path", getPolicyResponse.Policy.Path)
- // Retrieve policy
- getPolicyVersionRequest := &iam.GetPolicyVersionInput{
- PolicyArn: aws.String(d.Id()),
- VersionId: getPolicyResponse.Policy.DefaultVersionId,
- }
- log.Printf("[DEBUG] Getting IAM Policy Version: %s", getPolicyVersionRequest)
- // Handle IAM eventual consistency
- var getPolicyVersionResponse *iam.GetPolicyVersionOutput
- err = resource.Retry(1*time.Minute, func() *resource.RetryError {
- var err error
- getPolicyVersionResponse, err = iamconn.GetPolicyVersion(getPolicyVersionRequest)
- if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
- return resource.RetryableError(err)
- }
- if err != nil {
- return resource.NonRetryableError(err)
- }
- return nil
- })
- if isResourceTimeoutError(err) {
- getPolicyVersionResponse, err = iamconn.GetPolicyVersion(getPolicyVersionRequest)
- }
- if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
- log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
- d.SetId("")
- return nil
- }
- if err != nil {
- return fmt.Errorf("Error reading IAM policy version %s: %s", d.Id(), err)
- }
- policy := ""
- if getPolicyVersionResponse != nil && getPolicyVersionResponse.PolicyVersion != nil {
- var err error
- policy, err = url.QueryUnescape(aws.StringValue(getPolicyVersionResponse.PolicyVersion.Document))
- if err != nil {
- return fmt.Errorf("error parsing policy: %s", err)
- }
- }
- d.Set("policy", policy)
- return nil
- }
- func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
- iamconn := meta.(*AWSClient).iamconn
- if err := iamPolicyPruneVersions(d.Id(), iamconn); err != nil {
- return err
- }
- request := &iam.CreatePolicyVersionInput{
- PolicyArn: aws.String(d.Id()),
- PolicyDocument: aws.String(d.Get("policy").(string)),
- SetAsDefault: aws.Bool(true),
- }
- if _, err := iamconn.CreatePolicyVersion(request); err != nil {
- return fmt.Errorf("Error updating IAM policy %s: %s", d.Id(), err)
- }
- return resourceAwsIamPolicyRead(d, meta)
- }
- func resourceAwsIamPolicyDelete(d *schema.ResourceData, meta interface{}) error {
- iamconn := meta.(*AWSClient).iamconn
- if err := iamPolicyDeleteNondefaultVersions(d.Id(), iamconn); err != nil {
- return err
- }
- request := &iam.DeletePolicyInput{
- PolicyArn: aws.String(d.Id()),
- }
- if _, err := iamconn.DeletePolicy(request); err != nil {
- if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
- return nil
- }
- return fmt.Errorf("Error deleting IAM policy %s: %s", d.Id(), err)
- }
- return nil
- }
- // iamPolicyPruneVersions deletes the oldest versions.
- //
- // Old versions are deleted until there are 4 or less remaining, which means at
- // least one more can be created before hitting the maximum of 5.
- //
- // The default version is never deleted.
- func iamPolicyPruneVersions(arn string, iamconn *iam.IAM) error {
- versions, err := iamPolicyListVersions(arn, iamconn)
- if err != nil {
- return err
- }
- if len(versions) < 5 {
- return nil
- }
- var oldestVersion *iam.PolicyVersion
- for _, version := range versions {
- if *version.IsDefaultVersion {
- continue
- }
- if oldestVersion == nil ||
- version.CreateDate.Before(*oldestVersion.CreateDate) {
- oldestVersion = version
- }
- }
- err1 := iamPolicyDeleteVersion(arn, *oldestVersion.VersionId, iamconn)
- return err1
- }
- func iamPolicyDeleteNondefaultVersions(arn string, iamconn *iam.IAM) error {
- versions, err := iamPolicyListVersions(arn, iamconn)
- if err != nil {
- return err
- }
- for _, version := range versions {
- if *version.IsDefaultVersion {
- continue
- }
- if err := iamPolicyDeleteVersion(arn, *version.VersionId, iamconn); err != nil {
- return err
- }
- }
- return nil
- }
- func iamPolicyDeleteVersion(arn, versionID string, iamconn *iam.IAM) error {
- request := &iam.DeletePolicyVersionInput{
- PolicyArn: aws.String(arn),
- VersionId: aws.String(versionID),
- }
- _, err := iamconn.DeletePolicyVersion(request)
- if err != nil {
- return fmt.Errorf("Error deleting version %s from IAM policy %s: %s", versionID, arn, err)
- }
- return nil
- }
- func iamPolicyListVersions(arn string, iamconn *iam.IAM) ([]*iam.PolicyVersion, error) {
- request := &iam.ListPolicyVersionsInput{
- PolicyArn: aws.String(arn),
- }
- response, err := iamconn.ListPolicyVersions(request)
- if err != nil {
- return nil, fmt.Errorf("Error listing versions for IAM policy %s: %s", arn, err)
- }
- return response.Versions, nil
- }