Merge pull request #5029 from TimeIncOSS/f-aws-iam-pass-policy
provider/aws: Add support for account password policy
This commit is contained in:
commit
d60f22809f
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
`
|
|
@ -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_.
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue