-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5029 from TimeIncOSS/f-aws-iam-pass-policy
provider/aws: Add support for account password policy
- Loading branch information
Showing
5 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
165 changes: 165 additions & 0 deletions
165
builtin/providers/aws/resource_aws_iam_account_password_policy.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
105 changes: 105 additions & 0 deletions
105
builtin/providers/aws/resource_aws_iam_account_password_policy_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
` |
51 changes: 51 additions & 0 deletions
51
website/source/docs/providers/aws/r/iam_account_password_policy.html.markdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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_. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters