---
AWSTemplateFormatVersion: "2010-09-09"

Description: Handel-created Beanstalk application

Resources:
  #
  # Service role used by Beanstalk
  #
  ServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: {{serviceRoleName}}
      Path: "/services/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - Effect: "Allow"
            Principal: 
              Service: 
              - "elasticbeanstalk.amazonaws.com"
            Action:
            - "sts:AssumeRole"
      {{#if permissionsBoundary}}
      PermissionsBoundary: {{permissionsBoundary}}
      {{/if}}
  ServiceRolePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: {{serviceRoleName}}
      Roles:
      - !Ref ServiceRole
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action:
          - elasticloadbalancing:DescribeInstanceHealth
          - elasticloadbalancing:DescribeLoadBalancers
          - elasticloadbalancing:DescribeTargetHealth
          - ec2:DescribeInstances
          - ec2:DescribeInstanceStatus
          - ec2:GetConsoleOutput
          - ec2:AssociateAddress
          - ec2:DescribeAddresses
          - ec2:DescribeSecurityGroups
          - sqs:GetQueueAttributes
          - sqs:GetQueueUrl
          - autoscaling:DescribeAutoScalingGroups
          - autoscaling:DescribeAutoScalingInstances
          - autoscaling:DescribeScalingActivities
          - autoscaling:DescribeNotificationConfigurations
          Resource:
          - "*"
        - Effect: Allow
          Action:
          - cloudformation:*
          Resource:
          - arn:aws:cloudformation:*:*:stack/awseb-*
          - arn:aws:cloudformation:*:*:stack/eb-*
        - Effect: Allow
          Action:
          - logs:DeleteLogGroup
          Resource:
          - arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk*
        - Effect: Allow
          Action:
          - s3:*
          Resource:
          - arn:aws:s3:::elasticbeanstalk-*
          - arn:aws:s3:::elasticbeanstalk-*/*
        - Effect: Allow
          Action:
          - autoscaling:AttachInstances
          - autoscaling:CreateAutoScalingGroup
          - autoscaling:CreateLaunchConfiguration
          - autoscaling:DeleteLaunchConfiguration
          - autoscaling:DeleteAutoScalingGroup
          - autoscaling:DeleteScheduledAction
          - autoscaling:DescribeAccountLimits
          - autoscaling:DescribeAutoScalingGroups
          - autoscaling:DescribeAutoScalingInstances
          - autoscaling:DescribeLaunchConfigurations
          - autoscaling:DescribeLoadBalancers
          - autoscaling:DescribeNotificationConfigurations
          - autoscaling:DescribeScalingActivities
          - autoscaling:DescribeScheduledActions
          - autoscaling:DetachInstances
          - autoscaling:PutScheduledUpdateGroupAction
          - autoscaling:ResumeProcesses
          - autoscaling:SetDesiredCapacity
          - autoscaling:SuspendProcesses
          - autoscaling:TerminateInstanceInAutoScalingGroup
          - autoscaling:UpdateAutoScalingGroup
          - cloudwatch:PutMetricAlarm
          - ec2:AssociateAddress
          - ec2:AllocateAddress
          - ec2:AuthorizeSecurityGroupEgress
          - ec2:AuthorizeSecurityGroupIngress
          - ec2:CreateSecurityGroup
          - ec2:DeleteSecurityGroup
          - ec2:DescribeAccountAttributes
          - ec2:DescribeAddresses
          - ec2:DescribeImages
          - ec2:DescribeInstances
          - ec2:DescribeKeyPairs
          - ec2:DescribeSecurityGroups
          - ec2:DescribeSnapshots
          - ec2:DescribeSubnets
          - ec2:DescribeVpcs
          - ec2:DisassociateAddress
          - ec2:ReleaseAddress
          - ec2:RevokeSecurityGroupEgress
          - ec2:RevokeSecurityGroupIngress
          - ec2:TerminateInstances
          - ecs:CreateCluster
          - ecs:DeleteCluster
          - ecs:DescribeClusters
          - ecs:RegisterTaskDefinition
          - elasticbeanstalk:*
          - elasticloadbalancing:ApplySecurityGroupsToLoadBalancer
          - elasticloadbalancing:ConfigureHealthCheck
          - elasticloadbalancing:CreateLoadBalancer
          - elasticloadbalancing:DeleteLoadBalancer
          - elasticloadbalancing:DeregisterInstancesFromLoadBalancer
          - elasticloadbalancing:DescribeInstanceHealth
          - elasticloadbalancing:DescribeLoadBalancers
          - elasticloadbalancing:DescribeTargetHealth
          - elasticloadbalancing:RegisterInstancesWithLoadBalancer
          - elasticloadbalancing:DescribeTargetGroups
          - elasticloadbalancing:RegisterTargets
          - elasticloadbalancing:DeregisterTargets
          - iam:ListRoles
          - iam:PassRole
          - logs:CreateLogGroup
          - logs:PutRetentionPolicy
          - rds:DescribeDBEngineVersions
          - rds:DescribeDBInstances
          - rds:DescribeOrderableDBInstanceOptions
          - s3:CopyObject
          - s3:GetObject
          - s3:GetObjectAcl
          - s3:GetObjectMetadata
          - s3:ListBucket
          - s3:listBuckets
          - s3:ListObjects
          - sns:CreateTopic
          - sns:GetTopicAttributes
          - sns:ListSubscriptionsByTopic
          - sns:Subscribe
          - sqs:GetQueueAttributes
          - sqs:GetQueueUrl
          - codebuild:CreateProject
          - codebuild:DeleteProject
          - codebuild:BatchGetBuilds
          - codebuild:StartBuild
          Resource:
          - "*" # This is the role used by the AWS service itself, so it doesn't really need to have a granular resource like those used by our applications 

  # 
  # Role that goes on the instance
  #
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: {{applicationName}}
      Path: "/services/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - Effect: "Allow"
            Principal: 
              Service: 
              - "ec2.amazonaws.com"
            Action:
            - "sts:AssumeRole"
      {{#if permissionsBoundary}}
      PermissionsBoundary: {{permissionsBoundary}}
      {{/if}}
  Policy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: {{applicationName}}
      Roles:
      - !Ref Role
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        {{#each policyStatements}}
        - Effect: {{Effect}}
          Action:
          {{#each Action}}
          - '{{{this}}}'
          {{/each}}
          Resource:
          {{#each Resource}}
          - '{{{this}}}'
          {{/each}}
        {{/each}}
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties: 
      Path: "/services/"
      Roles:
      - !Ref Role

  #
  # Beanstalk application
  # 
  Application:
    Type: AWS::ElasticBeanstalk::Application
    Properties:
      ApplicationName: {{applicationName}}
      Description: Handel-created application for {{applicationName}}
  ApplicationVersion:
    Type: AWS::ElasticBeanstalk::ApplicationVersion
    Properties:
      ApplicationName: !Ref Application
      Description: {{description}}
      SourceBundle:
        S3Bucket: {{applicationVersionBucket}}
        S3Key: {{applicationVersionKey}}
  ConfigurationTemplate:
    Type: AWS::ElasticBeanstalk::ConfigurationTemplate
    Properties:
      ApplicationName: !Ref Application
      Description: {{description}}
      OptionSettings:
      - Namespace: aws:autoscaling:launchconfiguration
        OptionName: IamInstanceProfile
        Value: !Ref InstanceProfile
      {{#each optionSettings}}
      - Namespace: "{{namespace}}"
        OptionName: {{optionName}}
        Value: "{{value}}"
      {{/each}}
      SolutionStackName: {{solutionStack}}
  Environment:
    Type: "AWS::ElasticBeanstalk::Environment"
    Properties:
      ApplicationName: !Ref Application
      Description: Handel-created environment for {{applicationName}}
      TemplateName: !Ref ConfigurationTemplate
      VersionLabel: !Ref ApplicationVersion
      Tags:
      {{#if tags}}
      {{#each tags}}
      - Key: {{@key}}
        Value: {{this}}
      {{/each}}
      {{/if}}
      - Key: Name
        Value: {{applicationName}}
