Skip to content

Commit

Permalink
[Feat.] Update resource `opentelekomcloud_identity_protection_policy_…
Browse files Browse the repository at this point in the history
…v3` (#2752)

[Feat.] Update resource `opentelekomcloud_identity_protection_policy_v3`

Update resource with new options opentelekomcloud_identity_protection_policy_v3
Summary of the Pull Request
PR Checklist

 Refers to: #2747
 Tests added/passed.
 Documentation updated.
 Schema updated.
 Release notes added.

Acceptance Steps Performed
=== RUN   TestAccIdentityV3Protection_basic
--- PASS: TestAccIdentityV3Protection_basic (57.12s)
PASS

Process finished with exit code 0

Reviewed-by: Muneeb H. Jan <[email protected]>
Reviewed-by: Artem Lifshits
  • Loading branch information
anton-sidelnikov authored Nov 29, 2024
1 parent 43185f9 commit 100cba0
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 70 deletions.
42 changes: 41 additions & 1 deletion docs/resources/identity_protection_policy_v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,26 @@ cloud to use this resource. Please refer to [User Management Model](https://docs

## Example Usage

### Self-Verification

```hcl
resource "opentelekomcloud_identity_protection_policy_v3" "policy_1" {
enable_operation_protection_policy = false
enable_operation_protection_policy = true
self_management {
access_key = true
password = true
email = false
mobile = false
}
}
```

### Verification by another person

```hcl
resource "opentelekomcloud_identity_protection_policy_v3" "policy_2" {
enable_operation_protection_policy = true
verification_email = "[email protected]"
}
```

Expand All @@ -37,12 +54,35 @@ The following arguments are supported:
* `enable_operation_protection_policy` - (Optional, Bool) Indicates whether operation protection has been enabled.
The value can be `true` or `false`. Default: `false`

* `verification_email` - (Optional, String) Specifies the email address used for verification. An example value is `[email protected]`.

* `verification_mobile` - (Optional, String) Specifies the mobile number used for verification.

-> If `protection_enabled` is set to true and neither `verification_email` nor `verification_mobile` is specified, IAM users
perform verification by themselves when performing a critical operation.

* `self_management` - (Optional, List) Specifies the attributes IAM users can modify.
The [object](#self_management_policy) structure is documented below.

<a name="self_management_policy"></a>
The `self_management` block supports:

* `access_key` - (Optional, Bool) Specifies whether to allow IAM users to manage access keys by themselves.

* `password` - (Optional, Bool) Specifies whether to allow IAM users to change their passwords.

* `email` - (Optional, Bool) Specifies whether to allow IAM users to change their email addresses.

* `mobile` - (Optional, Bool) Specifies whether to allow IAM users to change their mobile numbers.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The ID of account protection policy, which is the same as the domain ID.

* `self_verification` - Indicates whether the IAM users perform verification by themselves.

## Import

Identity operation protection policy can be imported using the account ID or domain ID, e.g.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
github.com/mitchellh/go-homedir v1.1.0
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241125090636-639d0490ef08
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241128102934-12bde9d9ad22
github.com/unknwon/com v1.0.1
golang.org/x/crypto v0.23.0
golang.org/x/sync v0.1.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241125090636-639d0490ef08 h1:wG3Uy3CD7vTtjJmqTl4zgqzwK5RzkgIrFcNBj4W3bRg=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241125090636-639d0490ef08/go.mod h1:M1F6OfSRZRzAmAFKQqSLClX952at5hx5rHe4UTEykgg=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241128102934-12bde9d9ad22 h1:9TjDvrDqLTS9V5VUuFwi6qx/hp5IaYl+IK9sZuwIf74=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241128102934-12bde9d9ad22/go.mod h1:M1F6OfSRZRzAmAFKQqSLClX952at5hx5rHe4UTEykgg=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,49 @@ import (

const resourceProtectionPolicyName = "opentelekomcloud_identity_protection_policy_v3.pol_1"

func getIAMProtectionFunc(conf *cfg.Config, state *terraform.ResourceState) (interface{}, error) {
c, err := conf.IdentityV30Client()
if err != nil {
return nil, fmt.Errorf("error creating OpenTelekomCloud APIG v2 client: %s", err)
}

return security.GetOperationProtectionPolicy(c, state.Primary.ID)
}

func TestAccIdentityV3Protection_basic(t *testing.T) {
var policy security.ProtectionPolicy
rc := common.InitResourceCheck(
resourceProtectionPolicyName,
&policy,
getIAMProtectionFunc,
)
resource.Test(t, resource.TestCase{
PreCheck: func() {
common.TestAccPreCheck(t)
common.TestAccPreCheckAdminOnly(t)
},
ProviderFactories: common.TestAccProviderFactories,
CheckDestroy: testAccCheckIdentityV3ProtectionPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccIdentityV3ProtectionPolicyBasic,
Check: resource.ComposeTestCheckFunc(
testAccCheckIdentityV3ProtectionPolicyExists(resourceProtectionPolicyName),
rc.CheckResourceExists(),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "enable_operation_protection_policy", "true"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.access_key", "false"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.password", "false"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.email", "false"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.mobile", "false"),
),
},
{
Config: testAccIdentityV3ProtectionPolicyUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckIdentityV3ProtectionPolicyExists(resourceProtectionPolicyName),
rc.CheckResourceExists(),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "enable_operation_protection_policy", "false"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.access_key", "true"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.password", "true"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.email", "true"),
resource.TestCheckResourceAttr(resourceProtectionPolicyName, "self_management.0.mobile", "true"),
),
},
{
Expand All @@ -45,57 +67,26 @@ func TestAccIdentityV3Protection_basic(t *testing.T) {
})
}

func testAccCheckIdentityV3ProtectionPolicyDestroy(s *terraform.State) error {
config := common.TestAccProvider.Meta().(*cfg.Config)
client, err := config.IdentityV30Client()
if err != nil {
return fmt.Errorf("error creating OpenTelekomcloud IdentityV3 client: %w", err)
}

for _, rs := range s.RootModule().Resources {
if rs.Type != "opentelekomcloud_identity_protection_policy_v3" {
continue
}

_, err := security.GetOperationProtectionPolicy(client, rs.Primary.ID)
if err != nil {
return fmt.Errorf("error fetching the IAM protection policy")
}
}

return nil
}

func testAccCheckIdentityV3ProtectionPolicyExists(n string) 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 ID is set")
}

config := common.TestAccProvider.Meta().(*cfg.Config)
client, err := config.IdentityV30Client()
if err != nil {
return fmt.Errorf("error creating OpenTelekomcloud IdentityV3 client: %w", err)
}

_, err = security.GetOperationProtectionPolicy(client, rs.Primary.ID)
return err
}
}

const testAccIdentityV3ProtectionPolicyBasic = `
resource "opentelekomcloud_identity_protection_policy_v3" "pol_1" {
enable_operation_protection_policy = true
self_management {
access_key = false
password = false
email = false
mobile = false
}
}
`

const testAccIdentityV3ProtectionPolicyUpdate = `
resource "opentelekomcloud_identity_protection_policy_v3" "pol_1" {
enable_operation_protection_policy = false
self_management {
access_key = true
password = true
email = true
mobile = true
}
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func ResourceIdentityProtectionPolicyV3() *schema.Resource {
return &schema.Resource{
CreateContext: resourceIdentityProtectionPolicyV3Create,
ReadContext: resourceIdentityProtectionPolicyV3Read,
UpdateContext: resourceIdentityProtectionPolicyV3Update,
UpdateContext: resourceIdentityProtectionPolicyV3Create,
DeleteContext: resourceIdentityProtectionPolicyV3Delete,

Importer: &schema.ResourceImporter{
Expand All @@ -32,6 +32,44 @@ func ResourceIdentityProtectionPolicyV3() *schema.Resource {
Optional: true,
Default: false,
},
"verification_mobile": {
Type: schema.TypeString,
Optional: true,
},
"verification_email": {
Type: schema.TypeString,
Optional: true,
},
"self_management": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"access_key": {
Type: schema.TypeBool,
Optional: true,
},
"password": {
Type: schema.TypeBool,
Optional: true,
},
"mobile": {
Type: schema.TypeBool,
Optional: true,
},
"email": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
"self_verification": {
Type: schema.TypeBool,
Computed: true,
},
},
}
}
Expand All @@ -53,13 +91,36 @@ func resourceIdentityProtectionPolicyV3Create(ctx context.Context, d *schema.Res
enable := d.Get("enable_operation_protection_policy").(bool)
opPolicyOpts := security.UpdateProtectionPolicyOpts{
OperationProtection: pointerto.Bool(enable),
AllowUser: buildSelfManagement(d),
}

// verification_mobile and verification_mobile are valid when the protection is enabled
if enable {
var adminCheck string
if v, ok := d.GetOk("verification_mobile"); ok {
adminCheck = "on"
opPolicyOpts.Scene = "mobile"
opPolicyOpts.Mobile = v.(string)
} else if v, ok := d.GetOk("verification_email"); ok {
adminCheck = "on"
opPolicyOpts.Scene = "email"
opPolicyOpts.Email = v.(string)
} else {
// self verification
adminCheck = "off"
}
opPolicyOpts.AdminCheck = adminCheck
}

_, err = security.UpdateOperationProtectionPolicy(client, domainID, opPolicyOpts)
if err != nil {
return diag.Errorf("error updating the IAM operation protection policy: %s", err)
}

d.SetId(domainID)
// set the ID only when creating
if d.IsNewResource() {
d.SetId(domainID)
}

clientCtx := common.CtxWithClient(ctx, client, keyClientV3)
return resourceIdentityProtectionPolicyV3Read(clientCtx, d, meta)
Expand All @@ -83,6 +144,10 @@ func resourceIdentityProtectionPolicyV3Read(ctx context.Context, d *schema.Resou

mErr := multierror.Append(nil,
d.Set("enable_operation_protection_policy", opPolicy.OperationProtection),
d.Set("verification_email", opPolicy.Email),
d.Set("verification_mobile", opPolicy.Mobile),
d.Set("self_verification", opPolicy.AdminCheck != "on"),
d.Set("self_management", flattenSelfManagement(opPolicy.AllowUser)),
)

if err = mErr.ErrorOrNil(); err != nil {
Expand All @@ -91,27 +156,15 @@ func resourceIdentityProtectionPolicyV3Read(ctx context.Context, d *schema.Resou
return nil
}

func resourceIdentityProtectionPolicyV3Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
config := meta.(*cfg.Config)
client, err := common.ClientFromCtx(ctx, keyClientV3, func() (*golangsdk.ServiceClient, error) {
return config.IdentityV30Client()
})
if err != nil {
return fmterr.Errorf(clientCreationFail, err)
}

if d.HasChange("enable_operation_protection_policy") {
passPolicyOpts := security.UpdateProtectionPolicyOpts{
OperationProtection: pointerto.Bool(d.Get("enable_operation_protection_policy").(bool)),
}
_, err = security.UpdateOperationProtectionPolicy(client, d.Id(), passPolicyOpts)
if err != nil {
return diag.Errorf("error updating the IAM operation protection policy: %s", err)
}
func flattenSelfManagement(resp *security.AllowUser) []map[string]interface{} {
return []map[string]interface{}{
{
"access_key": resp.ManageAccessKey,
"password": resp.ManagePassword,
"mobile": resp.ManageMobile,
"email": resp.ManageEmail,
},
}

clientCtx := common.CtxWithClient(ctx, client, keyClientV3)
return resourceIdentityProtectionPolicyV3Read(clientCtx, d, meta)
}

func resourceIdentityProtectionPolicyV3Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
Expand All @@ -132,3 +185,32 @@ func resourceIdentityProtectionPolicyV3Delete(ctx context.Context, d *schema.Res

return nil
}

func buildSelfManagement(d *schema.ResourceData) *security.AllowUser {
raw := d.Get("self_management").([]interface{})
if len(raw) == 0 {
// if not specified, keep the previous settings.
return nil
}

item, ok := raw[0].(map[string]interface{})
if !ok {
return nil
}

allowed := security.AllowUser{}
if v, ok := item["access_key"]; ok {
allowed.ManageAccessKey = pointerto.Bool(v.(bool))
}
if v, ok := item["password"]; ok {
allowed.ManagePassword = pointerto.Bool(v.(bool))
}
if v, ok := item["mobile"]; ok {
allowed.ManageMobile = pointerto.Bool(v.(bool))
}
if v, ok := item["email"]; ok {
allowed.ManageEmail = pointerto.Bool(v.(bool))
}

return &allowed
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
enhancements:
- |
**[IAM]** Add ``self_management`` and other verification arguments to ``resource/opentelekomcloud_identity_protection_policy_v3`` (`#2752 <https://github.com/opentelekomcloud/terraform-provider-opentelekomcloud/pull/2752>`_)

0 comments on commit 100cba0

Please sign in to comment.