github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_iam_policy_attachment.go (about)

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