func GetAttachedPolicies(reqLogger logr.Logger, byocRole string, byocAWSClient awsclient.Client) (*iam.ListAttachedRolePoliciesOutput, error) {
	listRoleInput := &iam.ListAttachedRolePoliciesInput{
		RoleName: aws.String(byocRole),
	}
	policyList, err := byocAWSClient.ListAttachedRolePolicies(listRoleInput)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			default:
				reqLogger.Error(
					aerr,
					aerr.Error(),
				)
				return &iam.ListAttachedRolePoliciesOutput{}, err
			}
		} else {
			return &iam.ListAttachedRolePoliciesOutput{}, err
		}
	}
	return policyList, nil
}
GetAttachedPolicies gets a list of policies attached to a role
package account
import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/aws/aws-sdk-go/service/sts"
	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"
	awsv1alpha1 "github.com/openshift/aws-account-operator/pkg/apis/aws/v1alpha1"
	"github.com/openshift/aws-account-operator/pkg/awsclient"
	"github.com/openshift/aws-account-operator/pkg/controller/utils"
)
func newBYOCAccount(currentAcctInstance *awsv1alpha1.Account) bool {
	if currentAcctInstance.IsBYOC() {
		if !currentAcctInstance.HasState() || !currentAcctInstance.IsClaimed() {
			return true
		}
	}
	return false
}
func claimBYOCAccount(r *ReconcileAccount, reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account) error {
	if !currentAcctInstance.IsClaimed() {
		reqLogger.Info("Marking BYOC account claimed")
		currentAcctInstance.Status.Claimed = true
		return r.statusUpdate(currentAcctInstance)
	}
	return nil
}
func (r *ReconcileAccount) initializeNewCCSAccount(reqLogger logr.Logger, account *awsv1alpha1.Account) (reconcile.Result, error) {
	accountClaim, acctClaimErr := r.getAccountClaim(account)
	if acctClaimErr != nil {
		if accountClaim != nil {
			utils.SetAccountClaimStatus(
				accountClaim,
				"Failed to get AccountClaim for CSS account",
				"FailedRetrievingAccountClaim",
				awsv1alpha1.ClientError,
				awsv1alpha1.ClaimStatusError,
			)
			err := r.Client.Status().Update(context.TODO(), accountClaim)
			if err != nil {
				reqLogger.Error(err, "failed to update accountclaim status")
			}
		} else {
			reqLogger.Error(acctClaimErr, "accountclaim is nil")
		}
		return reconcile.Result{}, acctClaimErr
	}
	validateErr := accountClaim.Validate()
	if validateErr != nil {
		errReason := validateErr.Error()
		utils.SetAccountClaimStatus(
			accountClaim,
			"Invalid AccountClaim",
			errReason,
			awsv1alpha1.InvalidAccountClaim,
			awsv1alpha1.ClaimStatusError,
		)
		err := r.Client.Status().Update(context.TODO(), accountClaim)
		if err != nil {
			reqLogger.Error(err, "Failed to Update AccountClaim Status")
		}
		return reconcile.Result{}, validateErr
	}
	claimErr := claimBYOCAccount(r, reqLogger, account)
	if claimErr != nil {
		reqLogger.Error(claimErr, "Could not claim BYOC Account")
		claimStatusErr := r.setAccountClaimError(reqLogger, account, claimErr.Error())
		if claimStatusErr != nil {
			reqLogger.Error(claimStatusErr, "failed setting accountClaim error state")
		}
		return reconcile.Result{}, claimErr
	}
	return reconcile.Result{}, nil
}
func (r *ReconcileAccount) GetSREAccessARN(reqLogger logr.Logger, arnName string) (string, error) {
	configMap := &corev1.ConfigMap{}
	err := r.Client.Get(
		context.TODO(),
		types.NamespacedName{
			Namespace: awsv1alpha1.AccountCrNamespace,
			Name:      awsv1alpha1.DefaultConfigMap,
		},
		configMap,
	)
	if err != nil {
		reqLogger.Error(err, "There was an error getting the ConfigMap to get the SRE Access Role")
		return "", err
	}
	SREAccessARN := configMap.Data[arnName]
	if SREAccessARN == "" {
		reqLogger.Error(awsv1alpha1.ErrInvalidConfigMap, "configmap key missing", "keyName", arnName)
		return "", awsv1alpha1.ErrInvalidConfigMap
	}
	return SREAccessARN, nil
}
func (r *ReconcileAccount) createBYOCAdminAccessRole(reqLogger logr.Logger, awsSetupClient awsclient.Client, byocAWSClient awsclient.Client, policyArn string, instanceID string, tags []*iam.Tag) (roleID string, err error) {
	getUserOutput, err := awsSetupClient.GetUser(&iam.GetUserInput{})
	if err != nil {
		reqLogger.Error(err, "Failed to get non-BYOC IAM User info")
		return roleID, err
	}
	principalARN := *getUserOutput.User.Arn
	SREAccessARN, err := r.GetSREAccessARN(reqLogger, awsv1alpha1.CCSAccessARN)
	if err != nil {
		return roleID, err
	}
	accessArnList := []string{principalARN, SREAccessARN}
	byocInstanceIDRole := fmt.Sprintf("%s-%s", byocRole, instanceID)
	existingRole, err := GetExistingRole(reqLogger, byocInstanceIDRole, byocAWSClient)
	if err != nil {
		return roleID, err
	}
	if (*existingRole != iam.GetRoleOutput{}) {
		reqLogger.Info(fmt.Sprintf("Found pre-existing role: %s", byocInstanceIDRole))
		err := DeleteBYOCAdminAccessRole(reqLogger, byocAWSClient, byocInstanceIDRole)
		if err != nil {
			return roleID, err
		}
	}
	roleID, err = CreateRole(reqLogger, byocInstanceIDRole, accessArnList, byocAWSClient, tags)
	if err != nil {
		return roleID, err
	}
	reqLogger.Info(fmt.Sprintf("New RoleID created: %s", roleID))
	err = attachAndEnsureRolePolicies(reqLogger, byocAWSClient, byocInstanceIDRole, policyArn)
	return roleID, err
}
func DeleteBYOCAdminAccessRole(reqLogger logr.Logger, byocAWSClient awsclient.Client, byocInstanceIDRole string) (err error) {
	policyList, err := GetAttachedPolicies(reqLogger, byocInstanceIDRole, byocAWSClient)
	if err != nil {
		return err
	}
	for _, policy := range policyList.AttachedPolicies {
		err := DetachPolicyFromRole(reqLogger, policy, byocInstanceIDRole, byocAWSClient)
		if err != nil {
			return err
		}
	}
	return DeleteRole(reqLogger, byocInstanceIDRole, byocAWSClient)
}
func CreateRole(reqLogger logr.Logger, byocRole string, accessArnList []string, byocAWSClient awsclient.Client, tags []*iam.Tag) (string, error) {
	assumeRolePolicyDoc := struct {
		Version   string
		Statement []awsStatement
	}{
		Version: "2012-10-17",
		Statement: []awsStatement{{
			Effect: "Allow",
			Action: []string{"sts:AssumeRole"},
			Principal: &awsv1alpha1.Principal{
				AWS: accessArnList,
			},
		}},
	}
	jsonAssumeRolePolicyDoc, err := json.Marshal(&assumeRolePolicyDoc)
	if err != nil {
		return "", err
	}
	reqLogger.Info(fmt.Sprintf("Creating role: %s", byocRole))
	createRoleOutput, err := byocAWSClient.CreateRole(&iam.CreateRoleInput{
		Tags:                     tags,
		RoleName:                 aws.String(byocRole),
		Description:              aws.String("AdminAccess for BYOC"),
		AssumeRolePolicyDocument: aws.String(string(jsonAssumeRolePolicyDoc)),
	})
	if err != nil {
		return "", err
	}
	return *createRoleOutput.Role.RoleId, nil
}
func GetExistingRole(reqLogger logr.Logger, byocRole string, byocAWSClient awsclient.Client) (*iam.GetRoleOutput, error) {
	existingRole, err := byocAWSClient.GetRole(&iam.GetRoleInput{
		RoleName: aws.String(byocRole),
	})
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case iam.ErrCodeNoSuchEntityException:
				reqLogger.Info(fmt.Sprintf("%s role does not yet exist", byocRole))
				return &iam.GetRoleOutput{}, nil
			case iam.ErrCodeServiceFailureException:
				reqLogger.Error(
					aerr,
					fmt.Sprintf("AWS Internal Server Error (%s) checking for %s role existence: %s", aerr.Code(), byocRole, aerr.Message()),
				)
				return &iam.GetRoleOutput{}, err
			default:
				reqLogger.Error(
					aerr,
					fmt.Sprintf("Unknown error (%s) checking for %s role existence: %s", aerr.Code(), byocRole, aerr.Message()),
				)
				return &iam.GetRoleOutput{}, err
			}
		} else {
			return &iam.GetRoleOutput{}, err
		}
	}
	return existingRole, err
}