github.com/i0n/terraform@v0.4.3-0.20150506151324-010a39a58ec1/builtin/providers/aws/resource_aws_iam_policy.go (about)

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