github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/resource_aws_iam_user.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  
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceAwsIamUser() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAwsIamUserCreate,
    17  		Read:   resourceAwsIamUserRead,
    18  		Update: resourceAwsIamUserUpdate,
    19  		Delete: resourceAwsIamUserDelete,
    20  		Importer: &schema.ResourceImporter{
    21  			State: schema.ImportStatePassthrough,
    22  		},
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"arn": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Computed: true,
    28  			},
    29  			/*
    30  				The UniqueID could be used as the Id(), but none of the API
    31  				calls allow specifying a user by the UniqueID: they require the
    32  				name. The only way to locate a user by UniqueID is to list them
    33  				all and that would make this provider unnecessarilly complex
    34  				and inefficient. Still, there are other reasons one might want
    35  				the UniqueID, so we can make it available.
    36  			*/
    37  			"unique_id": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Computed: true,
    40  			},
    41  			"name": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Required: true,
    44  			},
    45  			"path": &schema.Schema{
    46  				Type:     schema.TypeString,
    47  				Optional: true,
    48  				Default:  "/",
    49  				ForceNew: true,
    50  			},
    51  			"force_destroy": &schema.Schema{
    52  				Type:        schema.TypeBool,
    53  				Optional:    true,
    54  				Default:     false,
    55  				Description: "Delete user even if it has non-Terraform-managed IAM access keys",
    56  			},
    57  		},
    58  	}
    59  }
    60  
    61  func resourceAwsIamUserCreate(d *schema.ResourceData, meta interface{}) error {
    62  	iamconn := meta.(*AWSClient).iamconn
    63  	name := d.Get("name").(string)
    64  	path := d.Get("path").(string)
    65  
    66  	request := &iam.CreateUserInput{
    67  		Path:     aws.String(path),
    68  		UserName: aws.String(name),
    69  	}
    70  
    71  	log.Println("[DEBUG] Create IAM User request:", request)
    72  	createResp, err := iamconn.CreateUser(request)
    73  	if err != nil {
    74  		return fmt.Errorf("Error creating IAM User %s: %s", name, err)
    75  	}
    76  	d.SetId(*createResp.User.UserName)
    77  	return resourceAwsIamUserReadResult(d, createResp.User)
    78  }
    79  
    80  func resourceAwsIamUserRead(d *schema.ResourceData, meta interface{}) error {
    81  	iamconn := meta.(*AWSClient).iamconn
    82  
    83  	request := &iam.GetUserInput{
    84  		UserName: aws.String(d.Id()),
    85  	}
    86  
    87  	getResp, err := iamconn.GetUser(request)
    88  	if err != nil {
    89  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
    90  			log.Printf("[WARN] No IAM user by name (%s) found", d.Id())
    91  			d.SetId("")
    92  			return nil
    93  		}
    94  		return fmt.Errorf("Error reading IAM User %s: %s", d.Id(), err)
    95  	}
    96  	return resourceAwsIamUserReadResult(d, getResp.User)
    97  }
    98  
    99  func resourceAwsIamUserReadResult(d *schema.ResourceData, user *iam.User) error {
   100  	if err := d.Set("name", user.UserName); err != nil {
   101  		return err
   102  	}
   103  	if err := d.Set("arn", user.Arn); err != nil {
   104  		return err
   105  	}
   106  	if err := d.Set("path", user.Path); err != nil {
   107  		return err
   108  	}
   109  	if err := d.Set("unique_id", user.UserId); err != nil {
   110  		return err
   111  	}
   112  	return nil
   113  }
   114  
   115  func resourceAwsIamUserUpdate(d *schema.ResourceData, meta interface{}) error {
   116  	if d.HasChange("name") || d.HasChange("path") {
   117  		iamconn := meta.(*AWSClient).iamconn
   118  		on, nn := d.GetChange("name")
   119  		_, np := d.GetChange("path")
   120  
   121  		request := &iam.UpdateUserInput{
   122  			UserName:    aws.String(on.(string)),
   123  			NewUserName: aws.String(nn.(string)),
   124  			NewPath:     aws.String(np.(string)),
   125  		}
   126  
   127  		log.Println("[DEBUG] Update IAM User request:", request)
   128  		_, err := iamconn.UpdateUser(request)
   129  		if err != nil {
   130  			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
   131  				log.Printf("[WARN] No IAM user by name (%s) found", d.Id())
   132  				d.SetId("")
   133  				return nil
   134  			}
   135  			return fmt.Errorf("Error updating IAM User %s: %s", d.Id(), err)
   136  		}
   137  		return resourceAwsIamUserRead(d, meta)
   138  	}
   139  	return nil
   140  }
   141  
   142  func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error {
   143  	iamconn := meta.(*AWSClient).iamconn
   144  
   145  	// IAM Users must be removed from all groups before they can be deleted
   146  	var groups []string
   147  	listGroups := &iam.ListGroupsForUserInput{
   148  		UserName: aws.String(d.Id()),
   149  	}
   150  	pageOfGroups := func(page *iam.ListGroupsForUserOutput, lastPage bool) (shouldContinue bool) {
   151  		for _, g := range page.Groups {
   152  			groups = append(groups, *g.GroupName)
   153  		}
   154  		return !lastPage
   155  	}
   156  	err := iamconn.ListGroupsForUserPages(listGroups, pageOfGroups)
   157  	if err != nil {
   158  		return fmt.Errorf("Error removing user %q from all groups: %s", d.Id(), err)
   159  	}
   160  	for _, g := range groups {
   161  		// use iam group membership func to remove user from all groups
   162  		log.Printf("[DEBUG] Removing IAM User %s from IAM Group %s", d.Id(), g)
   163  		if err := removeUsersFromGroup(iamconn, []*string{aws.String(d.Id())}, g); err != nil {
   164  			return err
   165  		}
   166  	}
   167  
   168  	// All access keys for the user must be removed
   169  	if d.Get("force_destroy").(bool) {
   170  		var accessKeys []string
   171  		listAccessKeys := &iam.ListAccessKeysInput{
   172  			UserName: aws.String(d.Id()),
   173  		}
   174  		pageOfAccessKeys := func(page *iam.ListAccessKeysOutput, lastPage bool) (shouldContinue bool) {
   175  			for _, k := range page.AccessKeyMetadata {
   176  				accessKeys = append(accessKeys, *k.AccessKeyId)
   177  			}
   178  			return !lastPage
   179  		}
   180  		err = iamconn.ListAccessKeysPages(listAccessKeys, pageOfAccessKeys)
   181  		if err != nil {
   182  			return fmt.Errorf("Error removing access keys of user %s: %s", d.Id(), err)
   183  		}
   184  		for _, k := range accessKeys {
   185  			_, err := iamconn.DeleteAccessKey(&iam.DeleteAccessKeyInput{
   186  				UserName:    aws.String(d.Id()),
   187  				AccessKeyId: aws.String(k),
   188  			})
   189  			if err != nil {
   190  				return fmt.Errorf("Error deleting access key %s: %s", k, err)
   191  			}
   192  		}
   193  	}
   194  
   195  	request := &iam.DeleteUserInput{
   196  		UserName: aws.String(d.Id()),
   197  	}
   198  
   199  	log.Println("[DEBUG] Delete IAM User request:", request)
   200  	if _, err := iamconn.DeleteUser(request); err != nil {
   201  		return fmt.Errorf("Error deleting IAM User %s: %s", d.Id(), err)
   202  	}
   203  	return nil
   204  }