Skip to content

Commit

Permalink
Merge pull request #621 from pvasant/seamlessrosaupgrade
Browse files Browse the repository at this point in the history
Add support for seamless upgrade from any rosa version
  • Loading branch information
openshift-merge-robot committed Mar 3, 2022
2 parents 16edbee + 2257a83 commit 7b3efee
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 21 deletions.
72 changes: 56 additions & 16 deletions cmd/upgrade/accountroles/cmd.go
Expand Up @@ -218,7 +218,7 @@ func run(cmd *cobra.Command, argv []string) error {
reporter.Infof("Run the following commands to upgrade the account role policies:\n")
}
commands := buildCommands(prefix, creator.AccountID, isUpgradeNeedForAccountRolePolicies,
isUpgradeNeedForOperatorRolePolicies)
isUpgradeNeedForOperatorRolePolicies, awsClient)
fmt.Println(commands)
if args.isInvokedFromClusterUpgrade {
reporter.Infof("Run the following command to continue scheduling cluster upgrade"+
Expand All @@ -236,8 +236,8 @@ func run(cmd *cobra.Command, argv []string) error {

func upgradeAccountRolePolicies(reporter *rprtr.Object, awsClient aws.Client, prefix string, accountID string) error {
for file, role := range aws.AccountRoles {
name := aws.GetRoleName(prefix, role.Name)
if !confirm.Prompt(true, "Upgrade the '%s' role policy to version %s?", name,
roleName := aws.GetRoleName(prefix, role.Name)
if !confirm.Prompt(true, "Upgrade the '%s' role policy to version %s?", roleName,
aws.DefaultPolicyVersion) {
if args.isInvokedFromClusterUpgrade {
return reporter.Errorf("Account roles need to be upgraded to proceed" +
Expand All @@ -247,7 +247,7 @@ func upgradeAccountRolePolicies(reporter *rprtr.Object, awsClient aws.Client, pr
}
filename := fmt.Sprintf("sts_%s_permission_policy.json", file)
path := fmt.Sprintf("templates/policies/%s", filename)
policyARN := aws.GetPolicyARN(accountID, fmt.Sprintf("%s-Policy", name))
policyARN := aws.GetPolicyARN(accountID, fmt.Sprintf("%s-Policy", roleName))

policy, err := aws.ReadPolicyDocument(path)
if err != nil {
Expand All @@ -262,8 +262,18 @@ func upgradeAccountRolePolicies(reporter *rprtr.Object, awsClient aws.Client, pr
if err != nil {
return err
}

err = awsClient.AttachRolePolicy(roleName, policyARN)
if err != nil {
return err
}
//Delete if present else continue
err = awsClient.DeleteInlineRolePolicies(roleName)
if err != nil {
reporter.Debugf("Error deleting inline role policy %s : %s", policyARN, err)
}
reporter.Infof("Upgraded policy with ARN '%s' to version '%s'", policyARN, aws.DefaultPolicyVersion)
err = awsClient.UpdateTag(name)
err = awsClient.UpdateTag(roleName)
if err != nil {
return err
}
Expand Down Expand Up @@ -304,7 +314,7 @@ func upgradeOperatorRolePolicies(reporter *rprtr.Object, awsClient aws.Client, a
}

func buildCommands(prefix string, accountID string, isUpgradeNeedForAccountRolePolicies bool,
isUpgradeNeedForOperatorRolePolicies bool) string {
isUpgradeNeedForOperatorRolePolicies bool, awsClient aws.Client) string {
commands := []string{}
if isUpgradeNeedForAccountRolePolicies {
for file, role := range aws.AccountRoles {
Expand All @@ -314,23 +324,53 @@ func buildCommands(prefix string, accountID string, isUpgradeNeedForAccountRoleP
"Key=%s,Value=%s",
tags.OpenShiftVersion, aws.DefaultPolicyVersion,
)
createPolicyVersion := fmt.Sprintf("aws iam create-policy-version \\\n"+
"\t--policy-arn %s \\\n"+
"\t--policy-document file://sts_%s_permission_policy.json \\\n"+
"\t--set-as-default",
policyARN, file)
tagPolicies := fmt.Sprintf("aws iam tag-policy \\\n"+
"\t--tags %s \\\n"+
"\t--policy-arn %s",
policyTags, policyARN)
iamRoleTags := fmt.Sprintf(
"Key=%s,Value=%s",
tags.OpenShiftVersion, aws.DefaultPolicyVersion)
tagRole := fmt.Sprintf("aws iam tag-role \\\n"+
"\t--tags %s \\\n"+
"\t--role-name %s",
iamRoleTags, name)
commands = append(commands, createPolicyVersion, tagPolicies, tagRole)
//check if the policy exists if not output create and attach
_, err := awsClient.IsPolicyExists(policyARN)
if err != nil {
policyName := fmt.Sprintf("%s-Policy", name)
iamTags := fmt.Sprintf(
"Key=%s,Value=%s Key=%s,Value=%s Key=%s,Value=%s",
tags.OpenShiftVersion, aws.DefaultPolicyVersion,
tags.RolePrefix, prefix,
tags.RoleType, file,
)
createPolicy := fmt.Sprintf("aws iam create-policy \\\n"+
"\t--policy-name %s \\\n"+
"\t--policy-document file://sts_%s_permission_policy.json"+
"\t--tags %s",
policyName, file, iamTags)
attachRolePolicy := fmt.Sprintf("aws iam attach-role-policy \\\n"+
"\t--role-name %s \\\n"+
"\t--policy-arn %s",
name, aws.GetPolicyARN(accountID, policyName))

_, _ = awsClient.IsRolePolicyExists(name, policyName)
if err != nil {
commands = append(commands, createPolicy, attachRolePolicy, tagRole)
} else {
deletePolicy := fmt.Sprintf("\taws iam delete-role-policy --role-name %s --policy-name %s",
name, policyName)
commands = append(commands, createPolicy, attachRolePolicy, tagRole, deletePolicy)
}
} else {
createPolicyVersion := fmt.Sprintf("aws iam create-policy-version \\\n"+
"\t--policy-arn %s \\\n"+
"\t--policy-document file://sts_%s_permission_policy.json \\\n"+
"\t--set-as-default",
policyARN, file)
tagPolicies := fmt.Sprintf("aws iam tag-policy \\\n"+
"\t--tags %s \\\n"+
"\t--policy-arn %s",
policyTags, policyARN)
commands = append(commands, createPolicyVersion, tagPolicies, tagRole)
}
}
}
if isUpgradeNeedForOperatorRolePolicies {
Expand Down
2 changes: 2 additions & 0 deletions pkg/aws/client.go
Expand Up @@ -130,7 +130,9 @@ type Client interface {
IsPolicyCompatible(policyArn string, version string) (bool, error)
GetAccountRoleVersion(roleName string) (string, error)
IsPolicyExists(policyARN string) (*iam.GetPolicyOutput, error)
IsRolePolicyExists(roleName string, policyName string) (*iam.GetRolePolicyOutput, error)
IsAdminRole(roleName string) (bool, error)
DeleteInlineRolePolicies(roleName string) error
IsUserRole(roleName *string) (bool, error)
}

Expand Down
24 changes: 19 additions & 5 deletions pkg/aws/policies.go
Expand Up @@ -433,6 +433,14 @@ func (c *awsClient) IsPolicyExists(policyArn string) (*iam.GetPolicyOutput, erro
return output, err
}

func (c *awsClient) IsRolePolicyExists(roleName string, policyName string) (*iam.GetRolePolicyOutput, error) {
output, err := c.iamClient.GetRolePolicy(&iam.GetRolePolicyInput{
PolicyName: aws.String(policyName),
RoleName: aws.String(roleName),
})
return output, err
}

func (c *awsClient) createPolicy(policyArn string, document string, tagList map[string]string) (string, error) {
parsedArn, err := arn.Parse(policyArn)
if err != nil {
Expand Down Expand Up @@ -986,15 +994,15 @@ func (c *awsClient) detachAttachedRolePolicies(role *string) error {
return nil
}

func (c *awsClient) deleteInlineRolePolicies(role *string) error {
listRolePolicyOutput, err := c.iamClient.ListRolePolicies(&iam.ListRolePoliciesInput{RoleName: role})
func (c *awsClient) DeleteInlineRolePolicies(role string) error {
listRolePolicyOutput, err := c.iamClient.ListRolePolicies(&iam.ListRolePoliciesInput{RoleName: aws.String(role)})
if err != nil {
return err
}
for _, policyName := range listRolePolicyOutput.PolicyNames {
_, err = c.iamClient.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
PolicyName: policyName,
RoleName: role,
RoleName: aws.String(role),
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
Expand All @@ -1015,7 +1023,7 @@ func (c *awsClient) deleteAccountRolePolicies(role *string) error {
if err != nil {
return err
}
err = c.deleteInlineRolePolicies(role)
err = c.DeleteInlineRolePolicies(aws.StringValue(role))
if err != nil {
return err
}
Expand All @@ -1037,6 +1045,7 @@ func (c *awsClient) GetAttachedPolicy(role *string) ([]PolicyDetail, error) {
return policies, err
}
}

for _, policy := range attachedPoliciesOutput.AttachedPolicies {
policyDetail := PolicyDetail{
PolicyName: aws.StringValue(policy.PolicyName),
Expand Down Expand Up @@ -1481,10 +1490,12 @@ func (c *awsClient) validateRoleUpgradeVersionCompatibility(roleName string,
if err != nil {
return false, err
}
isAttachedPolicyExists := false
for _, attachedPolicy := range attachedPolicies {
if attachedPolicy.PolicyArn == "" {
if attachedPolicy.PolicType == Inline {
continue
}
isAttachedPolicyExists = true
isCompatible, err := c.isRolePoliciesCompatibleForUpgrade(attachedPolicy.PolicyArn, version)
if err != nil {
return false, errors.Errorf("Failed to validate role polices : %v", err)
Expand All @@ -1493,6 +1504,9 @@ func (c *awsClient) validateRoleUpgradeVersionCompatibility(roleName string,
return false, nil
}
}
if !isAttachedPolicyExists {
return false, nil
}
return true, nil
}

Expand Down

0 comments on commit 7b3efee

Please sign in to comment.