-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: IAM supports identity acl (#982)
- Loading branch information
1 parent
28be281
commit afe17fb
Showing
11 changed files
with
738 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
subcategory: "Identity and Access Management (IAM)" | ||
--- | ||
|
||
# huaweicloud\_identity\_acl | ||
|
||
Manages a ACL resource within HuaweiCloud IAM service. | ||
The ACL allowing user access only from specified IP address ranges and IPv4 CIDR blocks. | ||
The ACL take effect for IAM users under the Domain account rather than the account itself. | ||
|
||
Note: You _must_ have admin privileges in your HuaweiCloud cloud to use this resource. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "huaweicloud_identity_acl" "acl" { | ||
type = "console" | ||
ip_cidrs { | ||
cidr = "159.138.39.192/32" | ||
description = "This is a test ip address" | ||
} | ||
ip_ranges { | ||
range = "0.0.0.0-255.255.255.0" | ||
description = "This is a test ip range" | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `type` - (Required, String, ForceNew) Specifies the ACL is created through the Console or API. | ||
valid value are 'console' and 'api'. | ||
Changing this parameter will create a new ACL. | ||
|
||
* `ip_cidrs` - (Optional, List) Specifies the IPv4 CIDR blocks from which console access or api access is allowed. | ||
The `ip_cidrs` cannot repeat. The structure is documented below. | ||
|
||
* `ip_ranges` - (Optional, List) Specifies the IP address ranges from which console access or api access is allowed. | ||
The `ip_ranges` cannot repeat. The structure is documented below. | ||
|
||
The `ip_cidrs` block supports: | ||
|
||
* `cidr` - (Required, String) Specifies the IPv4 CIDR block, for example, __192.168.0.0/24__. | ||
|
||
* `description` - (Optional, String) Specifies a description about an IPv4 CIDR block. | ||
This parameter can contain a maximum of 255 characters and the following charactors are not allowed:__@#%^&*<>\\__. | ||
|
||
The `ip_ranges` block supports: | ||
|
||
* `range` - (Required, String) Specifies the Ip address range, for example, __0.0.0.0-255.255.255.0__. | ||
|
||
* `description` - (Optional, String) Specifies a description about an IP address range. | ||
This parameter can contain a maximum of 255 characters and the following charactors are not allowed:__@#%^&*<>\\__. | ||
|
||
**note**: Up to 200 `ip_cidrs` and `ip_ranges` can be created in total for each access method. | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `id` - The ID of identity acl. | ||
|
||
## Timeouts | ||
This resource provides the following timeouts configuration options: | ||
- `create` - Default is 5 minute. | ||
- `update` - Default is 5 minute. | ||
- `delete` - Default is 3 minute. |
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
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
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
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,246 @@ | ||
package huaweicloud | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/validation" | ||
"github.com/huaweicloud/golangsdk/openstack/identity/v3.0/acl" | ||
) | ||
|
||
func resourceIdentityACL() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceIdentityACLCreate, | ||
Read: resourceIdentityACLRead, | ||
Update: resourceIdentityACLUpdate, | ||
Delete: resourceIdentityACLDelete, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(5 * time.Minute), | ||
Update: schema.DefaultTimeout(5 * time.Minute), | ||
Delete: schema.DefaultTimeout(3 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
"console", "api", | ||
}, true), | ||
}, | ||
"ip_cidrs": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
MaxItems: 200, | ||
AtLeastOneOf: []string{"ip_ranges"}, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"cidr": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validateCIDR, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
}, | ||
}, | ||
Set: resourceACLPolicyCIDRHash, | ||
}, | ||
"ip_ranges": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
MaxItems: 200, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"range": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validateIPRange, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
}, | ||
}, | ||
Set: resourceACLPolicyRangeHash, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceIdentityACLCreate(d *schema.ResourceData, meta interface{}) error { | ||
id := meta.(*Config).DomainID | ||
if err := updateACLPolicy(d, meta, id); err != nil { | ||
return fmt.Errorf("Error creating HuaweiCloud iam acl: %s", err) | ||
} | ||
|
||
d.SetId(id) | ||
return resourceIdentityACLRead(d, meta) | ||
} | ||
|
||
func resourceIdentityACLRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
iamClient, err := config.IAMV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating HuaweiCloud iam client: %s", err) | ||
} | ||
|
||
var res *acl.ACLPolicy | ||
switch d.Get("type").(string) { | ||
case "console": | ||
res, err = acl.ConsoleACLPolicyGet(iamClient, d.Id()).ConsoleExtract() | ||
if err != nil { | ||
return fmt.Errorf("Error fetching identity acl for console access") | ||
} | ||
log.Printf("[DEBUG] Retrieved HuaweiCloud identity acl: %#v", res) | ||
default: | ||
res, err = acl.APIACLPolicyGet(iamClient, d.Id()).APIExtract() | ||
if err != nil { | ||
return fmt.Errorf("Error fetching identity acl for api access") | ||
} | ||
log.Printf("[DEBUG] Retrieved HuaweiCloud identity acl: %#v", res) | ||
} | ||
|
||
if len(res.AllowAddressNetmasks) > 0 { | ||
addressNetmasks := make([]map[string]string, 0, len(res.AllowAddressNetmasks)) | ||
for _, v := range res.AllowAddressNetmasks { | ||
addressNetmask := map[string]string{ | ||
"cidr": v.AddressNetmask, | ||
"description": v.Description, | ||
} | ||
addressNetmasks = append(addressNetmasks, addressNetmask) | ||
} | ||
d.Set("ip_cidrs", addressNetmasks) | ||
} | ||
if len(res.AllowIPRanges) > 0 { | ||
ipRanges := make([]map[string]string, 0, len(res.AllowIPRanges)) | ||
for _, v := range res.AllowIPRanges { | ||
ipRange := map[string]string{ | ||
"range": v.IPRange, | ||
"description": v.Description, | ||
} | ||
ipRanges = append(ipRanges, ipRange) | ||
} | ||
d.Set("ip_ranges", ipRanges) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceIdentityACLUpdate(d *schema.ResourceData, meta interface{}) error { | ||
id := d.Id() | ||
if d.HasChanges("ip_cidrs", "ip_ranges") { | ||
if err := updateACLPolicy(d, meta, id); err != nil { | ||
return fmt.Errorf("Error updating HuaweiCloud iam acl: %s", err) | ||
} | ||
} | ||
|
||
return resourceIdentityACLRead(d, meta) | ||
} | ||
|
||
func resourceIdentityACLDelete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
iamClient, err := config.IAMV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating HuaweiCloud iam client: %s", err) | ||
} | ||
|
||
netmasksList := make([]acl.AllowAddressNetmasks, 0, 1) | ||
netmask := acl.AllowAddressNetmasks{ | ||
AddressNetmask: "0.0.0.0-255.255.255.255", | ||
} | ||
netmasksList = append(netmasksList, netmask) | ||
|
||
deleteOpts := &acl.ACLPolicy{ | ||
AllowAddressNetmasks: netmasksList, | ||
} | ||
|
||
switch d.Get("type").(string) { | ||
case "console": | ||
_, err := acl.ConsoleACLPolicyUpdate(iamClient, deleteOpts, d.Id()).ConsoleExtract() | ||
if err != nil { | ||
return fmt.Errorf("Error updating HuaweiCloud iam acl: %s", err) | ||
} | ||
default: | ||
_, err := acl.APIACLPolicyUpdate(iamClient, deleteOpts, d.Id()).APIExtract() | ||
if err != nil { | ||
return fmt.Errorf("Error updating HuaweiCloud iam acl: %s", err) | ||
} | ||
} | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func updateACLPolicy(d *schema.ResourceData, meta interface{}, id string) error { | ||
config := meta.(*Config) | ||
iamClient, err := config.IAMV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating HuaweiCloud iam client: %s", err) | ||
} | ||
|
||
updateOpts := &acl.ACLPolicy{} | ||
if addressNetmasks, ok := d.GetOk("ip_cidrs"); ok { | ||
netmasksList := make([]acl.AllowAddressNetmasks, 0, addressNetmasks.(*schema.Set).Len()) | ||
for _, v := range addressNetmasks.(*schema.Set).List() { | ||
netmask := acl.AllowAddressNetmasks{ | ||
AddressNetmask: v.(map[string]interface{})["cidr"].(string), | ||
Description: v.(map[string]interface{})["description"].(string), | ||
} | ||
netmasksList = append(netmasksList, netmask) | ||
} | ||
updateOpts.AllowAddressNetmasks = netmasksList | ||
} | ||
if ipRanges, ok := d.GetOk("ip_ranges"); ok { | ||
rangeList := make([]acl.AllowIPRanges, 0, ipRanges.(*schema.Set).Len()) | ||
for _, v := range ipRanges.(*schema.Set).List() { | ||
ipRange := acl.AllowIPRanges{ | ||
IPRange: v.(map[string]interface{})["range"].(string), | ||
Description: v.(map[string]interface{})["description"].(string), | ||
} | ||
rangeList = append(rangeList, ipRange) | ||
} | ||
updateOpts.AllowIPRanges = rangeList | ||
} | ||
|
||
switch d.Get("type").(string) { | ||
case "console": | ||
_, err = acl.ConsoleACLPolicyUpdate(iamClient, updateOpts, id).ConsoleExtract() | ||
case "api": | ||
_, err = acl.APIACLPolicyUpdate(iamClient, updateOpts, id).APIExtract() | ||
} | ||
if err != nil { | ||
return fmt.Errorf("Modify identity acl failed: %s", err) | ||
} | ||
return nil | ||
} | ||
|
||
func resourceACLPolicyCIDRHash(v interface{}) int { | ||
var buf bytes.Buffer | ||
m := v.(map[string]interface{}) | ||
|
||
if m["cidr"] != nil { | ||
buf.WriteString(fmt.Sprintf("%s-", m["cidr"].(string))) | ||
} | ||
|
||
return hashcode.String(buf.String()) | ||
} | ||
|
||
func resourceACLPolicyRangeHash(v interface{}) int { | ||
var buf bytes.Buffer | ||
m := v.(map[string]interface{}) | ||
|
||
if m["range"] != nil { | ||
buf.WriteString(fmt.Sprintf("%s-", m["range"].(string))) | ||
} | ||
|
||
return hashcode.String(buf.String()) | ||
} |
Oops, something went wrong.