github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/aws/resource_aws_iam_user_login_profile.go (about) 1 package aws 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 "math/rand" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/iam" 13 "github.com/hashicorp/errwrap" 14 "github.com/hashicorp/terraform/helper/encryption" 15 "github.com/hashicorp/terraform/helper/schema" 16 ) 17 18 func resourceAwsIamUserLoginProfile() *schema.Resource { 19 return &schema.Resource{ 20 Create: resourceAwsIamUserLoginProfileCreate, 21 Read: schema.Noop, 22 Update: schema.Noop, 23 Delete: schema.RemoveFromState, 24 25 Schema: map[string]*schema.Schema{ 26 "user": { 27 Type: schema.TypeString, 28 Required: true, 29 }, 30 "pgp_key": { 31 Type: schema.TypeString, 32 Required: true, 33 }, 34 "password_reset_required": { 35 Type: schema.TypeBool, 36 Optional: true, 37 Default: true, 38 }, 39 "password_length": { 40 Type: schema.TypeInt, 41 Optional: true, 42 Default: 20, 43 ValidateFunc: validateAwsIamLoginProfilePasswordLength, 44 }, 45 46 "key_fingerprint": { 47 Type: schema.TypeString, 48 Computed: true, 49 }, 50 "encrypted_password": { 51 Type: schema.TypeString, 52 Computed: true, 53 }, 54 }, 55 } 56 } 57 58 func validateAwsIamLoginProfilePasswordLength(v interface{}, _ string) (_ []string, es []error) { 59 length := v.(int) 60 if length < 4 { 61 es = append(es, errors.New("minimum password_length is 4 characters")) 62 } 63 if length > 128 { 64 es = append(es, errors.New("maximum password_length is 128 characters")) 65 } 66 return 67 } 68 69 // generatePassword generates a random password of a given length using 70 // characters that are likely to satisfy any possible AWS password policy 71 // (given sufficient length). 72 func generatePassword(length int) string { 73 charsets := []string{ 74 "abcdefghijklmnopqrstuvwxyz", 75 "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 76 "012346789", 77 "!@#$%^&*()_+-=[]{}|'", 78 } 79 80 // Use all character sets 81 random := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) 82 components := make(map[int]byte, length) 83 for i := 0; i < length; i++ { 84 charset := charsets[i%len(charsets)] 85 components[i] = charset[random.Intn(len(charset))] 86 } 87 88 // Randomise the ordering so we don't end up with a predictable 89 // lower case, upper case, numeric, symbol pattern 90 result := make([]byte, length) 91 i := 0 92 for _, b := range components { 93 result[i] = b 94 i = i + 1 95 } 96 97 return string(result) 98 } 99 100 func resourceAwsIamUserLoginProfileCreate(d *schema.ResourceData, meta interface{}) error { 101 iamconn := meta.(*AWSClient).iamconn 102 103 encryptionKey, err := encryption.RetrieveGPGKey(d.Get("pgp_key").(string)) 104 if err != nil { 105 return err 106 } 107 108 username := d.Get("user").(string) 109 passwordResetRequired := d.Get("password_reset_required").(bool) 110 passwordLength := d.Get("password_length").(int) 111 112 _, err = iamconn.GetLoginProfile(&iam.GetLoginProfileInput{ 113 UserName: aws.String(username), 114 }) 115 if err != nil { 116 if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "NoSuchEntity" { 117 // If there is already a login profile, bring it under management (to prevent 118 // resource creation diffs) - we will never modify it, but obviously cannot 119 // set the password. 120 d.SetId(username) 121 d.Set("key_fingerprint", "") 122 d.Set("encrypted_password", "") 123 return nil 124 } 125 } 126 127 initialPassword := generatePassword(passwordLength) 128 fingerprint, encrypted, err := encryption.EncryptValue(encryptionKey, initialPassword, "Password") 129 if err != nil { 130 return err 131 } 132 133 request := &iam.CreateLoginProfileInput{ 134 UserName: aws.String(username), 135 Password: aws.String(initialPassword), 136 PasswordResetRequired: aws.Bool(passwordResetRequired), 137 } 138 139 log.Println("[DEBUG] Create IAM User Login Profile request:", request) 140 createResp, err := iamconn.CreateLoginProfile(request) 141 if err != nil { 142 if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "EntityAlreadyExists" { 143 // If there is already a login profile, bring it under management (to prevent 144 // resource creation diffs) - we will never modify it, but obviously cannot 145 // set the password. 146 d.SetId(username) 147 d.Set("key_fingerprint", "") 148 d.Set("encrypted_password", "") 149 return nil 150 } 151 return errwrap.Wrapf(fmt.Sprintf("Error creating IAM User Login Profile for %q: {{err}}", username), err) 152 } 153 154 d.SetId(*createResp.LoginProfile.UserName) 155 d.Set("key_fingerprint", fingerprint) 156 d.Set("encrypted_password", encrypted) 157 return nil 158 }