github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_iam_policy.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/aws/aws-sdk-go/aws"
     7  	"github.com/aws/aws-sdk-go/aws/awserr"
     8  	"github.com/aws/aws-sdk-go/service/iam"
     9  
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func resourceAwsIamPolicy() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceAwsIamPolicyCreate,
    16  		Read:   resourceAwsIamPolicyRead,
    17  		Update: resourceAwsIamPolicyUpdate,
    18  		Delete: resourceAwsIamPolicyDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"description": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				ForceNew: true,
    24  				Optional: true,
    25  			},
    26  			"path": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Optional: true,
    29  				Default:  "/",
    30  				ForceNew: true,
    31  			},
    32  			"policy": &schema.Schema{
    33  				Type:     schema.TypeString,
    34  				Required: true,
    35  			},
    36  			"name": &schema.Schema{
    37  				Type:     schema.TypeString,
    38  				Required: true,
    39  				ForceNew: true,
    40  			},
    41  			"arn": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Computed: true,
    44  			},
    45  		},
    46  	}
    47  }
    48  
    49  func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error {
    50  	iamconn := meta.(*AWSClient).iamconn
    51  	name := d.Get("name").(string)
    52  
    53  	request := &iam.CreatePolicyInput{
    54  		Description:    aws.String(d.Get("description").(string)),
    55  		Path:           aws.String(d.Get("path").(string)),
    56  		PolicyDocument: aws.String(d.Get("policy").(string)),
    57  		PolicyName:     aws.String(name),
    58  	}
    59  
    60  	response, err := iamconn.CreatePolicy(request)
    61  	if err != nil {
    62  		return fmt.Errorf("Error creating IAM policy %s: %s", name, err)
    63  	}
    64  
    65  	return readIamPolicy(d, response.Policy)
    66  }
    67  
    68  func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
    69  	iamconn := meta.(*AWSClient).iamconn
    70  
    71  	request := &iam.GetPolicyInput{
    72  		PolicyArn: aws.String(d.Id()),
    73  	}
    74  
    75  	response, err := iamconn.GetPolicy(request)
    76  	if err != nil {
    77  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
    78  			d.SetId("")
    79  			return nil
    80  		}
    81  		return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err)
    82  	}
    83  
    84  	return readIamPolicy(d, response.Policy)
    85  }
    86  
    87  func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
    88  	iamconn := meta.(*AWSClient).iamconn
    89  
    90  	if err := iamPolicyPruneVersions(d.Id(), iamconn); err != nil {
    91  		return err
    92  	}
    93  
    94  	if !d.HasChange("policy") {
    95  		return nil
    96  	}
    97  	request := &iam.CreatePolicyVersionInput{
    98  		PolicyArn:      aws.String(d.Id()),
    99  		PolicyDocument: aws.String(d.Get("policy").(string)),
   100  		SetAsDefault:   aws.Bool(true),
   101  	}
   102  
   103  	if _, err := iamconn.CreatePolicyVersion(request); err != nil {
   104  		return fmt.Errorf("Error updating IAM policy %s: %s", d.Id(), err)
   105  	}
   106  	return nil
   107  }
   108  
   109  func resourceAwsIamPolicyDelete(d *schema.ResourceData, meta interface{}) error {
   110  	iamconn := meta.(*AWSClient).iamconn
   111  
   112  	if err := iamPolicyDeleteNondefaultVersions(d.Id(), iamconn); err != nil {
   113  		return err
   114  	}
   115  
   116  	request := &iam.DeletePolicyInput{
   117  		PolicyArn: aws.String(d.Id()),
   118  	}
   119  
   120  	_, err := iamconn.DeletePolicy(request)
   121  	if err != nil {
   122  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
   123  			return nil
   124  		}
   125  		return fmt.Errorf("Error reading IAM policy %s: %#v", d.Id(), err)
   126  	}
   127  	return nil
   128  }
   129  
   130  // iamPolicyPruneVersions deletes the oldest versions.
   131  //
   132  // Old versions are deleted until there are 4 or less remaining, which means at
   133  // least one more can be created before hitting the maximum of 5.
   134  //
   135  // The default version is never deleted.
   136  
   137  func iamPolicyPruneVersions(arn string, iamconn *iam.IAM) error {
   138  	versions, err := iamPolicyListVersions(arn, iamconn)
   139  	if err != nil {
   140  		return err
   141  	}
   142  	if len(versions) < 5 {
   143  		return nil
   144  	}
   145  
   146  	var oldestVersion *iam.PolicyVersion
   147  
   148  	for _, version := range versions {
   149  		if *version.IsDefaultVersion {
   150  			continue
   151  		}
   152  		if oldestVersion == nil ||
   153  			version.CreateDate.Before(*oldestVersion.CreateDate) {
   154  			oldestVersion = version
   155  		}
   156  	}
   157  
   158  	if err := iamPolicyDeleteVersion(arn, *oldestVersion.VersionId, iamconn); err != nil {
   159  		return err
   160  	}
   161  	return nil
   162  }
   163  
   164  func iamPolicyDeleteNondefaultVersions(arn string, iamconn *iam.IAM) error {
   165  	versions, err := iamPolicyListVersions(arn, iamconn)
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	for _, version := range versions {
   171  		if *version.IsDefaultVersion {
   172  			continue
   173  		}
   174  		if err := iamPolicyDeleteVersion(arn, *version.VersionId, iamconn); err != nil {
   175  			return err
   176  		}
   177  	}
   178  
   179  	return nil
   180  }
   181  
   182  func iamPolicyDeleteVersion(arn, versionID string, iamconn *iam.IAM) error {
   183  	request := &iam.DeletePolicyVersionInput{
   184  		PolicyArn: aws.String(arn),
   185  		VersionId: aws.String(versionID),
   186  	}
   187  
   188  	_, err := iamconn.DeletePolicyVersion(request)
   189  	if err != nil {
   190  		return fmt.Errorf("Error deleting version %s from IAM policy %s: %s", versionID, arn, err)
   191  	}
   192  	return nil
   193  }
   194  
   195  func iamPolicyListVersions(arn string, iamconn *iam.IAM) ([]*iam.PolicyVersion, error) {
   196  	request := &iam.ListPolicyVersionsInput{
   197  		PolicyArn: aws.String(arn),
   198  	}
   199  
   200  	response, err := iamconn.ListPolicyVersions(request)
   201  	if err != nil {
   202  		return nil, fmt.Errorf("Error listing versions for IAM policy %s: %s", arn, err)
   203  	}
   204  	return response.Versions, nil
   205  }
   206  
   207  func readIamPolicy(d *schema.ResourceData, policy *iam.Policy) error {
   208  	d.SetId(*policy.Arn)
   209  	if policy.Description != nil {
   210  		// the description isn't present in the response to CreatePolicy.
   211  		if err := d.Set("description", *policy.Description); err != nil {
   212  			return err
   213  		}
   214  	}
   215  	if err := d.Set("path", *policy.Path); err != nil {
   216  		return err
   217  	}
   218  	if err := d.Set("name", *policy.PolicyName); err != nil {
   219  		return err
   220  	}
   221  	if err := d.Set("arn", *policy.Arn); err != nil {
   222  		return err
   223  	}
   224  	// TODO: set policy
   225  
   226  	return nil
   227  }