Skip to content

Commit

Permalink
Bugfix on st-alicloud_ram_policy attaching long length policy. (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
styumyum authored Nov 16, 2023
1 parent aa1acd8 commit 3f0a492
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 35 deletions.
105 changes: 72 additions & 33 deletions alicloud/resource_ram_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ func (r *ramPolicyResource) Metadata(_ context.Context, req resource.MetadataReq

func (r *ramPolicyResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Provides a RAM Policy resource that manages policy content exceeding character limits by splitting it into smaller segments. These segments are combined to form a complete policy attached to the user.",
Description: "Provides a RAM Policy resource that manages policy content " +
"exceeding character limits by splitting it into smaller segments. " +
"These segments are combined to form a complete policy attached to " +
"the user. However, the policy` that exceed the maximum length of a " +
"policy, they will be attached directly to the user.",
Attributes: map[string]schema.Attribute{
"attached_policies": schema.ListAttribute{
Description: "The RAM policies to attach to the user.",
Expand Down Expand Up @@ -362,15 +366,15 @@ func (r *ramPolicyResource) ImportState(ctx context.Context, req resource.Import
}

func (r *ramPolicyResource) createPolicy(plan *ramPolicyResourceModel) (policiesList []attr.Value, err error) {
formattedPolicy, err := r.getPolicyDocument(plan)
combinedPolicyStatements, notCombinedPolicies, err := r.getPolicyDocument(plan)
if err != nil {
return nil, err
}

createPolicy := func() error {
runtime := &util.RuntimeOptions{}

for i, policy := range formattedPolicy {
for i, policy := range combinedPolicyStatements {
policyName := plan.UserName.ValueString() + "-" + strconv.Itoa(i+1)

createPolicyRequest := &alicloudRamClient.CreatePolicyRequest{
Expand All @@ -386,7 +390,7 @@ func (r *ramPolicyResource) createPolicy(plan *ramPolicyResourceModel) (policies
return nil
}

for i, policies := range formattedPolicy {
for i, policies := range combinedPolicyStatements {
policyName := plan.UserName.ValueString() + "-" + strconv.Itoa(i+1)

policyObj := types.ObjectValueMust(
Expand All @@ -402,6 +406,23 @@ func (r *ramPolicyResource) createPolicy(plan *ramPolicyResourceModel) (policies
policiesList = append(policiesList, policyObj)
}

// These policies will be attached directly to the user since splitting the
// policy "statement" will be hitting the limitation of "maximum number of
// attached policies" easily.
for _, policy := range notCombinedPolicies {
policyObj := types.ObjectValueMust(
map[string]attr.Type{
"policy_name": types.StringType,
"policy_document": types.StringType,
},
map[string]attr.Value{
"policy_name": types.StringValue(policy.policyName),
"policy_document": types.StringValue(policy.policyDocument),
},
)
policiesList = append(policiesList, policyObj)
}

reconnectBackoff := backoff.NewExponentialBackOff()
reconnectBackoff.MaxElapsedTime = 30 * time.Second
return policiesList, backoff.Retry(createPolicy, reconnectBackoff)
Expand Down Expand Up @@ -527,12 +548,16 @@ func (r *ramPolicyResource) removePolicy(state *ramPolicyResourceModel) diag.Dia
return nil
}

func (r *ramPolicyResource) getPolicyDocument(plan *ramPolicyResourceModel) (finalPolicyDocument []string, err error) {
type simplePolicy struct {
policyName string
policyDocument string
}

func (r *ramPolicyResource) getPolicyDocument(plan *ramPolicyResourceModel) (finalPolicyDocument []string, excludedPolicy []simplePolicy, err error) {
policyName := ""
currentLength := 0
currentPolicyDocument := ""
appendedPolicyDocument := make([]string, 0)
finalPolicyDocument = make([]string, 0)

var getPolicyResponse *alicloudRamClient.GetPolicyResponse

Expand Down Expand Up @@ -576,38 +601,52 @@ func (r *ramPolicyResource) getPolicyDocument(plan *ramPolicyResourceModel) (fin
if getPolicyResponse.Body.DefaultPolicyVersion.PolicyDocument != nil {
tempPolicyDocument := *getPolicyResponse.Body.DefaultPolicyVersion.PolicyDocument

var data map[string]interface{}
if err := json.Unmarshal([]byte(tempPolicyDocument), &data); err != nil {
return nil, err
skipCombinePolicy := false
// If the policy itself have more than 6144 characters, then skip the combine
// policy part since splitting the policy "statement" will be hitting the
// limitation of "maximum number of attached policies" easily.
if len(tempPolicyDocument) > maxLength {
excludedPolicy = append(excludedPolicy, simplePolicy{
policyName: policyName,
policyDocument: tempPolicyDocument,
})
skipCombinePolicy = true
}

statementArr := data["Statement"].([]interface{})
statementBytes, err := json.MarshalIndent(statementArr, "", " ")
if err != nil {
return nil, err
}
if !skipCombinePolicy {
var data map[string]interface{}
if err := json.Unmarshal([]byte(tempPolicyDocument), &data); err != nil {
return nil, nil, err
}

removeSpaces := strings.ReplaceAll(string(statementBytes), " ", "")
replacer := strings.NewReplacer("\n", "")
removeParagraphs := replacer.Replace(removeSpaces)
statementArr := data["Statement"].([]interface{})
statementBytes, err := json.MarshalIndent(statementArr, "", " ")
if err != nil {
return nil, nil, err
}

finalStatement := strings.Trim(removeParagraphs, "[]")
removeSpaces := strings.ReplaceAll(string(statementBytes), " ", "")
replacer := strings.NewReplacer("\n", "")
removeParagraphs := replacer.Replace(removeSpaces)

currentLength += len(finalStatement)
finalStatement := strings.Trim(removeParagraphs, "[]")

// Before further proceeding the current policy, we need to add a number of 30 to simulate the total length of completed policy to check whether it is already execeeded the max character length of 6144.
// Number of 30 indicates the character length of neccessary policy keyword such as "Version" and "Statement" and some JSON symbols ({}, [])
if (currentLength + 30) > maxLength {
lastCommaIndex := strings.LastIndex(currentPolicyDocument, ",")
if lastCommaIndex >= 0 {
currentPolicyDocument = currentPolicyDocument[:lastCommaIndex] + currentPolicyDocument[lastCommaIndex+1:]
}
currentLength += len(finalStatement)

appendedPolicyDocument = append(appendedPolicyDocument, currentPolicyDocument)
currentPolicyDocument = finalStatement + ","
currentLength = len(finalStatement)
} else {
currentPolicyDocument += finalStatement + ","
// Before further proceeding the current policy, we need to add a number of 30 to simulate the total length of completed policy to check whether it is already execeeded the max character length of 6144.
// Number of 30 indicates the character length of neccessary policy keyword such as "Version" and "Statement" and some JSON symbols ({}, [])
if (currentLength + 30) > maxLength {
lastCommaIndex := strings.LastIndex(currentPolicyDocument, ",")
if lastCommaIndex >= 0 {
currentPolicyDocument = currentPolicyDocument[:lastCommaIndex] + currentPolicyDocument[lastCommaIndex+1:]
}

appendedPolicyDocument = append(appendedPolicyDocument, currentPolicyDocument)
currentPolicyDocument = finalStatement + ","
currentLength = len(finalStatement)
} else {
currentPolicyDocument += finalStatement + ","
}
}

if i == len(plan.AttachedPolicies.Elements())-1 && (currentLength+30) <= maxLength {
Expand All @@ -619,7 +658,7 @@ func (r *ramPolicyResource) getPolicyDocument(plan *ramPolicyResourceModel) (fin
}
}
} else {
return nil, fmt.Errorf("could not find the policy: %v", policyName)
return nil, nil, fmt.Errorf("could not find the policy: %v", policyName)
}
}

Expand All @@ -629,7 +668,7 @@ func (r *ramPolicyResource) getPolicyDocument(plan *ramPolicyResourceModel) (fin
}
}

return finalPolicyDocument, nil
return finalPolicyDocument, excludedPolicy, nil
}

func (r *ramPolicyResource) attachPolicyToUser(state *ramPolicyResourceModel) (err error) {
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/ram_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
page_title: "st-alicloud_ram_policy Resource - st-alicloud"
subcategory: ""
description: |-
Provides a RAM Policy resource that manages policy content exceeding character limits by splitting it into smaller segments. These segments are combined to form a complete policy attached to the user.
Provides a RAM Policy resource that manages policy content exceeding character limits by splitting it into smaller segments. These segments are combined to form a complete policy attached to the user. However, the policy that exceed the maximum length of a policy, they will be attached directly to the user.
---

# st-alicloud_ram_policy (Resource)

Provides a RAM Policy resource that manages policy content exceeding character limits by splitting it into smaller segments. These segments are combined to form a complete policy attached to the user.
Provides a RAM Policy resource that manages policy content exceeding character limits by splitting it into smaller segments. These segments are combined to form a complete policy attached to the user. However, the policy that exceed the maximum length of a policy, they will be attached directly to the user.

## Example Usage

Expand Down

0 comments on commit 3f0a492

Please sign in to comment.