#-----------------------------------------------------------------------#

# Stack Description:
# This template provides a base serverless framework template containing
# commonly used sections and examples.

# Stack Purpose:
# - Create example lambda and roles
# - Create example bucket

# Stack Targets:
# - Global stack

# Cross-stack Dependencies:
# - Requires VPC setup deployed elsewhere

#-----------------------------------------------------------------------#

# Service name used as CloudFormationn stack name, must be unique
service: ${self:custom.ServiceName}

provider:
  name: aws
  runtime: python3.6 # Lambda environment
  profile: ${opt:profile, 'default'} 
  region: ${opt:region, 'eu-west-1'}
  
  # Stage and profile variable are the same for cross account deployments:
  stage: ${self:provider.profile} 
  
  # Deployment bucket required for uniform, neat deployments
  deploymentBucket:
    name:  ${self:custom.ServerlessBucketName}

  # If API Gateway is used, enable logging:
  logs:
    restApi: true # Required to enable API Gateway logging
  endpointType: PRIVATE # API deployed in VPC
  
  # If API Keys are required
  # Change as required
  apiKeys:
    - free:
      - ${self:custom.ServiceName}-${self:provider.stage} # Randomly generated key
  usagePlan: 
    - free:
        quota:
          limit: 5000
          offset: 2
          period: MONTH
        throttle:
          burstLimit: 200
          rateLimit: 100
  resourcePolicy:
    - Effect: Allow
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
    - Effect: Deny
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
      # Comment the condition section out when testing invocations on the console
      Condition:
        NotIpAddress:
          aws:SourceIp:
            - 'xx.xx.xx.xxx/32' # Specify allowed IP addresses

  # If lambda is deployed in a VPC:
  # Verify that networking is allowed
  # Uses CloudFormation export values
  vpc:
    securityGroupIds:
      - ${cf:private-vpc-1-lambda-${self:provider.profile}.LambdaSecurityGroup1}
    subnetIds:
      - ${cf:private-vpc-1-${self:provider.profile}.CustomSubnet1}
      - ${cf:private-vpc-1-${self:provider.profile}.CustomSubnet2}
  
  # Add Environment variables below. Values are declared in the Custom section
  # Variables can be accessed and used by lambda function
  environment:
    EXAMPLE_ENV_VARIABLE: ${self:custom.ExampleEnvironmentVariable}
    

# List plugins used in Serverless template below      
# Plugins should be added to CodeCommit repository when pushing code for CICD deployments
plugins:
  - serverless-pseudo-parameters

# Store variables in the custom section that can be re-used in any other sections ofthe template,
# allowing for CICD deployments, template reproducibility etc.
custom:
  
  # Bucket used to store serverless deployment artifacts
  ServerlessBucketName: ${cf:serverless-framework-${self:provider.profile}-${self:provider.region}.ServerlessBucket}

  # Change as required
  ServiceName: 'serverless-deployment-example-template'

  # Define custom variables used as environmental variables or referenced 
  # Variables defined below are used as example
  ExampleEnvironmentVariable: example-variable
  S3BucketName: example-results-${self:provider.profile}-${self:provider.stage}-${self:provider.region}
  S3BucketVersioningConfiguration: Suspended #Enabled/Suspended

# Configure lambda functions. Multiple functions can be created per serverless template:
functions:
  lambda:  example-name # Function name - can be changed
    handler: handler.example # Function handler(filename) and definition
    timeout: 20 # seconds
    role: LambdaRole # Define role below or reference existing role
    
    # Example error queue (deployed elsewhere):
    onError: arn:aws:sns:${self:provider.region}:#{AWS::AccountId}:dead-letter-queue-${self:provider.profile} 
    
    # Package layers if required:
    layers:
     - !Sub '${cf:python36-pandas-layer-${self:provider.profile}.PandasLayerExport}'

    # Define events to trigger lambda below
    events:
    # Refer to https://serverless.com/framework/docs/providers/aws/events/ for available events
    # API gateway example:   
      - http:
          path: example-path
          method: get # get/put/post
          private: true # Required when using API keys
    # Scheduled event example:
      - schedule: 
          rate: cron(30 5 * * ? *)


# Define custome resources below
# Use Cloudformation syntax  
resources:
  Resources:
    # Example lambda role:
    LambdaRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:custom.ServiceName}-${self:provider.stage}-role
        # Define assume role policy in JSON or YAML format below
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            -
              Effect: Allow
              Principal:
                Service:
                  - 'lambda.amazonaws.com'
              Action:
                - 'sts:AssumeRole'
        ManagedPolicyArns:
          # AWS managed policies:
          - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
          - 'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole' # Required for VPC deployments
          # Customer managed policies:
          - 'arn:aws:iam::#{AWS::AccountId}:policy/rain-lambda-sns-dlq-policy'
        # Inline policy:
        Policies:
          -
            PolicyName: ${self:custom.ServiceName}-${self:provider.stage}-policy
            # Define policy in JSON or YAML format below
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                # Example S3 access policy
                -
                  Effect: Allow
                  Action: 
                    - 's3:List*'
                    - 's3:Get*' 
                    - 's3:Put*' 
                  Resource: 
                    - 'arn:aws:s3:::${self:custom.ExampleBucketName}'
                    - 'arn:aws:s3:::${self:custom.ExampleBucketName}/*'
                # Example Athena access policy
                -
                  Effect: Allow
                  Action: 
                    - 'athena:GetQueryExecution'
                    - 'athena:GetQueryResults'
                    - 'athena:StartQueryExecution' 
                  Resource: 
                    - '*' 

    # Example S3 bucket:
    S3Bucket: 
      Type: AWS::S3::Bucket 
      # Define dependencies if any. 
      DependsOn: 
        - LambdaRole
      Properties:
        BucketName: ${self:custom.ExampleBucketName} # Reference variable defined in custom section:
        VersioningConfiguration:
          Status: ${self:custom.S3BucketVersioningConfiguration} # Reference variable defined in custom section:
        PublicAccessBlockConfiguration: 
          BlockPublicAcls: True
          BlockPublicPolicy: True
          IgnorePublicAcls: True
          RestrictPublicBuckets: True
        LifecycleConfiguration:
          Rules:
            - Id: IntelligentTieringTransition
              Status: Enabled
              Transitions:
                - TransitionInDays: 1
                  StorageClass: INTELLIGENT_TIERING
        BucketEncryption:
          ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                SSEAlgorithm: AES256

  # Output section can be defined as follow
  # Mostly used if you want to reference dynamic variables that only receive 
  # values upon template deployment (eg. security group id)
  Outputs:
    S3Bucket:
      Value:
        Ref: S3Bucket

#-----------------------------------------------------------------------#