Description: Create IAM roles for tidbcloud dataplane
Parameters:
  # ControlPlane account id
  ControlPlaneAccountId:
    Type: String
    Description: "TiDB Cloud Control Plane AWS Principal"
    Default: "385595570414"
  # Route53 hosted zone id
  HostedZoneId:
    Type: String
    Description: "The Route 53 hosted zone ID to manage DNS records"
    Default: "Z06682812CVJ47GSWA32H"
  # PCA ARN
  PCAArn:
    Type: String
    Description: "The ARN of the ACM Private CA to be used by cert-manager"
    Default: "arn:aws:acm-pca:us-west-2:227896186585:certificate-authority/4d4bd82b-069c-4d49-891c-5daaf8f52820"
  # Clinic account id
  ClinicAccountId:
    Type: String
    Description: "TiDB Cloud Clinic Account AWS Principal"
    Default: "552185537300"
  EnableExternalDNSNodeRolePolicy:
    Type: String
    Description: "Whether to enable Route53 permissions for external-dns on EKS node role"
    Default: "false"
    AllowedValues:
      - "true"
      - "false"
  AdditionalPCAArns:
    Type: CommaDelimitedList
    Default: ""
    Description: "Additional PCA ARNs for multi-region deployments (comma-separated full ARNs, e.g. arn:aws:acm-pca:us-east-1:ACCOUNT:certificate-authority/ID)"
  AdditionalHostedZoneIds:
    Type: CommaDelimitedList
    Default: ""
    Description: "Additional hosted zone IDs for multi-region deployments (comma-separated IDs, e.g. Z111AAA,Z222BBB)"
  ResourceNamePrefix:
    Type: String
    Default: "tidbcloud"
    Description: "Prefix for TiDB Cloud managed AWS resource names"
  RequiredManagedByTagValue:
    Type: String
    Default: "PingCAP"
    Description: "Required value for the ManagedBy tag on TiDB Cloud managed AWS resources"
  SLIBucketNamePrefix:
    Type: String
    Default: "tidbcloud-sli-data"
    Description: "Prefix for SLI data buckets readable by Clinic"
Conditions:
  EnableExternalDNSNodeRolePolicyCondition: !Equals [!Ref EnableExternalDNSNodeRolePolicy, "true"]
  HasAdditionalPCAs: !Not [!Equals [!Join [",", !Ref AdditionalPCAArns], ""]]
  HasAdditionalHostedZones: !Not [!Equals [!Join [",", !Ref AdditionalHostedZoneIds], ""]]
Resources:
  # Create an eks service role
  TiDBCloudEKSServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-eks-service-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: eks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
  TiDBCloudEKSNodeRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-eks-node-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly
      # Attach inline policy to allow cert-manager to use ACM PCA
      # Ref: https://github.com/cert-manager/aws-privateca-issuer#configuration
      Policies:
        - PolicyName: AllowCertManager
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - acm-pca:DescribeCertificateAuthority
                  - acm-pca:GetCertificate
                  - acm-pca:IssueCertificate
                Resource: !Sub ${PCAArn}
              - !If
                - HasAdditionalPCAs
                - Effect: Allow
                  Action:
                    - acm-pca:DescribeCertificateAuthority
                    - acm-pca:GetCertificate
                    - acm-pca:IssueCertificate
                  Resource: !Ref AdditionalPCAArns
                - !Ref AWS::NoValue
        # Attach inline policy for aws-load-balancer-controller
        # Ref: https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v2.13.4/docs/install/iam_policy.json
        - PolicyName: AllowLoadBalancerController
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - iam:CreateServiceLinkedRole
                Resource: "*"
                Condition:
                  StringEquals:
                    iam:AWSServiceName: "elasticloadbalancing.amazonaws.com"
              - Effect: Allow
                Action:
                  - ec2:DescribeAccountAttributes
                  - ec2:DescribeAddresses
                  - ec2:DescribeAvailabilityZones
                  - ec2:DescribeInternetGateways
                  - ec2:DescribeVpcs
                  - ec2:DescribeVpcPeeringConnections
                  - ec2:DescribeSubnets
                  - ec2:DescribeSecurityGroups
                  - ec2:DescribeInstances
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DescribeTags
                  - ec2:GetCoipPoolUsage
                  - ec2:DescribeCoipPools
                  - ec2:GetSecurityGroupsForVpc
                  - elasticloadbalancing:DescribeLoadBalancers
                  - elasticloadbalancing:DescribeLoadBalancerAttributes
                  - elasticloadbalancing:DescribeListeners
                  - elasticloadbalancing:DescribeListenerCertificates
                  - elasticloadbalancing:DescribeSSLPolicies
                  - elasticloadbalancing:DescribeRules
                  - elasticloadbalancing:DescribeTargetGroups
                  - elasticloadbalancing:DescribeTargetGroupAttributes
                  - elasticloadbalancing:DescribeTargetHealth
                  - elasticloadbalancing:DescribeTags
                  - elasticloadbalancing:DescribeTrustStores
                  - elasticloadbalancing:DescribeListenerAttributes
                  - elasticloadbalancing:DescribeCapacityReservation
                Resource: "*"
              - Effect: Allow
                Action:
                  - cognito-idp:DescribeUserPoolClient
                  - acm:ListCertificates
                  - acm:DescribeCertificate
                  - iam:ListServerCertificates
                  - iam:GetServerCertificate
                  - waf-regional:GetWebACL
                  - waf-regional:GetWebACLForResource
                  - waf-regional:AssociateWebACL
                  - waf-regional:DisassociateWebACL
                  - wafv2:GetWebACL
                  - wafv2:GetWebACLForResource
                  - wafv2:AssociateWebACL
                  - wafv2:DisassociateWebACL
                  - shield:GetSubscriptionState
                  - shield:DescribeProtection
                  - shield:CreateProtection
                  - shield:DeleteProtection
                Resource: "*"
              - Effect: Allow
                Action:
                  - ec2:AuthorizeSecurityGroupIngress
                  - ec2:RevokeSecurityGroupIngress
                Resource: "*"
              - Effect: Allow
                Action:
                  - ec2:CreateSecurityGroup
                Resource: "*"
              - Effect: Allow
                Action:
                  - ec2:CreateTags
                Resource: arn:aws:ec2:*:*:security-group/*
                Condition:
                  StringEquals:
                    ec2:CreateAction: CreateSecurityGroup
                  "Null":
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "false"
              - Effect: Allow
                Action:
                  - ec2:CreateTags
                  - ec2:DeleteTags
                Resource: arn:aws:ec2:*:*:security-group/*
                Condition:
                  "Null":
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "true"
                    "aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
              - Effect: Allow
                Action:
                  - ec2:AuthorizeSecurityGroupIngress
                  - ec2:RevokeSecurityGroupIngress
                  - ec2:DeleteSecurityGroup
                Resource: "*"
                Condition:
                  "Null":
                    aws:ResourceTag/elbv2.k8s.aws/cluster: "false"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:CreateLoadBalancer
                  - elasticloadbalancing:CreateTargetGroup
                Resource: "*"
                Condition:
                  "Null":
                    aws:RequestTag/elbv2.k8s.aws/cluster: "false"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:CreateListener
                  - elasticloadbalancing:DeleteListener
                  - elasticloadbalancing:CreateRule
                  - elasticloadbalancing:DeleteRule
                Resource: "*"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:AddTags
                  - elasticloadbalancing:RemoveTags
                Resource:
                  - arn:aws:elasticloadbalancing:*:*:targetgroup/*/*
                  - arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*
                  - arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*
                Condition:
                  "Null":
                    aws:RequestTag/elbv2.k8s.aws/cluster: "true"
                    aws:ResourceTag/elbv2.k8s.aws/cluster: "false"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:AddTags
                  - elasticloadbalancing:RemoveTags
                Resource:
                  - arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*
                  - arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*
                  - arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*
                  - arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*
              - Effect: Allow
                Action:
                  - elasticloadbalancing:ModifyLoadBalancerAttributes
                  - elasticloadbalancing:SetIpAddressType
                  - elasticloadbalancing:SetSecurityGroups
                  - elasticloadbalancing:SetSubnets
                  - elasticloadbalancing:DeleteLoadBalancer
                  - elasticloadbalancing:ModifyTargetGroup
                  - elasticloadbalancing:ModifyTargetGroupAttributes
                  - elasticloadbalancing:DeleteTargetGroup
                  - elasticloadbalancing:ModifyListenerAttributes
                  - elasticloadbalancing:ModifyCapacityReservation
                  - elasticloadbalancing:ModifyIpPools
                Resource: "*"
                Condition:
                  "Null":
                    aws:ResourceTag/elbv2.k8s.aws/cluster: "false"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:AddTags
                Resource:
                  - arn:aws:elasticloadbalancing:*:*:targetgroup/*/*
                  - arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*
                  - arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*
                Condition:
                  StringEquals:
                    elasticloadbalancing:CreateAction:
                      - CreateTargetGroup
                      - CreateLoadBalancer
                  "Null":
                    aws:RequestTag/elbv2.k8s.aws/cluster: "false"
              - Effect: Allow
                Action:
                  - elasticloadbalancing:RegisterTargets
                  - elasticloadbalancing:DeregisterTargets
                Resource: arn:aws:elasticloadbalancing:*:*:targetgroup/*/*
              - Effect: Allow
                Action:
                  - elasticloadbalancing:SetWebAcl
                  - elasticloadbalancing:ModifyListener
                  - elasticloadbalancing:AddListenerCertificates
                  - elasticloadbalancing:RemoveListenerCertificates
                  - elasticloadbalancing:ModifyRule
                  - elasticloadbalancing:SetRulePriorities
                Resource: "*"
        # Attach inline policy to allow cluster-autoscaler
        # Ref: https://docs.aws.amazon.com/eks/latest/best-practices/cas.html
        - PolicyName: AllowClusterAutoscaler
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - autoscaling:DescribeAutoScalingGroups
                  - autoscaling:DescribeAutoScalingInstances
                  - autoscaling:DescribeLaunchConfigurations
                  - autoscaling:DescribeScalingActivities
                  - autoscaling:DescribeTags
                  - ec2:DescribeImages
                  - ec2:DescribeInstanceTypes
                  - ec2:DescribeLaunchTemplateVersions
                  - ec2:GetInstanceTypesFromInstanceRequirements
                  - eks:DescribeNodegroup
                Resource: "*"
              - Effect: Allow
                Action:
                  - autoscaling:SetDesiredCapacity
                  - autoscaling:TerminateInstanceInAutoScalingGroup
                Resource: "*"
                Condition:
                  StringEquals:
                    aws:ResourceTag/k8s.io/cluster-autoscaler/enabled: "true"
        # Attach inline policy to allow assuming pre-provisioned TiDB Cloud roles and customer-provided import/CDC roles
        - PolicyName: AllowAssumeRoles
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: AllowAssumePreProvisionedRoles
                Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-o11y-agent-role
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-audit-log-write-only-role
              - Sid: AllowAssumeCustomerTaggedRoles
                Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - arn:aws:iam::*:role/*
                Condition:
                  StringEquals:
                    "aws:ResourceTag/tidbcloud.com/allow-dataplane-access": "true"
        # Attach inline policy to allow tidb-cluster
        - PolicyName: AllowTiDBCluster
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ec2:RebootInstances
                Resource:
                  - arn:aws:ec2:*:*:instance/*
        - PolicyName: AllowKMS
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: AllowAccessKMS
                Effect: Allow
                Action:
                  - kms:Encrypt
                  - kms:Decrypt
                  - kms:ReEncrypt*
                  - kms:GenerateDataKey*
                  - kms:CreateGrant
                  - kms:DescribeKey
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:ResourceTag/tidbcloud.com/allow-dataplane-access": "true"
        - PolicyName: AllowSliReporter
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - firehose:PutRecord
                Resource:
                  - arn:aws:firehose:*:*:deliverystream/tidbcloud-sli*
        - !If
          - EnableExternalDNSNodeRolePolicyCondition
          - PolicyName: AllowExternalDNS
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: Allow
                  Action:
                    - route53:ChangeResourceRecordSets
                    - route53:ListResourceRecordSets
                    - route53:ListTagsForResources
                  Resource:
                    - !Sub arn:aws:route53:::hostedzone/${HostedZoneId}
                - !If
                  - HasAdditionalHostedZones
                  - Effect: Allow
                    Action:
                      - route53:ChangeResourceRecordSets
                      - route53:ListResourceRecordSets
                      - route53:ListTagsForResources
                    Resource: !Ref AdditionalHostedZoneIds
                  - !Ref AWS::NoValue
                - Effect: Allow
                  Action:
                    - route53:ListHostedZones
                  Resource:
                    - "*"
          - !Ref AWS::NoValue
  # Create instance profile for EKS node role
  TiDBCloudEKSNodeInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: tidbcloud-eks-node-instance-profile
      Roles:
        - !Ref TiDBCloudEKSNodeRole
  # Create audit-log write only role
  TiDBCloudAuditLogWriteOnlyRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-audit-log-write-only-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !GetAtt TiDBCloudEKSNodeRole.Arn
            Action: sts:AssumeRole
      Policies:
        - PolicyName: audit-log-bucket-write-only-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: WriteAuditLogBucket
                Effect: Allow
                Action:
                  - s3:PutObject
                Resource:
                  - arn:aws:s3:::tidbcloud-*-byoc-audit/*
  # Create dataplane-manager role
  TiDBCloudDataplaneManagerRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-dataplane-manager-assumed-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${ControlPlaneAccountId}:root
            Action: sts:AssumeRole
            Condition:
              StringLike:
                aws:PrincipalArn:
                  - !Sub arn:aws:iam::${ControlPlaneAccountId}:role/*-dataplane-manager
      Policies:
        - PolicyName: dataplane-manager-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: EKSReadServiceAndNodeRole
                Effect: Allow
                Action:
                  - iam:GetRole
                  - iam:ListAttachedRolePolicies
                Resource:
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-eks-node-role
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-eks-service-role
              - Sid: EKSPassServiceAndNodeRole
                Effect: Allow
                Action:
                  - iam:PassRole
                Resource:
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-eks-node-role
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/tidbcloud-eks-service-role
                Condition:
                  StringEquals:
                    "iam:PassedToService": eks.amazonaws.com
              - Sid: EKSReadServiceLinkedRole
                Effect: Allow
                Action:
                  - iam:GetRole
                Resource:
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup
              - Sid: EKSCreateServiceLinkedRole
                Effect: Allow
                Action:
                  - iam:CreateServiceLinkedRole
                Resource:
                  - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup
                Condition:
                  StringEquals:
                    "iam:AWSServiceName": eks-nodegroup.amazonaws.com
              - Sid: S3OperationsWithPrefix
                Effect: Allow
                Action:
                  - s3:ListBucket
                  - s3:GetBucket*
                  - s3:GetEncryptionConfiguration
                  - s3:GetLifecycleConfiguration
                  - s3:PutLifecycleConfiguration
                  - s3:GetReplicationConfiguration
                  - s3:GetAccelerateConfiguration
                  - s3:CreateBucket
                  - s3:DeleteBucket
                  - s3:PutBucketTagging
                  - s3:PutBucketPolicy
                  - s3:DeleteBucketPolicy
                  - s3:PutBucketOwnershipControls
                Resource: !Sub arn:aws:s3:::${ResourceNamePrefix}*
              - Sid: EC2ReadOnlyOperations
                Effect: Allow
                Action:
                  - ec2:DescribeVpcs
                  - ec2:DescribeVpcAttribute
                  - ec2:DescribeVpcEndpoints
                  - ec2:DescribeAddresses
                  - ec2:DescribeSubnets
                  - ec2:DescribeRouteTables
                  - ec2:DescribeNatGateways
                  - ec2:DescribeInternetGateways
                  - ec2:DescribeSecurityGroup*
                  - ec2:DescribePlacementGroups
                  - ec2:DescribeLaunchTemplates
                  - ec2:DescribeLaunchTemplateVersions
                  - ec2:DescribeInstances
                  - ec2:DescribeInstanceAttribute
                  - ec2:DescribeInstanceTypes
                  - ec2:DescribeAvailabilityZones
                  - ec2:DescribeAddressesAttribute
                  - ec2:DescribePrefixLists
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DescribePlacementGroups
                Resource: "*"
              - Sid: EC2CreateOperationsWithRequiredTag
                Effect: Allow
                Action:
                  - ec2:CreateVpc
                  - ec2:AllocateAddress
                  - ec2:CreateNatGateway
                  - ec2:CreateInternetGateway
                  - ec2:CreateSubnet
                  - ec2:CreateRouteTable
                  - ec2:CreateSecurityGroup
                  - ec2:CreateLaunchTemplate
                  - ec2:CreatePlacementGroup
                  - ec2:RunInstances
                  - ec2:CreateVpcPeeringConnection
                  - ec2:CreateVpcEndpoint
                  - ec2:CreateVpcEndpointServiceConfiguration
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:RequestTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2CreateOperationsInTaggedVpcs
                Effect: Allow
                Action:
                  - ec2:CreateNatGateway
                  - ec2:CreateSubnet
                  - ec2:CreateRouteTable
                  - ec2:CreateSecurityGroup
                  - ec2:CreateVpcPeeringConnection
                  - ec2:CreateVpcEndpoint
                Resource: !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:vpc/*
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2CreateOperationsInTaggedSubnets
                Effect: Allow
                Action:
                  - ec2:CreateNatGateway
                  - ec2:CreateVpcEndpoint
                  - ec2:RunInstances
                Resource: !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:subnet/*
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2CreateOperationsWithTaggedDependencies
                Effect: Allow
                Action:
                  - ec2:CreateNatGateway
                  - ec2:CreateVpcEndpoint
                  - ec2:RunInstances
                Resource:
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:elastic-ip/*
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:route-table/*
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group/*
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:launch-template/*
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:placement-group/*
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2RunInstancesWithEksClusterSecurityGroups
                Effect: Allow
                Action:
                  - ec2:RunInstances
                Resource:
                  - !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group/*
                Condition:
                  ArnLike:
                    "ec2:LaunchTemplate": !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:launch-template/*
                  StringLike:
                    "aws:ResourceTag/aws:eks:cluster-name": !Sub "${ResourceNamePrefix}*"
              - Sid: EC2RunInstancesWithAmazonMachineImages
                Effect: Allow
                Action:
                  - ec2:RunInstances
                Resource:
                  - !Sub arn:${AWS::Partition}:ec2:*::image/*
                Condition:
                  ArnLike:
                    "ec2:LaunchTemplate": !Sub arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:launch-template/*
                  StringEquals:
                    "ec2:Owner": amazon
                    "ec2:ImageType": machine
                    "ec2:RootDeviceType": ebs
                  Bool:
                    "ec2:Public": "true"
              - Sid: EC2ModifyOperationsOnTaggedResources
                Effect: Allow
                Action:
                  - ec2:ModifyVpc*
                  - ec2:DeleteVpc
                  - ec2:ReleaseAddress
                  - ec2:DeleteNatGateway
                  - ec2:AssociateNatGatewayAddress
                  - ec2:AttachInternetGateway
                  - ec2:DetachInternetGateway
                  - ec2:DeleteInternetGateway
                  - ec2:DeleteSubnet
                  - ec2:DeleteRouteTable
                  - ec2:CreateRoute
                  - ec2:DeleteRoute
                  - ec2:AssociateRouteTable
                  - ec2:DisassociateRouteTable
                  - ec2:AuthorizeSecurityGroupIngress
                  - ec2:AuthorizeSecurityGroupEgress
                  - ec2:RevokeSecurityGroupIngress
                  - ec2:RevokeSecurityGroupEgress
                  - ec2:DeleteSecurityGroup
                  - ec2:CreateLaunchTemplateVersion
                  - ec2:DeleteLaunchTemplate
                  - ec2:DeletePlacementGroup
                  - ec2:RebootInstances
                  - ec2:StopInstances
                  - ec2:TerminateInstances
                  - ec2:DeleteVpcPeeringConnection
                  - ec2:AcceptVpcPeeringConnection
                  - ec2:DeleteVpcEndpointServiceConfigurations
                  - ec2:DeleteVpcEndpoints
                  - ec2:AcceptVpcEndpointConnections
                  - ec2:RejectVpcEndpointConnections
                  - ec2:StartVpcEndpointServicePrivateDnsVerification
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2CreateTagsOnCreateWithRequiredTag
                Effect: Allow
                Action:
                  - ec2:CreateTags
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:RequestTag/ManagedBy": !Ref RequiredManagedByTagValue
                    "ec2:CreateAction":
                      - CreateVpc
                      - AllocateAddress
                      - CreateNatGateway
                      - CreateInternetGateway
                      - CreateSubnet
                      - CreateRouteTable
                      - CreateSecurityGroup
                      - CreateLaunchTemplate
                      - CreatePlacementGroup
                      - RunInstances
                      - CreateVpcPeeringConnection
                      - CreateVpcEndpoint
                      - CreateVpcEndpointServiceConfiguration
              - Sid: EC2CreateTagsOnTaggedResources
                Effect: Allow
                Action:
                  - ec2:CreateTags
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
                  StringEqualsIfExists:
                    "aws:RequestTag/ManagedBy": !Ref RequiredManagedByTagValue
              - Sid: EC2DeleteTagsFromTaggedResources
                Effect: Allow
                Action:
                  - ec2:DeleteTags
                Resource: "*"
                Condition:
                  StringEquals:
                    "aws:ResourceTag/ManagedBy": !Ref RequiredManagedByTagValue
                  ForAllValues:StringNotEquals:
                    "aws:TagKeys": ManagedBy
              - Sid: VPCPeeringReadOnlyOperations
                Effect: Allow
                Action:
                  - ec2:DescribeVpcPeeringConnections
                Resource: "*"
              - Sid: PrivateLinkReadOnlyOperations
                Effect: Allow
                Action:
                  - ec2:DescribeVpcEndpointConnections
                  - ec2:DescribeVpcEndpointServices
                  - ec2:DescribeVpcEndpointServicePermissions
                  - ec2:DescribeVpcEndpointServiceConfigurations
                  - elasticloadbalancing:DescribeLoadBalancers
                Resource: "*"
              - Sid: EKSReadOnlyOperations
                Effect: Allow
                Action:
                  - eks:ListClusters
                  - eks:DescribeCluster
                  - eks:ListNodegroups
                  - eks:DescribeNodegroup
                  - eks:ListAddons
                  - eks:DescribeAddon
                  - eks:DescribeUpdate
                  - eks:ListAccessEntries
                  - eks:DescribeAccessEntry
                  - eks:ListAssociatedAccessPolicies
                Resource: "*"
              - Sid: EKSWriteOperationsWithPrefix
                Effect: Allow
                Action:
                  - eks:CreateCluster
                  - eks:TagResource
                  - eks:CreateNodegroup
                  - eks:CreateAddon
                  - eks:UpdateClusterVersion
                  - eks:UpdateClusterConfig
                  - eks:UpdateNodegroupConfig
                  - eks:UpdateNodegroupVersion
                  - eks:UpdateAddon
                  - eks:DeleteCluster
                  - eks:DeleteNodeGroup
                  - eks:DeleteAddon
                  - eks:CreateAccessEntry
                  - eks:DeleteAccessEntry
                  - eks:UpdateAccessEntry
                  - eks:AssociateAccessPolicy
                  - eks:DisassociateAccessPolicy
                  - eks:UntagResource
                Resource:
                  - !Sub arn:aws:eks:*:${AWS::AccountId}:cluster/${ResourceNamePrefix}*
                  - !Sub arn:aws:eks:*:${AWS::AccountId}:nodegroup/${ResourceNamePrefix}*/*
                  - !Sub arn:aws:eks:*:${AWS::AccountId}:addon/${ResourceNamePrefix}*/*
                  - !Sub arn:aws:eks:*:${AWS::AccountId}:access-entry/${ResourceNamePrefix}*/*
              - Sid: Route53ResourceRecordSetOperations
                Effect: Allow
                Action:
                  - route53:ListResourceRecordSets
                  - route53:ChangeResourceRecordSets
                  - route53:AssociateVPCWithHostedZone
                  - route53:GetHostedZone
                Resource:
                  - !Sub arn:aws:route53:::hostedzone/${HostedZoneId}
              - !If
                - HasAdditionalHostedZones
                - Sid: Route53AdditionalHostedZoneOperations
                  Effect: Allow
                  Action:
                    - route53:ListResourceRecordSets
                    - route53:ChangeResourceRecordSets
                    - route53:AssociateVPCWithHostedZone
                    - route53:GetHostedZone
                  Resource: !Ref AdditionalHostedZoneIds
                - !Ref AWS::NoValue
              - Sid: Route53ForO11yPrivateLinkPrivateDNS
                Effect: Allow
                Action:
                  - route53:AssociateVPCWithHostedZone
                Resource:
                  - arn:aws:route53:::hostedzone/*
              - Sid: Route53GetChange
                Effect: Allow
                Action:
                  - route53:GetChange
                Resource: arn:aws:route53:::change/*
              # Private hosted zones are created dynamically.
              # Route53 does not support tag-based conditions, so create remains
              # the isolated wildcard exception for private DNS.
              - Sid: Route53CreatePrivateHostedZone
                Effect: Allow
                Action:
                  - route53:CreateHostedZone
                Resource: "*"
              - Sid: Route53PrivateHostedZoneOperations
                Effect: Allow
                Action:
                  - route53:GetHostedZone
                  - route53:DeleteHostedZone
                  - route53:AssociateVPCWithHostedZone
                  - route53:DisassociateVPCFromHostedZone
                  - route53:ListResourceRecordSets
                  - route53:ListTagsForResource
                  - route53:ChangeTagsForResource
                Resource:
                  - arn:aws:route53:::hostedzone/*
              - Sid: Route53PrivateDNSRecordSetOperations
                Effect: Allow
                Action:
                  - route53:ChangeResourceRecordSets
                Resource:
                  - arn:aws:route53:::hostedzone/*
                Condition:
                  ForAllValues:StringEquals:
                    "route53:ChangeResourceRecordSetsActions":
                      - CREATE
                      - UPSERT
                      - DELETE
                    "route53:ChangeResourceRecordSetsRecordTypes":
                      - CNAME
  TiDBCloudSliRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-sli-assumed-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${ClinicAccountId}:root
            Action: sts:AssumeRole
            Condition:
              StringLike:
                aws:PrincipalArn:
                  - !Sub arn:aws:iam::${ClinicAccountId}:role/*-dataplane-manager
      Policies:
        - PolicyName: sli-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: S3BucketReadOnlyAccess
                Effect: Allow
                Action:
                  - s3:ListBucket
                  - s3:GetBucket*
                Resource:
                  - !Sub arn:aws:s3:::${SLIBucketNamePrefix}*
              - Sid: S3ObjectReadOnlyAccess
                Effect: Allow
                Action:
                  - s3:GetObject
                Resource:
                  - !Sub arn:aws:s3:::${SLIBucketNamePrefix}*/*
  TiDBCloudSliFirehoseRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: tidbcloud-sli-firehose-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: firehose.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: sli-firehose-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: S3Access
                Effect: Allow
                Action:
                  - s3:AbortMultipartUpload
                  - s3:GetBucketLocation
                  - s3:GetObject
                  - s3:ListBucket
                  - s3:ListBucketMultipartUploads
                  - s3:PutObject
                Resource:
                  - arn:aws:s3:::tidbcloud-sli-data*
                  - arn:aws:s3:::tidbcloud-sli-data*/*
              - Sid: CloudWatchLogsAccess
                Effect: Allow
                Action:
                  - logs:PutLogEvents
                  - logs:CreateLogStream
                  - logs:CreateLogGroup
                Resource: arn:aws:logs:*:*:log-group:/aws/kinesisfirehose/tidbcloud-sli*:*
              - Sid: GlueAccess
                Effect: Allow
                Action:
                  - glue:GetTable
                  - glue:GetTableVersion
                  - glue:GetTableVersions
                Resource:
                  - arn:aws:glue:*:*:catalog
                  - arn:aws:glue:*:*:database/tidbcloud-sli*
                  - arn:aws:glue:*:*:table/tidbcloud-sli*/*
