AWSTemplateFormatVersion: 2010-09-09
Parameters:
  CrossAccountRoleName:
    Description: >-
      Your Role Name (ex: OrganizationAccountAccessRole); This will need to be
      the same across all of the Member Accounts
    Type: String
    Default: union-ai-admin
  ExternalId:
    Description: >-
      External ID for additional security when assuming the cross-account role.
      This should be a unique identifier shared between Union AI and your account.
    Type: String
    NoEcho: true
    MinLength: 8
    MaxLength: 24
    AllowedPattern: '[\w+=,.@:\/-]*'
    ConstraintDescription: >-
      External ID must be between 8 and 24 characters and contain only
      alphanumeric characters and the following special characters: +=,.@:/-
Resources:
  CrossAccountRoleForAWSTrustedAdvisorUnion:
    Type: 'AWS::IAM::Role'
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W28
            reason: The role name needs to be same in all of the member accounts.
    Properties:
      RoleName: !Ref CrossAccountRoleName
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            AWS: arn:aws:iam::479331373192:root
          Action:
          - sts:AssumeRole
          Condition:
            StringEquals:
              'sts:ExternalId': !Ref ExternalId
  CrossAccountPolicyForAWSTrustedAdvisorUnion:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyName: UnionIAMPolicy
      Roles: [!Ref CrossAccountRoleForAWSTrustedAdvisorUnion]
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - 'logs:ListTagsLogGroup'
              - 'logs:TagLogGroup'
              - 'logs:UntagLogGroup'
              - 'logs:DescribeLogGroups'
              - 'logs:DeleteLogGroup'
              - 'eks:CreateNodegroup'
              - 'logs:CreateLogGroup'
              - 'eks:DeleteCluster'
              - 'kms:CreateAlias'
              - 'eks:DescribeCluster'
              - 'logs:PutRetentionPolicy'
              - 'kms:DeleteAlias'
            Resource:
              - !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:elastic-ip/*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/opta-*'
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:opta-*'
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group::log-stream*'
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/eks/opta-*:*'
          - Action:
              - sqs:CreateQueue
              - sqs:DeleteQueue
              - sqs:SetQueueAttributes
              - sqs:TagQueue
              - sqs:UntagQueue
              - sqs:GetQueueAttributes
              - sqs:ListQueueTags
            Effect: Allow
            Resource:
              - !Sub 'arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:Karpenter*'
          - Action:
              - events:DescribeRule
              - events:DeleteRule
              - events:ListTargetsByRule
              - events:ListTagsForResource
              - events:PutRule
              - events:PutTargets
              - events:RemoveTargets
              - events:TagResource
              - events:UntagResource
            Effect: Allow
            Resource:
              - !Sub 'arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/Karpenter*'
          - Effect: Allow
            Action:
              - 'eks:CreateAccessEntry'
              - 'eks:DescribeAccessEntry'
              - 'eks:UpdateAccessEntry'
              - 'eks:DeleteAccessEntry'
            Resource:
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/opta-*'
          - Effect: Allow
            Action:
              - 'kms:EnableKeyRotation'
              - 'kms:PutKeyPolicy'
              - 'kms:GetKeyPolicy'
              - 'ec2:AttachInternetGateway'
              - 'kms:ListResourceTags'
              - 'kms:TagResource'
              - 'kms:UntagResource'
              - 'ec2:DetachInternetGateway'
              - 'eks:DescribeNodegroup'
              - 'kms:GetKeyRotationStatus'
              - 'eks:DeleteNodegroup'
              - 'ec2:CreateInternetGateway'
              - 'kms:ScheduleKeyDeletion'
              - 'kms:CreateAlias'
              - 'kms:DescribeKey'
              - 'ec2:DeleteInternetGateway'
              - 'kms:DeleteAlias'
              - 'kms:CreateGrant'
            Resource:
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:nodegroup/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:internet-gateway/*'
              - !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/*'
          - Effect: Allow
            Action:
              - 'ec2:CreateRoute'
              - 'ec2:DeleteRoute'
              - 'ec2:CreateRouteTable'
              - 'ec2:DeleteRouteTable'
              - 'ec2:AssociateRouteTable'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:route-table/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/subnet-*'
          - Effect: Allow
            Action:
              - 'ec2:RevokeSecurityGroupIngress'
              - 'ec2:AuthorizeSecurityGroupEgress'
              - 'ec2:AuthorizeSecurityGroupIngress'
              - 'ec2:CreateSecurityGroup'
              - 'ec2:RevokeSecurityGroupEgress'
              - 'ec2:DeleteSecurityGroup'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group-rule/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/vpc-*'
          - Effect: Allow
            Action:
              - 'ec2:DeleteSubnet'
              - 'ec2:CreateNatGateway'
              - 'ec2:DeleteNatGateway'
              - 'ec2:CreateSubnet'
              - 'ec2:ModifySubnetAttribute'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:natgateway/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:elastic-ip/eipalloc-*'
          - Effect: Allow
            Action:
              - 'ec2:DeleteFlowLogs'
              - 'ec2:CreateFlowLogs'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc-flow-log/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/vpc*'
          - Effect: Allow
            Action:
              - 'ec2:CreateVpc'
              - 'ec2:CreateRouteTable'
              - 'ec2:AttachInternetGateway'
              - 'ec2:ModifyVpcAttribute'
              - 'ec2:DetachInternetGateway'
              - 'ec2:DeleteVpc'
              - 'ec2:CreateSubnet'
              - 'ec2:DescribeVpcAttribute'
              - 'ec2:AssociateVpcCidrBlock'
              - 'ec2:DisassociateVpcCidrBlock'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/*'
          - Effect: Allow
            Action:
              - 'iam:DeleteOpenIDConnectProvider'
              - 'iam:GetOpenIDConnectProvider'
              - 'iam:CreateOpenIDConnectProvider'
              - 'iam:TagOpenIDConnectProvider'
              - 'iam:UntagOpenIDConnectProvider'
              - 'iam:ListOpenIDConnectProviderTags'
              - 'iam:UpdateOpenIDConnectProviderThumbprint'
            Resource:
              - !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/*'
          - Effect: Allow
            Action:
              - 'iam:CreatePolicy'
              - 'iam:CreatePolicyVersion'
              - 'iam:DeletePolicyVersion'
              - 'iam:GetPolicyVersion'
              - 'iam:GetPolicy'
              - 'iam:ListPolicyVersions'
              - 'iam:DeletePolicy'
              - 'iam:ListPolicyTags'
              - 'iam:TagPolicy'
              - 'iam:UntagPolicy'
            Resource:
              - !Sub 'arn:aws:iam::${AWS::AccountId}:policy/*'
          - Effect: Allow
            Action:
              - 'iam:GetRole'
              - 'iam:TagRole'
              - 'iam:UntagRole'
              - 'iam:ListRoleTags'
              - 'iam:CreateRole'
              - 'iam:DeleteRole'
              - 'iam:AttachRolePolicy'
              - 'iam:PutRolePolicy'
              - 'iam:ListInstanceProfilesForRole'
              - 'iam:PassRole'
              - 'iam:CreateServiceLinkedRole'
              - 'iam:DetachRolePolicy'
              - 'iam:ListAttachedRolePolicies'
              - 'iam:DeleteRolePolicy'
              - 'iam:ListRolePolicies'
              - 'iam:GetRolePolicy'
            Resource:
              - !Sub 'arn:aws:iam::${AWS::AccountId}:role/*'
          - Effect: Allow
            Action:
              - 'ec2:DescribeAddresses'
              - 'ec2:EnableEbsEncryptionByDefault'
              - 'ec2:GetEbsEncryptionByDefault'
              - 'ec2:DescribeFlowLogs'
              - 'ec2:ResetEbsDefaultKmsKeyId'
              - 'ec2:DescribeInternetGateways'
              - 'ec2:DescribeNetworkInterfaces'
              - 'ec2:DescribeAvailabilityZones'
              - 'ec2:GetEbsDefaultKmsKeyId'
              - 'ec2:DescribeAccountAttributes'
              - 'kms:CreateKey'
              - 'ec2:DescribeNetworkAcls'
              - 'ec2:DescribeRouteTables'
              - 'ec2:ModifyEbsDefaultKmsKeyId'
              - 'eks:CreateCluster'
              - 'eks:UpdateClusterVersion'
              - 'eks:UpdateClusterConfig'
              - 'ec2:ReleaseAddress'
              - 'ec2:DescribeVpcClassicLinkDnsSupport'
              - 'ec2:DescribeNatGateways'
              - 'ec2:DisassociateRouteTable'
              - 'ec2:DescribeSecurityGroups'
              - 'ec2:DescribeVpcClassicLink'
              - 'ec2:DescribeVpcs'
              - 'kms:ListAliases'
              - 'ec2:DisableEbsEncryptionByDefault'
              - 'sts:GetCallerIdentity'
              - 'ec2:DescribeSubnets'
              - 'ec2:DescribeSecurityGroupRules'
              - 'ec2:AllocateAddress'
              - 'ec2:AssociateAddress'
              - 'ec2:DisassociateAddress'
              - 'ec2:DescribeAddressesAttribute'
              - 'ec2:DescribeInstanceTypeOfferings'
              - 'logs:DescribeLogStreams'
              - 'iam:ListRoles'
              - 'iam:ListPolicies'
              - 'ec2:DescribeInstanceTypes'
              - 'servicequotas:GetServiceQuota'
              - 'cloudwatch:GetMetricStatistics'
              - 'ec2:RunInstances'
              - 'ec2:CreateTags'
              - 'ec2:DescribeTags'
              - 'ec2:DeleteTags'
              - 'ec2:DescribeImages'
              - 'ec2:CreateLaunchTemplate'
              - 'ec2:CreateLaunchTemplateVersion'
              - 'ec2:DescribeLaunchTemplates'
              - 'ec2:DescribeLaunchTemplateVersions'
              - 'ec2:DeleteLaunchTemplate'
              - 'ec2:DeleteLaunchTemplateVersions'
              - 'ec2:ModifyLaunchTemplate'
              - 'autoscaling:CreateAutoScalingGroup'
              - 'autoscaling:DeleteAutoScalingGroup'
              - 'autoscaling:DescribeAutoScalingGroups'
              - 'autoscaling:UpdateAutoScalingGroup'
              - 'autoscaling:CreateLaunchConfiguration'
              - 'autoscaling:SetInstanceProtection'
              - 'autoscaling:DescribeScalingActivities'
              - 'autoscaling:CreateOrUpdateTags'
              - 'autoscaling:DescribeTags'
              - 'autoscaling:DeleteTags'
              - 'ec2:DescribeVpcEndpoints'
              - 'ec2:DescribePrefixLists'
              - 'ecr:GetAuthorizationToken'
            Resource: '*'
          - Effect: Allow
            Action: 'dynamodb:*'
            Resource:
              - !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/opta-*'
          - Effect: Allow
            Action: 's3:*'
            Resource:
              - 'arn:aws:s3:::opta-*'
              - 'arn:aws:s3:::opta-*/'
              - 'arn:aws:s3:::union-*'
              - 'arn:aws:s3:::union-*/'
          - Effect: Allow
            Action:
              - 'elasticache:CreateCacheSubnetGroup'
              - 'elasticache:AddTagsToResource'
              - 'elasticache:RemoveTagsFromResource'
              - 'elasticache:ListTagsForResource'
              - 'elasticache:DescribeCacheSubnetGroups'
              - 'elasticache:DeleteCacheSubnetGroup'
            Resource:
              - !Sub 'arn:aws:elasticache:${AWS::Region}:${AWS::AccountId}:subnetgroup:opta-*'
          - Effect: Allow
            Action:
              - 'iam:CreateInstanceProfile'
              - 'iam:AddRoleToInstanceProfile'
              - 'iam:RemoveRoleFromInstanceProfile'
              - 'iam:DeleteInstanceProfile'
              - 'iam:TagInstanceProfile'
              - 'iam:UntagInstanceProfile'
              - 'iam:ListInstanceProfileTags'
              - 'iam:GetInstanceProfile'
              - 'iam:UpdateAssumeRolePolicy'
            Resource:
              - !Sub 'arn:aws:iam::${AWS::AccountId}:instance-profile/*'
          - Effect: Allow
            Action:
              - 'eks:UpdateNodegroupConfig'
              - 'eks:ListNodegroups'
              - 'eks:UpdateNodegroupVersion'
              - 'eks:TagResource'
              - 'eks:UntagResource'
              - 'eks:ListTagsForResource'
              - 'eks:DescribeUpdate'
              - 'eks:DeleteNodegroup'
            Resource:
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:addon/opta-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/opta-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:nodegroup/opta-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:addon/union-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/union-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:nodegroup/union-*'
          - Effect: Allow
            Action:
              - 'eks:CreateAddon'
              - 'eks:UpdateAddon'
              - 'eks:DeleteAddon'
              - 'eks:DescribeAddonVersions'
              - 'eks:DescribeAddon'
              - 'eks:ListAddons'
            Resource:
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:addon/opta-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/opta-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:addon/union-*'
              - !Sub 'arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/union-*'
          - Effect: Allow
            Action:
              - 'ec2:CreateVpcEndpoint'
              - 'ec2:ModifyVpcEndpoint'
              - 'ec2:DeleteVpcEndpoints'
            Resource:
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/vpc*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc-endpoint/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:route-table/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/*'
              - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/*'
          - Effect: Allow
            Action:
              - logs:GetLogEvents
              - logs:FilterLogEvents
            Resource:
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/eks/opta-*:log-stream:kube-*'
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/union/cluster-*/*:log-stream:*'
              - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/containerinsights/opta-*/application:log-stream:fluentbit-kube.var.log.containers.*'
          - Effect: Allow
            Action:
              - ecr:CreateRepository
              - ecr:DeleteRepository
              - ecr:TagResource
              - ecr:UntagResource
              - ecr:PutLifecyclePolicy
              - ecr:DeleteLifecyclePolicy
              - ecr:PutImageTagMutability
              - ecr:PutImageScanningConfiguration
              - ecr:BatchDeleteImage
              - ecr:DeleteRepositoryPolicy
              - ecr:SetRepositoryPolicy
              - ecr:GetRepositoryPolicy
              - ecr:PutReplicationConfiguration
              - ecr:DescribeRepositories
              - ecr:ListTagsForResource
              - ecr:GetLifecyclePolicy
              - ecr:DescribeImages
            Resource:
              - !Sub 'arn:aws:ecr:*:${AWS::AccountId}:repository/union/*'
Metadata:
  'AWS::CloudFormation::Designer': {}
Outputs:
  RoleId:
    Description: The logical ID of the IAM role
    Value: !Ref CrossAccountRoleForAWSTrustedAdvisorUnion
  RoleArn:
    Description: The ARN of the IAM role
    Value: !GetAtt [CrossAccountRoleForAWSTrustedAdvisorUnion, Arn]
  PolicyId:
    Description: The logical ID of the IAM policy
    Value: !Ref CrossAccountPolicyForAWSTrustedAdvisorUnion
  ExternalId:
    Description: The External ID used for additional security
    Value: !Ref ExternalId
