Editor/Resources/CloudFormation/scenario3_mrf_queue/cloudformation.yml [12:556]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameters:
  ApiGatewayStageNameParameter:
    Type: String
    Default: v1
    Description: Name of the Api Gateway stage

  BuildNameParameter:
    Type: String
    Default: Sample GameLift Build
    Description: Name of the build

  BuildOperatingSystemParameter:
    Type: String
    Description: Operating system of the build

  BuildS3BucketParameter:
    Type: String
    Description: Bucket that stores the server build

  BuildS3KeyParameter:
    Type: String
    Description: Key of the server build in the S3 bucket

  BuildVersionParameter:
    Type: String
    Description: Version number of the build

  FleetDescriptionParameter:
    Type: String
    Default: Deployed by the Amazon GameLift Plug-in for Unity.
    Description: Description of the fleet

  FleetNameParameter:
    Type: String
    Default: Sample GameLift Fleet
    Description: Name of the fleet

  FleetTcpFromPortParameter:
    Type: Number
    Default: 33430
    Description: Starting port number for TCP ports to be opened

  FleetTcpToPortParameter:
    Type: Number
    Default: 33440
    Description: Ending port number for TCP ports to be opened

  FleetUdpFromPortParameter:
    Type: Number
    Default: 33430
    Description: Starting port number for UDP ports to be opened

  FleetUdpToPortParameter:
    Type: Number
    Default: 33440
    Description: Ending port number for UDP ports to be opened

  GameNameParameter:
    Type: String
    Default: MyGame
    Description: Game name to prepend before resource names
    MaxLength: 12

  LambdaZipS3BucketParameter:
    Type: String
    Description: S3 bucket that stores the lambda function zip

  LambdaZipS3KeyParameter:
    Type: String
    Description: S3 key that stores the lambda function zip

  LaunchParametersParameter:
    Type: String
    Description: Parameters used to launch the game server process

  LaunchPathParameter:
    Type: String
    Description: Location of the game server executable in the build

  MatchmakingTimeoutInSecondsParamter:
    Type: Number
    Default: 60
    Description: Time in seconds before matchmaker times out to wait for enough players to create game session placement

  MaxTransactionsPerFiveMinutesPerIpParameter:
    Type: Number
    Default: 100
    MaxValue: 20000000
    MinValue: 100

  NumPlayersPerGameParameter:
    Type: Number
    Default: 2
    Description: Number of players per game session

  QueueTimeoutInSecondsParameter:
    Type: Number
    Default: 60
    Description: Time in seconds before game session placement times out to place players on a server

Resources:
  ApiGatewayCloudWatchRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"

  Account:
    Type: "AWS::ApiGateway::Account"
    Properties:
      CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchRole.Arn

  GameRequestLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}GameRequestLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:PutItem"
                  - "dynamodb:UpdateItem"
                  - "dynamodb:GetItem"
                  - "dynamodb:DeleteItem"
                  - "dynamodb:Query"
                  - "sqs:SendMessage"
                Resource: "*"

  GameSessionEventHandlerLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}GameSessionEventHandlerLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:PutItem"
                Resource: "*"

  GameSessionPlacementTable:
    Type: "AWS::DynamoDB::Table"
    Properties:
      AttributeDefinitions:
        - AttributeName: PlacementId
          AttributeType: S
      KeySchema:
        - AttributeName: PlacementId
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      TableName: !Sub ${GameNameParameter}GameSessionPlacementTable
      TimeToLiveSpecification:
        AttributeName: ExpirationTime
        Enabled: true

  MatchmakingRequestTable:
    Type: "AWS::DynamoDB::Table"
    Properties:
      AttributeDefinitions:
        - AttributeName: PlayerId
          AttributeType: S
        - AttributeName: StartTime
          AttributeType: "N"
      KeySchema:
        - AttributeName: PlayerId
          KeyType: HASH
        - AttributeName: StartTime
          KeyType: RANGE
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      TableName: !Sub ${GameNameParameter}MatchmakingRequestTable
      TimeToLiveSpecification:
        AttributeName: ExpirationTime
        Enabled: true

  RestApi:
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: !Sub ${GameNameParameter}RestApi

  ResultsRequestLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}ResultsRequestLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:GetItem"
                  - "dynamodb:Query"
                Resource: "*"

  SimpleMatchmakerLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}SimpleMatchmakerLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:UpdateItem"
                  - "gamelift:StartGameSessionPlacement"
                  - "sqs:ReceiveMessage"
                  - "sqs:DeleteMessage"
                  - "sqs:GetQueueAttributes"
                Resource: "*"

  UserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      AutoVerifiedAttributes:
        - email
      EmailConfiguration:
        EmailSendingAccount: COGNITO_DEFAULT
      EmailVerificationMessage: "Please verify your email to complete account registration for GameLift Sample Game. Confirmation Code {####}."
      EmailVerificationSubject: GameLift Sample Game Account Verification
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          RequireUppercase: true
      Schema:
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
      UserPoolName: !Sub ${GameNameParameter}UserPool
      UsernameAttributes:
        - email

  BuildAccessRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - cloudformation.amazonaws.com
                - gamelift.amazonaws.com
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}BuildS3AccessPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:GetObjectVersion"
                Resource:
                  - "Fn::Sub": "arn:aws:s3:::${BuildS3BucketParameter}/${BuildS3KeyParameter}"
      RoleName: !Sub ${GameNameParameter}BuildIAMRole

  GameRequestApiResource:
    Type: "AWS::ApiGateway::Resource"
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: start_game
      RestApiId: !Ref RestApi

  ResultsRequestApiResource:
    Type: "AWS::ApiGateway::Resource"
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: get_game_connection
      RestApiId: !Ref RestApi

  SimpleMatchMakerTicketQueue:
    Type: "AWS::SQS::Queue"
    Properties:
      FifoQueue: true
      MessageRetentionPeriod: !Ref MatchmakingTimeoutInSecondsParamter
      QueueName: !Sub ${GameNameParameter}SimpleMatchMakerTicketQueue.fifo

  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      AccessTokenValidity: 1
      ClientName: !Sub ${GameNameParameter}UserPoolClient
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      GenerateSecret: false
      IdTokenValidity: 1
      PreventUserExistenceErrors: ENABLED
      ReadAttributes:
        - email
        - preferred_username
      RefreshTokenValidity: 30
      SupportedIdentityProviders:
        - COGNITO
      UserPoolId: !Ref UserPool

  WebACL:
    Type: "AWS::WAFv2::WebACL"
    DependsOn:
      - ApiDeployment
    Properties:
      DefaultAction:
        Allow:
          {}
      Description: !Sub "WebACL for game: ${GameNameParameter}"
      Name: !Sub ${GameNameParameter}WebACL
      Rules:
        - Name: !Sub ${GameNameParameter}WebACLPerIpThrottleRule
          Action:
            Block:
              {}
          Priority: 0
          Statement:
            RateBasedStatement:
              AggregateKeyType: IP
              Limit: !Ref MaxTransactionsPerFiveMinutesPerIpParameter
          VisibilityConfig:
            CloudWatchMetricsEnabled: true
            MetricName: !Sub ${GameNameParameter}WebACLPerIpThrottleRuleMetrics
            SampledRequestsEnabled: true
      Scope: REGIONAL
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: !Sub ${GameNameParameter}WebACLMetrics
        SampledRequestsEnabled: true

  ApiDeployment:
    Type: "AWS::ApiGateway::Deployment"
    DependsOn:
      - GameRequestApiMethod
      - ResultsRequestApiMethod
    Properties:
      RestApiId: !Ref RestApi
      StageDescription:
        DataTraceEnabled: true
        LoggingLevel: INFO
        MetricsEnabled: true
      StageName: !Ref ApiGatewayStageNameParameter

  Authorizer:
    Type: "AWS::ApiGateway::Authorizer"
    Properties:
      IdentitySource: method.request.header.Auth
      Name: CognitoAuthorizer
      ProviderARNs:
        - "Fn::GetAtt":
            - UserPool
            - Arn
      RestApiId: !Ref RestApi
      Type: COGNITO_USER_POOLS

  GameSessionEventHandlerLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
      FunctionName: !Sub ${GameNameParameter}GameSessionEventHandlerLambda
      Handler: game_session_event_handler.handler
      MemorySize: 128
      Role: !GetAtt GameSessionEventHandlerLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  GameRequestApiMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId: !Ref Authorizer
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GameRequestLambdaFunction.Arn}/invocations"
      OperationName: GameRequest
      ResourceId: !Ref GameRequestApiResource
      RestApiId: !Ref RestApi

  GameSessionEventTopic:
    Type: "AWS::SNS::Topic"
    Properties:
      Subscription:
        - Endpoint: !GetAtt GameSessionEventHandlerLambdaFunction.Arn
          Protocol: lambda
      TopicName: !Sub ${GameNameParameter}GameSessionEventTopic

  ResultsRequestApiMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId: !Ref Authorizer
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ResultsRequestLambdaFunction.Arn}/invocations"
      OperationName: ResultsRequest
      ResourceId: !Ref ResultsRequestApiResource
      RestApiId: !Ref RestApi

  ResultsRequestLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
          MatchmakingRequestTableName: !Ref MatchmakingRequestTable
      FunctionName: !Sub ${GameNameParameter}ResultsRequestLambda
      Handler: results_request.handler
      MemorySize: 128
      Role: !GetAtt ResultsRequestLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  WebACLAssociation:
    Type: "AWS::WAFv2::WebACLAssociation"
    DependsOn:
      - ApiDeployment
      - WebACL
    Properties:
      ResourceArn: !Sub
        - "arn:aws:apigateway:${REGION}::/restapis/${REST_API_ID}/stages/${STAGE_NAME}"
        - REGION: !Ref "AWS::Region"
          REST_API_ID: !Ref RestApi
          STAGE_NAME: !Ref ApiGatewayStageNameParameter
      WebACLArn: !GetAtt WebACL.Arn

  GameSessionEventHandlerLambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref GameSessionEventHandlerLambdaFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref GameSessionEventTopic

  ServerBuild:
    Type: "AWS::GameLift::Build"
    Properties:
      Name: !Ref BuildNameParameter
      OperatingSystem: !Ref BuildOperatingSystemParameter
      StorageLocation:
        Bucket: !Ref BuildS3BucketParameter
        Key: !Ref BuildS3KeyParameter
        RoleArn: !GetAtt BuildAccessRole.Arn
      Version: !Ref BuildVersionParameter

  GameRequestLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
          MatchmakingRequestTableName: !Ref MatchmakingRequestTable
          SimpleMatchMakerTicketQueueUrl: !Ref SimpleMatchMakerTicketQueue
      FunctionName: !Sub ${GameNameParameter}GameRequestLambda
      Handler: game_request.handler
      MemorySize: 128
      Role: !GetAtt GameRequestLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  ResultsRequestLambdaFunctionApiGatewayPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt ResultsRequestLambdaFunction.Arn
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*/*"

  GameSessionQueue:
    Type: "AWS::GameLift::GameSessionQueue"
    Properties:
      Destinations:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



Editor/Resources/CloudFormation/scenario4_spot_fleets/cloudformation.yml [11:555]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameters:
  ApiGatewayStageNameParameter:
    Type: String
    Default: v1
    Description: Name of the Api Gateway stage

  BuildNameParameter:
    Type: String
    Default: Sample GameLift Build
    Description: Name of the build

  BuildOperatingSystemParameter:
    Type: String
    Description: Operating system of the build

  BuildS3BucketParameter:
    Type: String
    Description: Bucket that stores the server build

  BuildS3KeyParameter:
    Type: String
    Description: Key of the server build in the S3 bucket

  BuildVersionParameter:
    Type: String
    Description: Version number of the build

  FleetDescriptionParameter:
    Type: String
    Default: Deployed by the Amazon GameLift Plug-in for Unity.
    Description: Description of the fleet

  FleetNameParameter:
    Type: String
    Default: Sample GameLift Fleet
    Description: Name of the fleet

  FleetTcpFromPortParameter:
    Type: Number
    Default: 33430
    Description: Starting port number for TCP ports to be opened

  FleetTcpToPortParameter:
    Type: Number
    Default: 33440
    Description: Ending port number for TCP ports to be opened

  FleetUdpFromPortParameter:
    Type: Number
    Default: 33430
    Description: Starting port number for UDP ports to be opened

  FleetUdpToPortParameter:
    Type: Number
    Default: 33440
    Description: Ending port number for UDP ports to be opened

  GameNameParameter:
    Type: String
    Default: MyGame
    Description: Game name to prepend before resource names
    MaxLength: 12

  LambdaZipS3BucketParameter:
    Type: String
    Description: S3 bucket that stores the lambda function zip

  LambdaZipS3KeyParameter:
    Type: String
    Description: S3 key that stores the lambda function zip

  LaunchParametersParameter:
    Type: String
    Description: Parameters used to launch the game server process

  LaunchPathParameter:
    Type: String
    Description: Location of the game server executable in the build

  MatchmakingTimeoutInSecondsParamter:
    Type: Number
    Default: 60
    Description: Time in seconds before matchmaker times out to wait for enough players to create game session placement

  MaxTransactionsPerFiveMinutesPerIpParameter:
    Type: Number
    Default: 100
    MaxValue: 20000000
    MinValue: 100

  NumPlayersPerGameParameter:
    Type: Number
    Default: 2
    Description: Number of players per game session

  QueueTimeoutInSecondsParameter:
    Type: Number
    Default: 60
    Description: Time in seconds before game session placement times out to place players on a server

Resources:
  ApiGatewayCloudWatchRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"

  Account:
    Type: "AWS::ApiGateway::Account"
    Properties:
      CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchRole.Arn

  GameRequestLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}GameRequestLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:PutItem"
                  - "dynamodb:UpdateItem"
                  - "dynamodb:GetItem"
                  - "dynamodb:DeleteItem"
                  - "dynamodb:Query"
                  - "sqs:SendMessage"
                Resource: "*"

  GameSessionEventHandlerLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}GameSessionEventHandlerLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:PutItem"
                Resource: "*"

  GameSessionPlacementTable:
    Type: "AWS::DynamoDB::Table"
    Properties:
      AttributeDefinitions:
        - AttributeName: PlacementId
          AttributeType: S
      KeySchema:
        - AttributeName: PlacementId
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      TableName: !Sub ${GameNameParameter}GameSessionPlacementTable
      TimeToLiveSpecification:
        AttributeName: ExpirationTime
        Enabled: true

  MatchmakingRequestTable:
    Type: "AWS::DynamoDB::Table"
    Properties:
      AttributeDefinitions:
        - AttributeName: PlayerId
          AttributeType: S
        - AttributeName: StartTime
          AttributeType: "N"
      KeySchema:
        - AttributeName: PlayerId
          KeyType: HASH
        - AttributeName: StartTime
          KeyType: RANGE
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      TableName: !Sub ${GameNameParameter}MatchmakingRequestTable
      TimeToLiveSpecification:
        AttributeName: ExpirationTime
        Enabled: true

  RestApi:
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: !Sub ${GameNameParameter}RestApi

  ResultsRequestLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}ResultsRequestLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:GetItem"
                  - "dynamodb:Query"
                Resource: "*"

  SimpleMatchmakerLambdaFunctionExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}SimpleMatchmakerLambdaFunctionPolicies
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:UpdateItem"
                  - "gamelift:StartGameSessionPlacement"
                  - "sqs:ReceiveMessage"
                  - "sqs:DeleteMessage"
                  - "sqs:GetQueueAttributes"
                Resource: "*"

  UserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      AutoVerifiedAttributes:
        - email
      EmailConfiguration:
        EmailSendingAccount: COGNITO_DEFAULT
      EmailVerificationMessage: "Please verify your email to complete account registration for GameLift Sample Game. Confirmation Code {####}."
      EmailVerificationSubject: GameLift Sample Game Account Verification
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          RequireUppercase: true
      Schema:
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
      UserPoolName: !Sub ${GameNameParameter}UserPool
      UsernameAttributes:
        - email

  BuildAccessRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - cloudformation.amazonaws.com
                - gamelift.amazonaws.com
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub ${GameNameParameter}BuildS3AccessPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:GetObjectVersion"
                Resource:
                  - "Fn::Sub": "arn:aws:s3:::${BuildS3BucketParameter}/${BuildS3KeyParameter}"
      RoleName: !Sub ${GameNameParameter}BuildIAMRole

  GameRequestApiResource:
    Type: "AWS::ApiGateway::Resource"
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: start_game
      RestApiId: !Ref RestApi

  ResultsRequestApiResource:
    Type: "AWS::ApiGateway::Resource"
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: get_game_connection
      RestApiId: !Ref RestApi

  SimpleMatchMakerTicketQueue:
    Type: "AWS::SQS::Queue"
    Properties:
      FifoQueue: true
      MessageRetentionPeriod: !Ref MatchmakingTimeoutInSecondsParamter
      QueueName: !Sub ${GameNameParameter}SimpleMatchMakerTicketQueue.fifo

  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      AccessTokenValidity: 1
      ClientName: !Sub ${GameNameParameter}UserPoolClient
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      GenerateSecret: false
      IdTokenValidity: 1
      PreventUserExistenceErrors: ENABLED
      ReadAttributes:
        - email
        - preferred_username
      RefreshTokenValidity: 30
      SupportedIdentityProviders:
        - COGNITO
      UserPoolId: !Ref UserPool

  WebACL:
    Type: "AWS::WAFv2::WebACL"
    DependsOn:
      - ApiDeployment
    Properties:
      DefaultAction:
        Allow:
          {}
      Description: !Sub "WebACL for game: ${GameNameParameter}"
      Name: !Sub ${GameNameParameter}WebACL
      Rules:
        - Name: !Sub ${GameNameParameter}WebACLPerIpThrottleRule
          Action:
            Block:
              {}
          Priority: 0
          Statement:
            RateBasedStatement:
              AggregateKeyType: IP
              Limit: !Ref MaxTransactionsPerFiveMinutesPerIpParameter
          VisibilityConfig:
            CloudWatchMetricsEnabled: true
            MetricName: !Sub ${GameNameParameter}WebACLPerIpThrottleRuleMetrics
            SampledRequestsEnabled: true
      Scope: REGIONAL
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: !Sub ${GameNameParameter}WebACLMetrics
        SampledRequestsEnabled: true

  ApiDeployment:
    Type: "AWS::ApiGateway::Deployment"
    DependsOn:
      - GameRequestApiMethod
      - ResultsRequestApiMethod
    Properties:
      RestApiId: !Ref RestApi
      StageDescription:
        DataTraceEnabled: true
        LoggingLevel: INFO
        MetricsEnabled: true
      StageName: !Ref ApiGatewayStageNameParameter

  Authorizer:
    Type: "AWS::ApiGateway::Authorizer"
    Properties:
      IdentitySource: method.request.header.Auth
      Name: CognitoAuthorizer
      ProviderARNs:
        - "Fn::GetAtt":
            - UserPool
            - Arn
      RestApiId: !Ref RestApi
      Type: COGNITO_USER_POOLS

  GameSessionEventHandlerLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
      FunctionName: !Sub ${GameNameParameter}GameSessionEventHandlerLambda
      Handler: game_session_event_handler.handler
      MemorySize: 128
      Role: !GetAtt GameSessionEventHandlerLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  GameRequestApiMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId: !Ref Authorizer
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GameRequestLambdaFunction.Arn}/invocations"
      OperationName: GameRequest
      ResourceId: !Ref GameRequestApiResource
      RestApiId: !Ref RestApi

  GameSessionEventTopic:
    Type: "AWS::SNS::Topic"
    Properties:
      Subscription:
        - Endpoint: !GetAtt GameSessionEventHandlerLambdaFunction.Arn
          Protocol: lambda
      TopicName: !Sub ${GameNameParameter}GameSessionEventTopic

  ResultsRequestApiMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId: !Ref Authorizer
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ResultsRequestLambdaFunction.Arn}/invocations"
      OperationName: ResultsRequest
      ResourceId: !Ref ResultsRequestApiResource
      RestApiId: !Ref RestApi

  ResultsRequestLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
          MatchmakingRequestTableName: !Ref MatchmakingRequestTable
      FunctionName: !Sub ${GameNameParameter}ResultsRequestLambda
      Handler: results_request.handler
      MemorySize: 128
      Role: !GetAtt ResultsRequestLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  WebACLAssociation:
    Type: "AWS::WAFv2::WebACLAssociation"
    DependsOn:
      - ApiDeployment
      - WebACL
    Properties:
      ResourceArn: !Sub
        - "arn:aws:apigateway:${REGION}::/restapis/${REST_API_ID}/stages/${STAGE_NAME}"
        - REGION: !Ref "AWS::Region"
          REST_API_ID: !Ref RestApi
          STAGE_NAME: !Ref ApiGatewayStageNameParameter
      WebACLArn: !GetAtt WebACL.Arn

  GameSessionEventHandlerLambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref GameSessionEventHandlerLambdaFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref GameSessionEventTopic

  ServerBuild:
    Type: "AWS::GameLift::Build"
    Properties:
      Name: !Ref BuildNameParameter
      OperatingSystem: !Ref BuildOperatingSystemParameter
      StorageLocation:
        Bucket: !Ref BuildS3BucketParameter
        Key: !Ref BuildS3KeyParameter
        RoleArn: !GetAtt BuildAccessRole.Arn
      Version: !Ref BuildVersionParameter

  GameRequestLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref LambdaZipS3BucketParameter
        S3Key: !Ref LambdaZipS3KeyParameter
      Description: Lambda function to handle game requests
      Environment:
        Variables:
          GameSessionPlacementTableName: !Ref GameSessionPlacementTable
          MatchmakingRequestTableName: !Ref MatchmakingRequestTable
          SimpleMatchMakerTicketQueueUrl: !Ref SimpleMatchMakerTicketQueue
      FunctionName: !Sub ${GameNameParameter}GameRequestLambda
      Handler: game_request.handler
      MemorySize: 128
      Role: !GetAtt GameRequestLambdaFunctionExecutionRole.Arn
      Runtime: python3.8

  ResultsRequestLambdaFunctionApiGatewayPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt ResultsRequestLambdaFunction.Arn
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*/*"

  GameSessionQueue:
    Type: "AWS::GameLift::GameSessionQueue"
    Properties:
      Destinations:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



