alicloud/resource_alicloud_ram_role.go (312 lines of code) (raw):
package alicloud
import (
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ram"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func resourceAlicloudRamRole() *schema.Resource {
return &schema.Resource{
Create: resourceAlicloudRamRoleCreate,
Read: resourceAlicloudRamRoleRead,
Update: resourceAlicloudRamRoleUpdate,
Delete: resourceAlicloudRamRoleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Update: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ram_users": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Set: schema.HashString,
ConflictsWith: []string{"document"},
Deprecated: "Field 'ram_users' has been deprecated from version 1.49.0, and use field 'document' to replace. ",
},
"max_session_duration": {
Type: schema.TypeInt,
Optional: true,
Default: 3600,
ValidateFunc: IntBetween(3600, 43200),
},
"services": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Set: schema.HashString,
ConflictsWith: []string{"document"},
Deprecated: "Field 'services' has been deprecated from version 1.49.0, and use field 'document' to replace. ",
},
"document": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"ram_users", "services", "version"},
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
equal, _ := compareJsonTemplateAreEquivalent(old, new)
return equal
},
ValidateFunc: validation.ValidateJsonString,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"version": {
Type: schema.TypeString,
Optional: true,
Default: "1",
ConflictsWith: []string{"document"},
// can only be '1' so far.
ValidateFunc: StringInSlice([]string{"1"}, false),
Deprecated: "Field 'version' has been deprecated from version 1.49.0, and use field 'document' to replace. ",
},
"force": {
Type: schema.TypeBool,
Optional: true,
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"role_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceAlicloudRamRoleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
request, err := buildAlicloudRamRoleCreateArgs(d, meta)
if err != nil {
return WrapError(err)
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
raw, err := client.WithRamClient(func(ramClient *ram.Client) (interface{}, error) {
return ramClient.CreateRole(request)
})
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ram.CreateRoleResponse)
d.SetId(response.Role.RoleName)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, "alicloud_ram_role", request.GetActionName(), AlibabaCloudSdkGoERROR)
}
return resourceAlicloudRamRoleRead(d, meta)
}
func resourceAlicloudRamRoleUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ramService := RamService{client}
var response map[string]interface{}
var err error
update := false
request := map[string]interface{}{
"RoleName": d.Id(),
}
if d.HasChange("document") {
update = true
request["NewAssumeRolePolicyDocument"] = d.Get("document").(string)
} else if d.HasChange("ram_users") || d.HasChange("services") || d.HasChange("version") {
update = true
document, err := ramService.AssembleRolePolicyDocument(d.Get("ram_users").(*schema.Set).List(), d.Get("services").(*schema.Set).List(), d.Get("version").(string))
if err != nil {
return WrapError(err)
}
request["NewAssumeRolePolicyDocument"] = document
}
if d.HasChange("max_session_duration") {
update = true
request["NewMaxSessionDuration"] = d.Get("max_session_duration")
}
if d.HasChange("description") {
update = true
request["NewDescription"] = d.Get("description")
}
if update {
action := "UpdateRole"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err = client.RpcPost("Ram", "2015-05-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
}
return resourceAlicloudRamRoleRead(d, meta)
}
func resourceAlicloudRamRoleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ramService := RamService{client}
object, err := ramService.DescribeRamRole(d.Id())
if err != nil {
if NotFoundError(err) {
d.SetId("")
return nil
}
return WrapError(err)
}
role := object.Role
rolePolicy, err := ramService.ParseRolePolicyDocument(role.AssumeRolePolicyDocument)
if err != nil {
return WrapError(err)
}
if len(rolePolicy.Statement) > 0 {
principal := rolePolicy.Statement[0].Principal
d.Set("services", principal.Service)
d.Set("ram_users", principal.RAM)
}
d.Set("role_id", role.RoleId)
d.Set("name", role.RoleName)
d.Set("arn", role.Arn)
d.Set("description", role.Description)
d.Set("version", rolePolicy.Version)
d.Set("document", role.AssumeRolePolicyDocument)
d.Set("max_session_duration", role.MaxSessionDuration)
return nil
}
func resourceAlicloudRamRoleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ramService := RamService{client}
ListPoliciesForRoleRequest := ram.CreateListPoliciesForRoleRequest()
ListPoliciesForRoleRequest.RegionId = client.RegionId
ListPoliciesForRoleRequest.RoleName = d.Id()
if d.Get("force").(bool) {
var response *ram.ListPoliciesForRoleResponse
err := resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError {
raw, err := client.WithRamClient(func(ramClient *ram.Client) (interface{}, error) {
return ramClient.ListPoliciesForRole(ListPoliciesForRoleRequest)
})
if err != nil {
if NeedRetry(err) {
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(ListPoliciesForRoleRequest.GetActionName(), raw, ListPoliciesForRoleRequest.RpcRequest, ListPoliciesForRoleRequest)
response, _ = raw.(*ram.ListPoliciesForRoleResponse)
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"EntityNotExist.Role"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), ListPoliciesForRoleRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
// Loop and remove the Policies from the Role
if len(response.Policies.Policy) > 0 {
for _, v := range response.Policies.Policy {
request := ram.CreateDetachPolicyFromRoleRequest()
request.RegionId = client.RegionId
request.RoleName = d.Id()
request.PolicyName = v.PolicyName
request.PolicyType = v.PolicyType
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutDelete)), func() *resource.RetryError {
raw, err := client.WithRamClient(func(ramClient *ram.Client) (interface{}, error) {
return ramClient.DetachPolicyFromRole(request)
})
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return nil
})
if err != nil && !IsExpectedErrors(err, []string{"EntityNotExist"}) {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
}
}
}
deleteRoleRequest := ram.CreateDeleteRoleRequest()
deleteRoleRequest.RegionId = client.RegionId
deleteRoleRequest.RoleName = d.Id()
err := resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError {
raw, err := client.WithRamClient(func(ramClient *ram.Client) (interface{}, error) {
return ramClient.DeleteRole(deleteRoleRequest)
})
if err != nil {
if NeedRetry(err) || IsExpectedErrors(err, []string{"DeleteConflict.Role.Policy"}) {
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(deleteRoleRequest.GetActionName(), raw, deleteRoleRequest.RpcRequest, deleteRoleRequest)
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"EntityNotExist.Role"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), deleteRoleRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
return WrapError(ramService.WaitForRamRole(d.Id(), Deleted, DefaultTimeout))
}
func buildAlicloudRamRoleCreateArgs(d *schema.ResourceData, meta interface{}) (*ram.CreateRoleRequest, error) {
client := meta.(*connectivity.AliyunClient)
ramService := RamService{client}
request := ram.CreateCreateRoleRequest()
request.RegionId = client.RegionId
request.RoleName = d.Get("name").(string)
ramUsers, usersOk := d.GetOk("ram_users")
services, servicesOk := d.GetOk("services")
document, documentOk := d.GetOk("document")
if !usersOk && !servicesOk && !documentOk {
return &ram.CreateRoleRequest{}, WrapError(Error("At least one of 'ram_users', 'services' or 'document' must be set."))
}
if documentOk {
request.AssumeRolePolicyDocument = document.(string)
} else {
rolePolicyDocument, err := ramService.AssembleRolePolicyDocument(ramUsers.(*schema.Set).List(), services.(*schema.Set).List(), d.Get("version").(string))
if err != nil {
return &ram.CreateRoleRequest{}, WrapError(err)
}
request.AssumeRolePolicyDocument = rolePolicyDocument
}
if v, ok := d.GetOk("description"); ok && v.(string) != "" {
request.Description = v.(string)
}
if v, ok := d.GetOk("max_session_duration"); ok {
request.MaxSessionDuration = requests.NewInteger(v.(int))
}
return request, nil
}