Merge pull request #5029 from TimeIncOSS/f-aws-iam-pass-policy

provider/aws: Add support for account password policy
This commit is contained in:
Radek Simko 2016-02-26 13:36:46 +00:00
commit d60f22809f
5 changed files with 326 additions and 0 deletions

View File

@ -154,6 +154,7 @@ func Provider() terraform.ResourceProvider {
"aws_flow_log": resourceAwsFlowLog(),
"aws_glacier_vault": resourceAwsGlacierVault(),
"aws_iam_access_key": resourceAwsIamAccessKey(),
"aws_iam_account_password_policy": resourceAwsIamAccountPasswordPolicy(),
"aws_iam_group_policy": resourceAwsIamGroupPolicy(),
"aws_iam_group": resourceAwsIamGroup(),
"aws_iam_group_membership": resourceAwsIamGroupMembership(),

View File

@ -0,0 +1,165 @@
package aws
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsIamAccountPasswordPolicy() *schema.Resource {
return &schema.Resource{
Create: resourceAwsIamAccountPasswordPolicyUpdate,
Read: resourceAwsIamAccountPasswordPolicyRead,
Update: resourceAwsIamAccountPasswordPolicyUpdate,
Delete: resourceAwsIamAccountPasswordPolicyDelete,
Schema: map[string]*schema.Schema{
"allow_users_to_change_password": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"expire_passwords": &schema.Schema{
Type: schema.TypeBool,
Computed: true,
},
"hard_expiry": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"max_password_age": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"minimum_password_length": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 6,
},
"password_reuse_prevention": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"require_lowercase_characters": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"require_numbers": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"require_symbols": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"require_uppercase_characters": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
},
}
}
func resourceAwsIamAccountPasswordPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
input := &iam.UpdateAccountPasswordPolicyInput{}
if v, ok := d.GetOk("allow_users_to_change_password"); ok {
input.AllowUsersToChangePassword = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("hard_expiry"); ok {
input.HardExpiry = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("max_password_age"); ok {
input.MaxPasswordAge = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("minimum_password_length"); ok {
input.MinimumPasswordLength = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("password_reuse_prevention"); ok {
input.PasswordReusePrevention = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("require_lowercase_characters"); ok {
input.RequireLowercaseCharacters = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("require_numbers"); ok {
input.RequireNumbers = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("require_symbols"); ok {
input.RequireSymbols = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("require_uppercase_characters"); ok {
input.RequireUppercaseCharacters = aws.Bool(v.(bool))
}
log.Printf("[DEBUG] Updating IAM account password policy: %s", input)
_, err := iamconn.UpdateAccountPasswordPolicy(input)
if err != nil {
return fmt.Errorf("Error updating IAM Password Policy: %s", err)
}
log.Println("[DEBUG] IAM account password policy updated")
d.SetId("iam-account-password-policy")
return resourceAwsIamAccountPasswordPolicyRead(d, meta)
}
func resourceAwsIamAccountPasswordPolicyRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
input := &iam.GetAccountPasswordPolicyInput{}
resp, err := iamconn.GetAccountPasswordPolicy(input)
if err != nil {
awsErr, ok := err.(awserr.Error)
if ok && awsErr.Code() == "NoSuchEntity" {
log.Printf("[WARN] IAM account password policy is gone (i.e. default)")
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IAM account password policy: %s", err)
}
log.Printf("[DEBUG] Received IAM account password policy: %s", resp)
policy := resp.PasswordPolicy
d.Set("allow_users_to_change_password", policy.AllowUsersToChangePassword)
d.Set("expire_passwords", policy.ExpirePasswords)
d.Set("hard_expiry", policy.HardExpiry)
d.Set("max_password_age", policy.MaxPasswordAge)
d.Set("minimum_password_length", policy.MinimumPasswordLength)
d.Set("password_reuse_prevention", policy.PasswordReusePrevention)
d.Set("require_lowercase_characters", policy.RequireLowercaseCharacters)
d.Set("require_numbers", policy.RequireNumbers)
d.Set("require_symbols", policy.RequireSymbols)
d.Set("require_uppercase_characters", policy.RequireUppercaseCharacters)
return nil
}
func resourceAwsIamAccountPasswordPolicyDelete(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
log.Println("[DEBUG] Deleting IAM account password policy")
input := &iam.DeleteAccountPasswordPolicyInput{}
if _, err := iamconn.DeleteAccountPasswordPolicy(input); err != nil {
return fmt.Errorf("Error deleting IAM Password Policy: %s", err)
}
d.SetId("")
log.Println("[DEBUG] Deleted IAM account password policy")
return nil
}

View File

@ -0,0 +1,105 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMAccountPasswordPolicy_basic(t *testing.T) {
var policy iam.GetAccountPasswordPolicyOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSIAMAccountPasswordPolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSIAMAccountPasswordPolicy,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSIAMAccountPasswordPolicyExists("aws_iam_account_password_policy.default", &policy),
resource.TestCheckResourceAttr("aws_iam_account_password_policy.default", "minimum_password_length", "8"),
),
},
resource.TestStep{
Config: testAccAWSIAMAccountPasswordPolicy_modified,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSIAMAccountPasswordPolicyExists("aws_iam_account_password_policy.default", &policy),
resource.TestCheckResourceAttr("aws_iam_account_password_policy.default", "minimum_password_length", "7"),
),
},
},
})
}
func testAccCheckAWSIAMAccountPasswordPolicyDestroy(s *terraform.State) error {
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_iam_account_password_policy" {
continue
}
// Try to get policy
_, err := iamconn.GetAccountPasswordPolicy(&iam.GetAccountPasswordPolicyInput{})
if err == nil {
return fmt.Errorf("still exist.")
}
// Verify the error is what we want
awsErr, ok := err.(awserr.Error)
if !ok {
return err
}
if awsErr.Code() != "NoSuchEntity" {
return err
}
}
return nil
}
func testAccCheckAWSIAMAccountPasswordPolicyExists(n string, res *iam.GetAccountPasswordPolicyOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No policy ID is set")
}
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
resp, err := iamconn.GetAccountPasswordPolicy(&iam.GetAccountPasswordPolicyInput{})
if err != nil {
return err
}
*res = *resp
return nil
}
}
const testAccAWSIAMAccountPasswordPolicy = `
resource "aws_iam_account_password_policy" "default" {
allow_users_to_change_password = true
minimum_password_length = 8
require_numbers = true
}
`
const testAccAWSIAMAccountPasswordPolicy_modified = `
resource "aws_iam_account_password_policy" "default" {
allow_users_to_change_password = true
minimum_password_length = 7
require_numbers = false
require_symbols = true
require_uppercase_characters = true
}
`

View File

@ -0,0 +1,51 @@
---
layout: "aws"
page_title: "AWS: aws_iam_account_password_policy"
sidebar_current: "docs-aws-resource-iam-account-password-policy"
description: |-
Manages Password Policy for the AWS Account.
---
# aws\_iam\_account_password_policy
-> **Note:** There is only a single policy allowed per AWS account. An existing policy will be lost when using this resource as an effect of this limitation.
Manages Password Policy for the AWS Account.
See more about [Account Password Policy](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html)
in the official AWS docs.
## Example Usage
```
resource "aws_iam_account_password_policy" "strict" {
minimum_password_length = 8
require_lowercase_characters = true
require_numbers = true
require_uppercase_characters = true
require_symbols = true
allow_users_to_change_password = true
}
```
## Argument Reference
The following arguments are supported:
* `allow_users_to_change_password` - (Optional) Whether to allow users to change their own password
* `hard_expiry` - (Optional) Whether users are prevented from setting a new password after their password has expired
(i.e. require administrator reset)
* `max_password_age` - (Optional) The number of days that an user password is valid.
* `minimum_password_length` - (Optional) Minimum length to require for user passwords.
* `password_reuse_prevention` - (Optional) The number of previous passwords that users are prevented from reusing.
* `require_lowercase_characters` - (Optional) Whether to require lowercase characters for user passwords.
* `require_numbers` - (Optional) Whether to require numbers for user passwords.
* `require_symbols` - (Optional) Whether to require symbols for user passwords.
* `require_uppercase_characters` - (Optional) Whether to require uppercase characters for user passwords.
## Attributes Reference
The following attributes are exported:
* `expire_passwords` - Indicates whether passwords in the account expire.
Returns `true` if `max_password_age` contains a value greater than `0`.
Returns `false` if it is `0` or _not present_.

View File

@ -283,6 +283,10 @@
<a href="/docs/providers/aws/r/iam_access_key.html">aws_iam_access_key</a>
</li>
<li<%= sidebar_current("docs-aws-resource-iam-account-password-policy") %>>
<a href="/docs/providers/aws/r/iam_account_password_policy.html">aws_iam_account_password_policy</a>
</li>
<li<%= sidebar_current("docs-aws-resource-iam-group") %>>
<a href="/docs/providers/aws/r/iam_group.html">aws_iam_group</a>
</li>