AWSTemplateFormatVersion: '2010-09-09'
Description: Axiom AWS Integrations with all supported options

Parameters:
  IdentityCenterAccessManagement:
    Type: String
    Default: 'true'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to include permissions for Axiom's Access
      management integration for AWS Identity Center.
  ExternalId:
    Description: External ID for the Axiom role
    Type: String
  IntegrationTypes:
    Type: String
    Description: 'A comma separated list indicating on the types of the integration.
      Can chose from: Observability,AccessManagement'
    Default: Observability,AccessManagement
  IAMRoleName:
    Description: Customize the name of IAM role for your AWS integration
    Type: String
    Default: AxiomIntegrationRole
  AxiomAWSAccountId:
    Description: The ARN of the principal allowed to assume this role. By default,
      it's the root account of Axiom AWS account. If using axiom-runner, replace
      this with the runner's role ARN.
    Type: String
    Default: arn:aws:iam::172796517899:root
  EC2RemoteConnect:
    Type: String
    Default: 'true'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to include EC2 Remote Connect permissions,
      including log reading.
  S3Collection:
    Type: String
    Default: 'true'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to enable S3 resource collection for
      granular access support.
  S3ResourcePrefixes:
    Type: String
    Default: '*'
    Description: Comma-separated list of S3 bucket prefixes to collect. Use '*' for
      all buckets (default).
  AWSCloudTrailSessionAudit:
    Type: String
    Default: 'true'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to enable AWS CloudTrail Session audit.
  IAMUsersImpersonation:
    Type: String
    Default: 'false'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to enable IAM Users impersonation support
      for temporary security credentials.
  WhitelistedIPs:
    Type: String
    Default: ''
    Description: Optional comma-separated list of IP addresses/CIDR blocks to
      restrict IAM user impersonation access (e.g.,
      '10.0.0.0/8,192.168.1.0/24'). Leave empty to allow access from any IP.
  EnableNATIPRestrictions:
    Type: String
    Default: 'false'
    AllowedValues:
      - 'true'
      - 'false'
    Description: Set this value to "true" to enable NAT IP restrictions for role
      assumption. When enabled, uses pre-populated IPs for production accounts.

Conditions:
  AccessManagementPermissions: !Or
    - !Or
      - !Equals
        - !Select
          - 0
          - !Split
            - ','
            - !Sub
              - ${Integrations},,,,,
              - Integrations: !Join
                  - ','
                  - !Split
                    - ','
                    - !Ref IntegrationTypes
        - AccessManagement
      - !Equals
        - !Select
          - 1
          - !Split
            - ','
            - !Sub
              - ${Integrations},,,,,
              - Integrations: !Join
                  - ','
                  - !Split
                    - ','
                    - !Ref IntegrationTypes
        - AccessManagement
    - !Equals
      - !Ref IdentityCenterAccessManagement
      - 'true'
  InstallEC2RemoteConnect: !Equals
    - !Ref EC2RemoteConnect
    - 'true'
  InstallS3Collection: !Equals
    - !Ref S3Collection
    - 'true'
  InstallCloudTrailLookupEvents: !Equals
    - !Ref AWSCloudTrailSessionAudit
    - 'true'
  InstallIAMUsersImpersonation: !Equals
    - !Ref IAMUsersImpersonation
    - 'true'
  HasWhitelistedIPs: !Not
    - !Equals
      - !Ref WhitelistedIPs
      - ''
  EnableIPRestrictions: !Equals
    - !Ref EnableNATIPRestrictions
    - 'true'
  HasNATIPRestrictions: !And
    - !Condition EnableIPRestrictions
    - !Not
      - !Equals
        - !Ref WhitelistedIPs
        - ''

Resources:
  AxiomIAMUsersImpersonationPolicy:
    Type: AWS::IAM::ManagedPolicy
    Condition: InstallIAMUsersImpersonation
    Properties:
      ManagedPolicyName: !Sub ${IAMRoleName}-ImpersonationPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - sts:AssumeRole
              - iam:ListUsers
              - iam:GetUser
              - iam:ListUserPolicies
              - iam:ListAttachedUserPolicies
              - iam:GetUserPolicy
              - iam:SimulatePrincipalPolicy
            Condition: !If
              - HasWhitelistedIPs
              - IpAddress:
                  aws:SourceIp: !Split
                    - ','
                    - !Ref WhitelistedIPs
              - !Ref AWS::NoValue

  S3CollectionPolicy:
    Type: AWS::IAM::Policy
    Condition: InstallS3Collection
    Properties:
      PolicyName: !Sub ${IAMRoleName}-S3CollectionPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - s3:GetBucketLocation
              - s3:GetBucketTagging
              - s3:GetBucketVersioning
              - s3:GetBucketWebsite
              - s3:GetBucketLogging
              - s3:GetBucketNotification
              - s3:GetBucketPolicy
              - s3:GetBucketAcl
              - s3:GetBucketCORS
              - s3:GetBucketLifecycle
              - s3:GetBucketReplication
              - s3:GetBucketEncryption
              - s3:GetBucketPublicAccessBlock
              - s3:ListBucket
              - s3:ListBucketVersions
            Condition:
              StringLike:
                s3:prefix: !Split
                  - ','
                  - !Ref S3ResourcePrefixes
      Roles:
        - !Ref AxiomIntegrationRole

  CloudTrailLookupEventsPolicy:
    Type: AWS::IAM::Policy
    Condition: InstallCloudTrailLookupEvents
    Properties:
      PolicyName: !Sub ${IAMRoleName}-CloudTrailPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - cloudtrail:LookupEvents
      Roles:
        - !Ref AxiomIntegrationRole

  AxiomBrokerAdminPolicy:
    Type: AWS::IAM::ManagedPolicy
    Condition: InstallIAMUsersImpersonation
    Properties:
      ManagedPolicyName: !Sub ${IAMRoleName}-BrokerAdminPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - '*'

  AxiomBrokerPermissionsBoundary:
    Type: AWS::IAM::ManagedPolicy
    Condition: InstallIAMUsersImpersonation
    Properties:
      ManagedPolicyName: !Sub ${IAMRoleName}-PermissionsBoundary
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: DenyIAMUserAndKeyManagement
            Effect: Deny
            Action:
              - iam:CreateUser
              - iam:CreateAccessKey
              - iam:CreateLoginProfile
              - iam:CreateServiceLinkedRole
              - iam:CreatePolicy
              - iam:CreatePolicyVersion
              - iam:DeleteUser
              - iam:DeleteRole
              - iam:DeletePolicy
              - iam:DeletePolicyVersion
              - iam:DetachRolePolicy
              - iam:PutRolePolicy
              - iam:DeleteRolePolicy
            Resource: '*'
          - Sid: AllowRest
            Effect: Allow
            Action:
              - '*'
            Resource: '*'

  AxiomIntegrationRole:
    Type: AWS::IAM::Role
    Metadata:
      cfn-lint:
        config:
          ignore_checks:
            - E3002
            - E3003
            - EIAMPolicyActionWildcard
            - EIAMPolicyWildcardResource
    Properties:
      PermissionsBoundary: !If
        - InstallIAMUsersImpersonation
        - !Ref AxiomBrokerPermissionsBoundary
        - !Ref AWS::NoValue
      MaxSessionDuration: 43200
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref AxiomAWSAccountId
                - !Sub arn:aws:iam::${AWS::AccountId}:root
            Action:
              - sts:AssumeRole
            Condition: !If
              - HasNATIPRestrictions
              - And:
                  StringEquals:
                    sts:ExternalId: !Ref ExternalId
                  IpAddress:
                    aws:SourceIp: !Split
                      - ','
                      - !Ref WhitelistedIPs
              - StringEquals:
                  sts:ExternalId: !Ref ExternalId
          - Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
            Action:
              - sts:TagSession
      Path: /
      RoleName: !Ref IAMRoleName
      ManagedPolicyArns:
        - !Sub arn:${AWS::Partition}:iam::aws:policy/SecurityAudit
        - !If
          - InstallIAMUsersImpersonation
          - !Ref AxiomBrokerAdminPolicy
          - !Ref AWS::NoValue
        - !If
          - InstallIAMUsersImpersonation
          - !Ref AxiomIAMUsersImpersonationPolicy
          - !Ref AWS::NoValue
      Policies:
        - PolicyName: AxiomAWSIntegrationPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Resource: '*'
                Action:
                  - apigateway:GET*
                  - iam:List*
                  - lambda:List*
                  - iam:GenerateServiceLastAccessedDetails
                  - iam:GetServiceLastAccessedDetails
                  - s3:GetBucket*
                  - s3:GetEncryptionConfiguration
                  - s3:List*
                  - dynamodb:ListTables
                  - dynamodb:Scan
                  - dynamodb:DescribeTable
                  - dynamodb:ListTagsOfResource
                  - kms:ListKeys
                  - ec2:Describe*
                  - iam:Get*
                  - iam:Describe*
                  - iam:GenerateOrganizationsAccessReport
                  - rds:Describe*
                  - organizations:Describe*
                  - organizations:List*
                  - redshift:Describe*
                  - elasticloadbalancing:Describe*
                  - secretsmanager:GetResourcePolicy
                  - secretsmanager:ListSecrets
                  - secretsmanager:DescribeSecret
                  - ecr:DescribeRegistry
                  - ecr:DescribeRepositories
                  - ecr:GetRepositoryPolicy
                  - eks:List*
                  - ecs:List*
                  - kms:List*
                  - sso:List*
                  - identitystore:Describe*
                  - identitystore:List*
                  - identitystore:IsMemberInGroups
                  - sso:Get*
                  - sso:Describe*
                  - logs:GetL*
                  - ssm:DescribeI*
                  - ssm:DescribeS*
  AxiomAccessManagementPolicy:
    Type: AWS::IAM::Policy
    Condition: AccessManagementPermissions
    Properties:
      PolicyName: AxiomAWSAccessManagementIntegrationPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - sso:PutInlinePolicyToPermissionSet
              - sso:DeleteAccountAssignment
              - sso:CreateAccountAssignment
              - sso:DeleteInlinePolicyFromPermissionSet
              - sso:DeletePermissionSet
              - sso:CreatePermissionSet
              - sso:ProvisionPermissionSet
              - sso:UpdatePermissionSet
              - sso:PutPermissionsPolicy
              - sso:PutPermissionsBoundaryToPermissionSet
          - Sid: IAMSAMLProviderCreationAction
            Effect: Allow
            Resource:
              - !Sub arn:${AWS::Partition}:iam::*:saml-provider/AWSSSO_*
            Action:
              - iam:CreateSAMLProvider
              - iam:UpdateSAMLProvider
            Condition:
              StringEquals:
                aws:PrincipalOrgMasterAccountId: ${aws:PrincipalAccount}
          - Sid: IAMRoleProvisioningActions
            Effect: Allow
            Resource:
              - !Sub arn:${AWS::Partition}:iam::*:role/aws-reserved/sso.amazonaws.com/*
            Action:
              - iam:AttachRolePolicy
              - iam:CreateRole
              - iam:DeleteRolePermissionsBoundary
              - iam:PutRolePermissionsBoundary
              - iam:PutRolePolicy
              - iam:UpdateRole
              - iam:UpdateRoleDescription
              - iam:UpdateAssumeRolePolicy
            Condition:
              StringEquals:
                aws:PrincipalOrgMasterAccountId: ${aws:PrincipalAccount}
      Roles:
        - !Ref AxiomIntegrationRole

  EC2RemoteConnectPolicy:
    Type: AWS::IAM::Policy
    Condition: InstallEC2RemoteConnect
    Properties:
      PolicyName: AxiomEC2RemoteConnectPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Resource: '*'
            Action:
              - ec2:Describe*
              - ssm:DescribeI*
              - ssm:DescribeS*
              - logs:DescribeLogGroups
              - logs:DescribeLogStreams
              - logs:GetLogEvents
          - Effect: Allow
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::*
              - !Sub arn:${AWS::Partition}:s3:::*/AWSLogs/${AWS::AccountId}/SSMSessionManager/*
            Action:
              - s3:GetObject
              - s3:GetBucketLocation
      Roles:
        - !Ref AxiomIntegrationRole

Outputs:
  RoleARN:
    Description: ARN of the created IAM Role for Axiom AWS Integration
    Value: !GetAtt AxiomIntegrationRole.Arn
  ExternalId:
    Description: External ID for the Axiom role
    Value: !Ref ExternalId

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Required
        Parameters:
          - ExternalId
          - IAMRoleName
      - Label:
          default: Optional
        Parameters:
          - IdentityCenterAccessManagement
          - IntegrationTypes
          - EC2RemoteConnect
          - S3Collection
          - S3ResourcePrefixes
          - AWSCloudTrailSessionAudit
          - AxiomAWSAccountId
          - IAMUsersImpersonation
          - WhitelistedIPs
          - EnableNATIPRestrictions