github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/builtin/providers/aws/resource_aws_iam_policy_attachment.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  	"github.com/hashicorp/terraform/helper/schema"
    10  )
    11  
    12  func resourceAwsIamPolicyAttachment() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceAwsIamPolicyAttachmentCreate,
    15  		Read:   resourceAwsIamPolicyAttachmentRead,
    16  		Update: resourceAwsIamPolicyAttachmentUpdate,
    17  		Delete: resourceAwsIamPolicyAttachmentDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"name": &schema.Schema{
    21  				Type:     schema.TypeString,
    22  				Required: true,
    23  				ForceNew: true,
    24  			},
    25  			"users": &schema.Schema{
    26  				Type:     schema.TypeSet,
    27  				Optional: true,
    28  				Elem:     &schema.Schema{Type: schema.TypeString},
    29  				Set:      schema.HashString,
    30  			},
    31  			"roles": &schema.Schema{
    32  				Type:     schema.TypeSet,
    33  				Optional: true,
    34  				Elem:     &schema.Schema{Type: schema.TypeString},
    35  				Set:      schema.HashString,
    36  			},
    37  			"groups": &schema.Schema{
    38  				Type:     schema.TypeSet,
    39  				Optional: true,
    40  				Elem:     &schema.Schema{Type: schema.TypeString},
    41  				Set:      schema.HashString,
    42  			},
    43  			"policy_arn": &schema.Schema{
    44  				Type:     schema.TypeString,
    45  				Required: true,
    46  				ForceNew: true,
    47  			},
    48  		},
    49  	}
    50  }
    51  
    52  func resourceAwsIamPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
    53  	conn := meta.(*AWSClient).iamconn
    54  
    55  	name := d.Get("name").(string)
    56  	arn := d.Get("policy_arn").(string)
    57  	users := expandStringList(d.Get("users").(*schema.Set).List())
    58  	roles := expandStringList(d.Get("roles").(*schema.Set).List())
    59  	groups := expandStringList(d.Get("groups").(*schema.Set).List())
    60  
    61  	if len(users) == 0 && len(roles) == 0 && len(groups) == 0 {
    62  		return fmt.Errorf("[WARN] No Users, Roles, or Groups specified for IAM Policy Attachment %s", name)
    63  	} else {
    64  		var userErr, roleErr, groupErr error
    65  		if users != nil {
    66  			userErr = attachPolicyToUsers(conn, users, arn)
    67  		}
    68  		if roles != nil {
    69  			roleErr = attachPolicyToRoles(conn, roles, arn)
    70  		}
    71  		if groups != nil {
    72  			groupErr = attachPolicyToGroups(conn, groups, arn)
    73  		}
    74  		if userErr != nil || roleErr != nil || groupErr != nil {
    75  			return composeErrors(fmt.Sprint("[WARN] Error attaching policy with IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
    76  		}
    77  	}
    78  	d.SetId(d.Get("name").(string))
    79  	return resourceAwsIamPolicyAttachmentRead(d, meta)
    80  }
    81  
    82  func resourceAwsIamPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error {
    83  	conn := meta.(*AWSClient).iamconn
    84  	arn := d.Get("policy_arn").(string)
    85  	name := d.Get("name").(string)
    86  
    87  	_, err := conn.GetPolicy(&iam.GetPolicyInput{
    88  		PolicyArn: aws.String(arn),
    89  	})
    90  
    91  	if err != nil {
    92  		if awsErr, ok := err.(awserr.Error); ok {
    93  			if awsErr.Code() == "NoSuchIdentity" {
    94  				d.SetId("")
    95  				return nil
    96  			}
    97  		}
    98  		return err
    99  	}
   100  
   101  	policyEntities, err := conn.ListEntitiesForPolicy(&iam.ListEntitiesForPolicyInput{
   102  		PolicyArn: aws.String(arn),
   103  	})
   104  
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	ul := make([]string, 0, len(policyEntities.PolicyUsers))
   110  	rl := make([]string, 0, len(policyEntities.PolicyRoles))
   111  	gl := make([]string, 0, len(policyEntities.PolicyGroups))
   112  
   113  	for _, u := range policyEntities.PolicyUsers {
   114  		ul = append(ul, *u.UserName)
   115  	}
   116  
   117  	for _, r := range policyEntities.PolicyRoles {
   118  		rl = append(rl, *r.RoleName)
   119  	}
   120  
   121  	for _, g := range policyEntities.PolicyGroups {
   122  		gl = append(gl, *g.GroupName)
   123  	}
   124  
   125  	userErr := d.Set("users", ul)
   126  	roleErr := d.Set("roles", rl)
   127  	groupErr := d.Set("groups", gl)
   128  
   129  	if userErr != nil || roleErr != nil || groupErr != nil {
   130  		return composeErrors(fmt.Sprint("[WARN} Error setting user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
   131  	}
   132  
   133  	return nil
   134  }
   135  func resourceAwsIamPolicyAttachmentUpdate(d *schema.ResourceData, meta interface{}) error {
   136  	conn := meta.(*AWSClient).iamconn
   137  	name := d.Get("name").(string)
   138  	var userErr, roleErr, groupErr error
   139  
   140  	if d.HasChange("users") {
   141  		userErr = updateUsers(conn, d, meta)
   142  	}
   143  	if d.HasChange("roles") {
   144  		roleErr = updateRoles(conn, d, meta)
   145  	}
   146  	if d.HasChange("groups") {
   147  		groupErr = updateGroups(conn, d, meta)
   148  	}
   149  	if userErr != nil || roleErr != nil || groupErr != nil {
   150  		return composeErrors(fmt.Sprint("[WARN] Error updating user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
   151  	}
   152  	return resourceAwsIamPolicyAttachmentRead(d, meta)
   153  }
   154  
   155  func resourceAwsIamPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
   156  	conn := meta.(*AWSClient).iamconn
   157  	name := d.Get("name").(string)
   158  	arn := d.Get("policy_arn").(string)
   159  	users := expandStringList(d.Get("users").(*schema.Set).List())
   160  	roles := expandStringList(d.Get("roles").(*schema.Set).List())
   161  	groups := expandStringList(d.Get("groups").(*schema.Set).List())
   162  
   163  	var userErr, roleErr, groupErr error
   164  	if len(users) != 0 {
   165  		userErr = detachPolicyFromUsers(conn, users, arn)
   166  	}
   167  	if len(roles) != 0 {
   168  		roleErr = detachPolicyFromRoles(conn, roles, arn)
   169  	}
   170  	if len(groups) != 0 {
   171  		groupErr = detachPolicyFromGroups(conn, groups, arn)
   172  	}
   173  	if userErr != nil || roleErr != nil || groupErr != nil {
   174  		return composeErrors(fmt.Sprint("[WARN] Error removing user, role, or group list from IAM Policy Detach ", name, ":"), userErr, roleErr, groupErr)
   175  	}
   176  	return nil
   177  }
   178  
   179  func composeErrors(desc string, uErr error, rErr error, gErr error) error {
   180  	errMsg := fmt.Sprintf(desc)
   181  	errs := []error{uErr, rErr, gErr}
   182  	for _, e := range errs {
   183  		if e != nil {
   184  			errMsg = errMsg + "\n– " + e.Error()
   185  		}
   186  	}
   187  	return fmt.Errorf(errMsg)
   188  }
   189  
   190  func attachPolicyToUsers(conn *iam.IAM, users []*string, arn string) error {
   191  	for _, u := range users {
   192  		_, err := conn.AttachUserPolicy(&iam.AttachUserPolicyInput{
   193  			UserName:  u,
   194  			PolicyArn: aws.String(arn),
   195  		})
   196  		if err != nil {
   197  			return err
   198  		}
   199  	}
   200  	return nil
   201  }
   202  func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
   203  	for _, r := range roles {
   204  		_, err := conn.AttachRolePolicy(&iam.AttachRolePolicyInput{
   205  			RoleName:  r,
   206  			PolicyArn: aws.String(arn),
   207  		})
   208  		if err != nil {
   209  			return err
   210  		}
   211  	}
   212  	return nil
   213  }
   214  func attachPolicyToGroups(conn *iam.IAM, groups []*string, arn string) error {
   215  	for _, g := range groups {
   216  		_, err := conn.AttachGroupPolicy(&iam.AttachGroupPolicyInput{
   217  			GroupName: g,
   218  			PolicyArn: aws.String(arn),
   219  		})
   220  		if err != nil {
   221  			return err
   222  		}
   223  	}
   224  	return nil
   225  }
   226  func updateUsers(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
   227  	arn := d.Get("policy_arn").(string)
   228  	o, n := d.GetChange("users")
   229  	if o == nil {
   230  		o = new(schema.Set)
   231  	}
   232  	if n == nil {
   233  		n = new(schema.Set)
   234  	}
   235  	os := o.(*schema.Set)
   236  	ns := n.(*schema.Set)
   237  	remove := expandStringList(os.Difference(ns).List())
   238  	add := expandStringList(ns.Difference(os).List())
   239  
   240  	if rErr := detachPolicyFromUsers(conn, remove, arn); rErr != nil {
   241  		return rErr
   242  	}
   243  	if aErr := attachPolicyToUsers(conn, add, arn); aErr != nil {
   244  		return aErr
   245  	}
   246  	return nil
   247  }
   248  func updateRoles(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
   249  	arn := d.Get("policy_arn").(string)
   250  	o, n := d.GetChange("roles")
   251  	if o == nil {
   252  		o = new(schema.Set)
   253  	}
   254  	if n == nil {
   255  		n = new(schema.Set)
   256  	}
   257  	os := o.(*schema.Set)
   258  	ns := n.(*schema.Set)
   259  	remove := expandStringList(os.Difference(ns).List())
   260  	add := expandStringList(ns.Difference(os).List())
   261  
   262  	if rErr := detachPolicyFromRoles(conn, remove, arn); rErr != nil {
   263  		return rErr
   264  	}
   265  	if aErr := attachPolicyToRoles(conn, add, arn); aErr != nil {
   266  		return aErr
   267  	}
   268  	return nil
   269  }
   270  func updateGroups(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
   271  	arn := d.Get("policy_arn").(string)
   272  	o, n := d.GetChange("groups")
   273  	if o == nil {
   274  		o = new(schema.Set)
   275  	}
   276  	if n == nil {
   277  		n = new(schema.Set)
   278  	}
   279  	os := o.(*schema.Set)
   280  	ns := n.(*schema.Set)
   281  	remove := expandStringList(os.Difference(ns).List())
   282  	add := expandStringList(ns.Difference(os).List())
   283  
   284  	if rErr := detachPolicyFromGroups(conn, remove, arn); rErr != nil {
   285  		return rErr
   286  	}
   287  	if aErr := attachPolicyToGroups(conn, add, arn); aErr != nil {
   288  		return aErr
   289  	}
   290  	return nil
   291  
   292  }
   293  func detachPolicyFromUsers(conn *iam.IAM, users []*string, arn string) error {
   294  	for _, u := range users {
   295  		_, err := conn.DetachUserPolicy(&iam.DetachUserPolicyInput{
   296  			UserName:  u,
   297  			PolicyArn: aws.String(arn),
   298  		})
   299  		if err != nil {
   300  			return err
   301  		}
   302  	}
   303  	return nil
   304  }
   305  func detachPolicyFromRoles(conn *iam.IAM, roles []*string, arn string) error {
   306  	for _, r := range roles {
   307  		_, err := conn.DetachRolePolicy(&iam.DetachRolePolicyInput{
   308  			RoleName:  r,
   309  			PolicyArn: aws.String(arn),
   310  		})
   311  		if err != nil {
   312  			return err
   313  		}
   314  	}
   315  	return nil
   316  }
   317  func detachPolicyFromGroups(conn *iam.IAM, groups []*string, arn string) error {
   318  	for _, g := range groups {
   319  		_, err := conn.DetachGroupPolicy(&iam.DetachGroupPolicyInput{
   320  			GroupName: g,
   321  			PolicyArn: aws.String(arn),
   322  		})
   323  		if err != nil {
   324  			return err
   325  		}
   326  	}
   327  	return nil
   328  }