# This is a very minimal list of permissions that the console needs to operate
# cloud backend provisioning and deployments.
AWSTemplateFormatVersion: "2010-09-09"
Description: "Ownstak IAM Roles for Lambda and ECS"

Parameters:
  Principals:
    Type: CommaDelimitedList
    Description: "AWS principal (ARNs) that can assume the OwnstakCloudCredentialsRole. Do not change unless you want to use a non-production Ownstak instance."
    Default: "arn:aws:iam::452764013502:role/OwnstakConsoleProd"

Resources:
  ExternalIdSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: ownstak/external-id
      Description: "External ID for Ownstak cross-account access"
      GenerateSecretString:
        SecretStringTemplate: '{"ExternalId":""}'
        GenerateStringKey: "ExternalId"
        PasswordLength: 32
        ExcludePunctuation: true

  OwnstakCloudCredentialsPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: ownstak-cloud-credentials-policy
      Description: Policy for Ownstak services
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: ACM
            Effect: Allow
            Action:
              - acm:ListCertificates
              - acm:RequestCertificate
              - acm:DeleteCertificate
              - acm:DescribeCertificate
              - acm:AddTagsToCertificate
            Resource: "*"
          - Sid: EC2
            Effect: Allow
            Action:
              - ec2:AuthorizeSecurityGroupIngress
              - ec2:CreateSecurityGroup
              - ec2:CreateTags
              - ec2:DeleteSecurityGroup
              - ec2:DescribeAccountAttributes
              - ec2:DescribeInstances # for single instance mode
              - ec2:DescribeSecurityGroups
              - ec2:DescribeSubnets
              - ec2:DescribeVpcs
              - ec2:RunInstances # for single instance mode
              - ec2:TerminateInstances # for single instance mode
            Resource: "*"
          - Sid: ElasticLoadBalancing
            Effect: Allow
            Action:
              - elasticloadbalancing:AddTags
              - elasticloadbalancing:CreateListener
              - elasticloadbalancing:CreateLoadBalancer
              - elasticloadbalancing:CreateTargetGroup
              - elasticloadbalancing:DeleteLoadBalancer
              - elasticloadbalancing:DeleteTargetGroup
              - elasticloadbalancing:DescribeLoadBalancers
              - elasticloadbalancing:DescribeListeners
              - elasticloadbalancing:DescribeTargetGroups
              - elasticloadbalancing:ModifyTargetGroupAttributes
            Resource: "*"
          - Sid: ECSRead
            Effect: Allow
            Action:
              - ecs:DescribeClusters
              - ecs:DescribeServices
              - ecs:DescribeTaskDefinition
              - ecs:ListServices
              - ecs:ListTasks
              - ecs:ListTaskDefinitions
            Resource: "*"
          # For some reason this permission only applies to a wildcard resource.
          - Sid: ECSGlobal
            Effect: Allow
            Action:
              - ecs:DeregisterTaskDefinition
            Resource: "*"
          - Sid: ECSWrite
            Effect: Allow
            Action:
              - ecs:CreateCluster
              - ecs:CreateService
              - ecs:DeleteCluster
              - ecs:DeleteService
              - ecs:RegisterTaskDefinition
              - ecs:StopTask
              - ecs:TagResource
              - ecs:UpdateService
            Resource:
              - "arn:aws:ecs:*:*:*/ownstak-*"
          - Sid: ECSCleanup
            Effect: Allow
            Action:
              - ecs:DeregisterTaskDefinition
            Resource: "arn:aws:ecs:*:*:task-definition/ownstak-*:*"
          - Sid: ApplicationAutoScaling
            Effect: Allow
            Action:
              - application-autoscaling:DescribeScalableTargets
              - application-autoscaling:RegisterScalableTarget
              - application-autoscaling:DeregisterScalableTarget
              - application-autoscaling:PutScalingPolicy
              - application-autoscaling:DeleteScalingPolicy
            Resource:
              # Scalable targets have random resource ID, e.g.: arn:aws:application-autoscaling:us-east-1:012345678901:scalable-target/0ec59ef2a3c7a9d14478a017360c3cdd55de
              - "arn:aws:application-autoscaling:*:*:scalable-target/*"
              - "arn:aws:application-autoscaling:*:*:scalingpolicy/*"
          - Sid: CloudWatchLogsRead
            Effect: Allow
            Action:
              - logs:DescribeLogGroups
            Resource: "*"
          - Sid: CloudWatchLogsWrite
            Effect: Allow
            Action:
              - logs:CreateLogGroup
              - logs:DeleteLogGroup
              - logs:DescribeLogGroups
              - logs:GetLogEvents
              - logs:GetLogRecord
              - logs:ListTagsLogGroup
              - logs:PutRetentionPolicy
              - logs:TagLogGroup
              - logs:FilterLogEvents
            Resource:
              - "arn:aws:logs:*:*:log-group:/aws/lambda/ownstak-*"
              - "arn:aws:logs:*:*:log-group:/aws/lambda/ownstak-*/log-stream:*"
              - "arn:aws:logs:*:*:log-group:/ecs/ownstak-*"
              - "arn:aws:logs:*:*:log-group:/ecs/ownstak-*/log-stream:*"
          - Sid: LambdaGlobal
            Effect: Allow
            Action:
              - lambda:ListFunctions
            Resource: "*"
          - Sid: Lambda
            Effect: Allow
            Action:
              - lambda:CreateAlias
              - lambda:CreateFunction
              - lambda:DeleteAlias
              - lambda:DeleteFunction
              - lambda:GetAlias
              - lambda:GetFunction
              - lambda:GetFunctionConfiguration
              - lambda:InvokeFunction
              - lambda:ListAliases
              - lambda:ListTags
              - lambda:PublishVersion
              - lambda:TagResource
              - lambda:UpdateAlias
              - lambda:UpdateFunctionCode
              - lambda:UpdateFunctionConfiguration
            Resource:
              - "arn:aws:lambda:*:*:function:ownstak-*"
              - "arn:aws:lambda:*:*:function:ownstak-*:*"
          - Sid: IAMALB
            Effect: Allow
            Action:
              - iam:CreateServiceLinkedRole
            Resource: "arn:aws:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing"
          - Sid: IAMRead
            Effect: Allow
            Action:
              - iam:GetRole
              - iam:GetInstanceProfile
            Resource: "*"
          - Sid: IAMAssign
            Effect: Allow
            Action:
              - iam:passRole
            Resource:
              - "arn:aws:iam::*:role/ownstak-lambda-execution-role"
              - "arn:aws:iam::*:role/ownstak-ecs-execution-role"
              - "arn:aws:iam::*:role/ownstak-ecs-task-role"
              - "arn:aws:iam::*:role/ownstak-ec2-instance-profile-role" # for single instance mode
          - Sid: S3
            Effect: Allow
            Action:
              - s3:CreateBucket
              - s3:DeleteBucket
              - s3:DeleteObject
              - s3:GetObject
              - s3:GetObjectAttributes
              - s3:ListBucket
              - s3:PutBucketPolicy
              - s3:PutBucketPublicAccessBlock
              - s3:PutObject
            Resource: "arn:aws:s3:::ownstak-*"

  OwnstakCloudCredentialsRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: OwnstakCloudCredentialsRole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref Principals
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Sub '{{resolve:secretsmanager:${ExternalIdSecret}:SecretString:ExternalId}}'
      ManagedPolicyArns:
        - !Ref OwnstakCloudCredentialsPolicy

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ownstak-lambda-execution-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: S3Access
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                Resource:
                  - "arn:aws:s3:::ownstak-*"

  ECSExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ownstak-ecs-execution-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

  ECSTaskRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ownstak-ecs-task-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
      Policies:
        - PolicyName: LambdaProxyPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - lambda:InvokeFunction
                Resource: "arn:aws:lambda:*:*:function:ownstak-*"

  Ec2InstanceProfileRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ownstak-ec2-instance-profile-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Policies:
        - PolicyName: LambdaProxyPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - lambda:InvokeFunction
                Resource: "arn:aws:lambda:*:*:function:ownstak-*"

  Ec2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: ownstak-ec2-instance-profile
      Roles:
        - !Ref Ec2InstanceProfileRole
