func (b *backend) secretAccessKeysCreate( s logical.Storage, displayName, policyName string, policy string) (*logical.Response, error) { client, err := clientIAM(s) if err != nil { return logical.ErrorResponse(err.Error()), nil } // Generate a random username. We don't put the policy names in the // username because the AWS console makes it pretty easy to see that. username := fmt.Sprintf("vault-%s-%d-%d", displayName, time.Now().Unix(), rand.Int31n(10000)) // Write to the WAL that this user will be created. We do this before // the user is created because if switch the order then the WAL put // can fail, which would put us in an awkward position: we have a user // we need to rollback but can't put the WAL entry to do the rollback. walId, err := framework.PutWAL(s, "user", &walUser{ UserName: username, }) if err != nil { return nil, fmt.Errorf("Error writing WAL entry: %s", err) } // Create the user _, err = client.CreateUser(&iam.CreateUserRequest{ UserName: aws.String(username), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error creating IAM user: %s", err)), nil } // Add the user to all the groups err = client.PutUserPolicy(&iam.PutUserPolicyRequest{ UserName: aws.String(username), PolicyName: aws.String(policyName), PolicyDocument: aws.String(policy), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error adding user to group: %s", err)), nil } // Create the keys keyResp, err := client.CreateAccessKey(&iam.CreateAccessKeyRequest{ UserName: aws.String(username), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error creating access keys: %s", err)), nil } // Remove the WAL entry, we succeeded! If we fail, we don't return // the secret because it'll get rolled back anyways, so we have to return // an error here. if err := framework.DeleteWAL(s, walId); err != nil { return nil, fmt.Errorf("Failed to commit WAL entry: %s", err) } // Return the info! return b.Secret(SecretAccessKeyType).Response(map[string]interface{}{ "access_key": *keyResp.AccessKey.AccessKeyID, "secret_key": *keyResp.AccessKey.SecretAccessKey, }, map[string]interface{}{ "username": username, "policy": policy, }), nil }
func (b *backend) secretAccessKeysCreate( s logical.Storage, displayName, policyName string, policy string) (*logical.Response, error) { client, err := clientIAM(s) if err != nil { return logical.ErrorResponse(err.Error()), nil } username, usernameWarning := genUsername(displayName, policyName, "iam_user") // Write to the WAL that this user will be created. We do this before // the user is created because if switch the order then the WAL put // can fail, which would put us in an awkward position: we have a user // we need to rollback but can't put the WAL entry to do the rollback. walId, err := framework.PutWAL(s, "user", &walUser{ UserName: username, }) if err != nil { return nil, fmt.Errorf("Error writing WAL entry: %s", err) } // Create the user _, err = client.CreateUser(&iam.CreateUserInput{ UserName: aws.String(username), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error creating IAM user: %s", err)), nil } if strings.HasPrefix(policy, "arn:") { // Attach existing policy against user _, err = client.AttachUserPolicy(&iam.AttachUserPolicyInput{ UserName: aws.String(username), PolicyArn: aws.String(policy), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error attaching user policy: %s", err)), nil } } else { // Add new inline user policy against user _, err = client.PutUserPolicy(&iam.PutUserPolicyInput{ UserName: aws.String(username), PolicyName: aws.String(policyName), PolicyDocument: aws.String(policy), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error putting user policy: %s", err)), nil } } // Create the keys keyResp, err := client.CreateAccessKey(&iam.CreateAccessKeyInput{ UserName: aws.String(username), }) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error creating access keys: %s", err)), nil } // Remove the WAL entry, we succeeded! If we fail, we don't return // the secret because it'll get rolled back anyways, so we have to return // an error here. if err := framework.DeleteWAL(s, walId); err != nil { return nil, fmt.Errorf("Failed to commit WAL entry: %s", err) } // Return the info! resp := b.Secret(SecretAccessKeyType).Response(map[string]interface{}{ "access_key": *keyResp.AccessKey.AccessKeyId, "secret_key": *keyResp.AccessKey.SecretAccessKey, "security_token": nil, }, map[string]interface{}{ "username": username, "policy": policy, "is_sts": false, }) lease, err := b.Lease(s) if err != nil || lease == nil { lease = &configLease{} } resp.Secret.TTL = lease.Lease if usernameWarning != "" { resp.AddWarning(usernameWarning) } return resp, nil }