--- # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 Description: (GAMEKIT1003) - The AWS CloudFormation template for AWS GameKit Achievements. v1.0.0 AWSTemplateFormatVersion: 2010-09-09 Parameters: GameKitEnv: Type: String GameKitGameName: Type: String GameKitBase36AwsAccountId: Type: String GameKitShortAwsRegionCode: Type: String AchievementsTableName: Type: String PlayerAchievementsTableName: Type: String AchievementsAdminLambdaRoleName: Type: String AchievementsLambdaRoleName: Type: String AdminAddAchievementsLambdaName: Type: String AdminGetAchievementsLambdaName: Type: String AdminDeleteAchievementsLambdaName: Type: String UpdateAchievementsLambdaName: Type: String GetAchievementsLambdaName: Type: String GetAchievementLambdaName: Type: String ResizeIconLambdaName: Type: String AchievementsAdminInvokePolicyName: Type: String AchievementsAdminInvokeRoleName: Type: String AchievementsTokenAuthorizerLambdaRoleName: Type: String AchievementsTokenAuthorizerLambdaName: Type: String CloudWatchDashboardEnabled: Type: String Default: "true" AllowedValues: ["true", "false"] S3AccessLoggingEnabled: Type: String AllowedValues: [ "true", "false" ] DetailedLambdaLoggingDisabled: Type: String AllowedValues: [ "true", "false" ] LambdaFunctionsReplacementID: Type: 'AWS::SSM::Parameter::Value<String>' LambdaLayerARNCommonLambdaLayer: Type: 'AWS::SSM::Parameter::Value<String>' LambdaLayerARNImageProcessingLambdaLayer: Type: 'AWS::SSM::Parameter::Value<String>' LambdaLayerARNCryptoLambdaLayer: Type: 'AWS::SSM::Parameter::Value<String>' IdentityLambdaFunctionsReplacementID: Type: 'AWS::SSM::Parameter::Value<String>' UseThirdPartyIdentityProvider: Type: String AllowedValues: [ "true", "false" ] Conditions: IsCloudWatchDashboardEnabled: !Equals - !Ref CloudWatchDashboardEnabled - true IsS3AccessLoggingEnabled: !Equals - !Ref S3AccessLoggingEnabled - true IsS3AccessLoggingDisabled: !Not - !Equals - !Ref S3AccessLoggingEnabled - true IsUsingThirdPartyIdentityProvider: !Equals - !Ref UseThirdPartyIdentityProvider - true IsNotUsingThirdPartyIdentityProvider: !Not - !Equals - !Ref UseThirdPartyIdentityProvider - true Resources: GameKitAchievements: Type: 'AWS::DynamoDB::Table' Properties: AttributeDefinitions: - AttributeName: achievement_id AttributeType: S KeySchema: - AttributeName: achievement_id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 TableName: !Ref AchievementsTableName GameKitPlayerAchievements: Type: 'AWS::DynamoDB::Table' Properties: AttributeDefinitions: - AttributeName: player_id AttributeType: S - AttributeName: achievement_id AttributeType: S KeySchema: - AttributeName: player_id KeyType: HASH - AttributeName: achievement_id KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 TableName: !Ref PlayerAchievementsTableName AchievementsAdminLambdaRole: Type: 'AWS::IAM::Role' Properties: RoleName: !Ref AchievementsAdminLambdaRoleName ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: /service-role/ Policies: - PolicyName: AdditionalPermissions PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'dynamodb:PutItem' - 'dynamodb:GetItem' - 'dynamodb:UpdateItem' - 'dynamodb:Query' - 'dynamodb:Scan' - 'dynamodb:BatchGetItem' - 'dynamodb:BatchWriteItem' - 'dynamodb:DeleteItem' Resource: - !Sub '${GameKitAchievements.Arn}' - !Sub '${GameKitAchievements.Arn}/index/*' - Effect: Allow Action: - 's3:DeleteObject' Resource: - !Sub '${AchievementsBucket.Arn}/icons/*' AchievementsLambdaRole: Type: 'AWS::IAM::Role' Properties: RoleName: !Ref AchievementsLambdaRoleName ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: /service-role/ Policies: - PolicyName: AdditionalPermissions PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'dynamodb:Query' - 'dynamodb:Scan' - 'dynamodb:GetItem' - 'dynamodb:BatchGetItem' Resource: - !Sub '${GameKitAchievements.Arn}' - !Sub '${GameKitAchievements.Arn}/index/*' - Effect: Allow Action: - 'dynamodb:PutItem' - 'dynamodb:GetItem' - 'dynamodb:UpdateItem' - 'dynamodb:Query' - 'dynamodb:Scan' - 'dynamodb:BatchGetItem' - 'dynamodb:BatchWriteItem' Resource: - !Sub '${GameKitPlayerAchievements.Arn}' - !Sub '${GameKitPlayerAchievements.Arn}/index/*' - Effect: Allow Action: - 's3:GetObject' - 's3:PutObject' - 's3:DeleteObject' Resource: - !Sub 'arn:aws:s3:::gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}-achievements/*' - !If - IsNotUsingThirdPartyIdentityProvider - Effect: Allow Action: - 'dynamodb:Query' Resource: - !Sub - '${IdentityTableArn}/index/*' - IdentityTableArn: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:IdentityTableArn' - !Ref AWS::NoValue AchievementsTokenAuthorizerLambdaRole: Condition: IsUsingThirdPartyIdentityProvider Type: 'AWS::IAM::Role' Properties: RoleName: !Ref AchievementsTokenAuthorizerLambdaRoleName ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: /service-role/ Policies: - PolicyName: AdditionalPermissions PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'secretsmanager:DescribeSecret' - 'secretsmanager:GetSecretValue' Resource: !Sub - 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:${TokenAuthorizerSecretName}*' - TokenAuthorizerSecretName: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:TokenAuthorizerSecretName' - Effect: Allow Action: - 'secretsmanager:ListSecrets' Resource: '*' AdminAddAchievementsLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref AdminAddAchievementsLambdaName Description: Admin function to add new achievements Handler: index.lambda_handler Role: !GetAtt AchievementsAdminLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements ACHIEVEMENTS_BUCKET_NAME: !Ref AchievementsBucket DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/AdminAddAchievements.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer AdminAddAchievementsLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: AdminAddAchievementsLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${AdminAddAchievementsLambda}' AdminAddAchievementsLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt AdminAddAchievementsLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AdminGetAchievementsLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref AdminGetAchievementsLambdaName Description: Admin function to get all achievements Handler: index.lambda_handler Role: !GetAtt AchievementsAdminLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/AdminGetAchievements.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer AdminGetAchievementsLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: AdminGetAchievementsLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${AdminGetAchievementsLambda}' AdminGetAchievementsLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt AdminGetAchievementsLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AdminDeleteAchievementsLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref AdminDeleteAchievementsLambdaName Description: Admin function to delete achievements Handler: index.lambda_handler Role: !GetAtt AchievementsAdminLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements ACHIEVEMENTS_BUCKET_NAME: !Ref AchievementsBucket DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/AdminDeleteAchievements.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer AdminDeleteAchievementsLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: AdminDeleteAchievementsLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${AdminDeleteAchievementsLambda}' AdminDeleteAchievementsLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt AdminDeleteAchievementsLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' UpdateAchievementsLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref UpdateAchievementsLambdaName Description: Updates a player's achievement Handler: index.lambda_handler Role: !GetAtt AchievementsLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements PLAYER_ACHIEVEMENTS_TABLE_NAME: !Ref GameKitPlayerAchievements DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled IDENTITY_TABLE_NAME: !If - IsNotUsingThirdPartyIdentityProvider - !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:IdentityTableName' - !Ref AWS::NoValue Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/UpdateAchievements.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer UpdateAchievementsLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: UpdateAchievementsLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${UpdateAchievementsLambda}' UpdateAchievementsLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt UpdateAchievementsLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' GetAchievementsLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref GetAchievementsLambdaName Description: Retrieves all player achievements, earned and unearned. Handler: index.lambda_handler Role: !GetAtt AchievementsLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements PLAYER_ACHIEVEMENTS_TABLE_NAME: !Ref GameKitPlayerAchievements DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled IDENTITY_TABLE_NAME: !If - IsNotUsingThirdPartyIdentityProvider - !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:IdentityTableName' - !Ref AWS::NoValue Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/GetAchievements.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer GetAchievementsLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: GetAchievementsLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${GetAchievementsLambda}' GetAchievementsLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt GetAchievementsLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' GetAchievementLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref GetAchievementLambdaName Description: Retrieves a player achievement, earned or unearned. Handler: index.lambda_handler Role: !GetAtt AchievementsLambdaRole.Arn Environment: Variables: ACHIEVEMENTS_TABLE_NAME: !Ref GameKitAchievements PLAYER_ACHIEVEMENTS_TABLE_NAME: !Ref GameKitPlayerAchievements DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled IDENTITY_TABLE_NAME: !If - IsNotUsingThirdPartyIdentityProvider - !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:IdentityTableName' - !Ref AWS::NoValue Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/GetAchievement.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer GetAchievementLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: GetAchievementLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${GetAchievementLambda}' GetAchievementLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt GetAchievementLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/*/*/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' ResizeIconLambda: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref ResizeIconLambdaName Description: A Lambda Function configured as a PUT Trigger on the Achievements bucket for resizing icons Handler: index.lambda_handler Role: !GetAtt AchievementsLambdaRole.Arn Environment: Variables: RESIZE_WIDTH: 100 RESIZE_HEIGHT: 100 DESTINATION_PREFIX: 'icons' AWS_ACCOUNT_ID: !Sub '${AWS::AccountId}' Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/achievements/ResizeIcon.${LambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer - !Ref LambdaLayerARNImageProcessingLambdaLayer ResizeIconLambdaLogGroup: Type: 'AWS::Logs::LogGroup' DependsOn: ResizeIconLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${ResizeIconLambda}' ResizeIconLambdaPermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt ResizeIconLambda.Arn Principal: s3.amazonaws.com SourceAccount: !Sub '${AWS::AccountId}' SourceArn: !Sub 'arn:aws:s3:::gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}-achievements' AchievementsTokenAuthorizerLambda: Condition: IsUsingThirdPartyIdentityProvider Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref AchievementsTokenAuthorizerLambdaName Description: Custom Token Authorizer for Achievements feature Handler: index.lambda_handler Role: !GetAtt AchievementsTokenAuthorizerLambdaRole.Arn Environment: Variables: JWKS_SECRET_NAME: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:TokenAuthorizerSecretName' ENDPOINTS_ALLOWED: 'achievements*,achievements/*' DEPLOYMENT_STAGE: !Ref GameKitEnv DETAILED_LOGGING_DISABLED: !Ref DetailedLambdaLoggingDisabled USER_IDENTIFIER_CLAIM_FIELD: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:TokenAuthorizerUserIdClaimName' Code: S3Bucket: !Sub 'do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}' S3Key: !Sub 'functions/identity/DefaultTokenAuthorizer.${IdentityLambdaFunctionsReplacementID}.zip' Runtime: python3.7 Timeout: 25 TracingConfig: Mode: Active Layers: - !Ref LambdaLayerARNCommonLambdaLayer - !Ref LambdaLayerARNCryptoLambdaLayer AchievementsTokenAuthorizerLambdaLogGroup: Condition: IsUsingThirdPartyIdentityProvider Type: 'AWS::Logs::LogGroup' DependsOn: AchievementsTokenAuthorizerLambda Properties: RetentionInDays: 30 LogGroupName: !Sub '/aws/lambda/${AchievementsTokenAuthorizerLambda}' AchievementsTokenAuthorizerLambdaPermission: Condition: IsUsingThirdPartyIdentityProvider Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt AchievementsTokenAuthorizerLambda.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MainApi}/authorizers/*' - MainApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AchievementApiResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApiRootResourceId' PathPart: achievements RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AchievementAdminApiResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !Ref AchievementApiResource PathPart: admin RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AdminAddAchievementsApiResourcePostMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: POST ResourceId: !Ref AchievementAdminApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: AWS_IAM Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AdminAddAchievementsLambda.Arn}/invocations' RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' RequestParameters: method.request.header.x-amz-date: true RequestModels: '$default': !Ref AchievementsArrayModel AdminGetAchievementsApiResourceGetMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: GET ResourceId: !Ref AchievementAdminApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: AWS_IAM Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AdminGetAchievementsLambda.Arn}/invocations' RequestParameters: method.request.header.x-amz-date: true method.request.querystring.start_key: false method.request.querystring.limit: false RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' AdminDeleteAchievementsApiResourceDeleteMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: DELETE ResourceId: !Ref AchievementAdminApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: AWS_IAM Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AdminDeleteAchievementsLambda.Arn}/invocations' RequestParameters: method.request.header.x-amz-date: true RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' AchievementByIdApiResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !Ref AchievementApiResource PathPart: '{achievement_id}' RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AchievementUnlockByIdApiResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !Ref AchievementByIdApiResource PathPart: 'unlock' RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' UpdateAchievementsApiResourcePostMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: POST ResourceId: !Ref AchievementUnlockByIdApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: !If [ IsUsingThirdPartyIdentityProvider, CUSTOM, COGNITO_USER_POOLS ] AuthorizerId: !If [ IsUsingThirdPartyIdentityProvider, !Ref TokenAuthorizer, !Ref CognitoAuthorizer ] Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UpdateAchievementsLambda.Arn}/invocations' RequestParameters: method.request.header.authorization: true method.request.path.achievement_id: true RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' RequestModels: '$default': !Ref UpdateAchievementsModel UpdateAchievementsModel: Type: AWS::ApiGateway::Model Properties: RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' ContentType: application/json Description: Schema for Achievements Update API call Schema: $schema: 'http://json-schema.org/draft-04/schema#' type: object properties: increment_by: type: integer AchievementsArrayModel: Type: AWS::ApiGateway::Model Properties: RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' ContentType: application/json Description: Schema for Achievements Array Schema: $schema: 'http://json-schema.org/draft-04/schema#' type: object properties: achievements: title: AchievementsArray type: array items: type: object properties: title: type: string locked_description: type: string unlocked_description: type: string locked_icon_url: type: string unlocked_icon_url: type: string points: type: integer is_stateful: type: boolean max_value: type: integer is_secret: type: boolean is_hidden: type: boolean order_number: type: integer created_at: type: string updated_at: type: string GetAchievementsApiResourceGetMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: GET ResourceId: !Ref AchievementApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: !If [ IsUsingThirdPartyIdentityProvider, CUSTOM, COGNITO_USER_POOLS ] AuthorizerId: !If [ IsUsingThirdPartyIdentityProvider, !Ref TokenAuthorizer, !Ref CognitoAuthorizer ] Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetAchievementsLambda.Arn}/invocations' RequestParameters: method.request.header.authorization: true method.request.querystring.start_key: false method.request.querystring.limit: false RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' GetAchievementApiResourceGetMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: GET ResourceId: !Ref AchievementByIdApiResource RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizationType: !If [ IsUsingThirdPartyIdentityProvider, CUSTOM, COGNITO_USER_POOLS ] AuthorizerId: !If [ IsUsingThirdPartyIdentityProvider, !Ref TokenAuthorizer, !Ref CognitoAuthorizer ] Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetAchievementLambda.Arn}/invocations' RequestValidatorId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRequestValidator' RequestParameters: method.request.header.authorization: true method.request.path.achievement_id: true CloudFrontOriginIdentity: Type: AWS::CloudFront::CloudFrontOriginAccessIdentity Properties: CloudFrontOriginAccessIdentityConfig: Comment: 'gamekit-${GameKitEnv}-${GameKitGameName} Origin Identity' AchievementsBucket: DependsOn: ResizeIconLambdaPermission Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: 'AES256' VersioningConfiguration: Status: Enabled AccessControl: Private BucketName: !Sub 'gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}-achievements' LifecycleConfiguration: Rules: - Prefix: uploads/ Status: Enabled ExpirationInDays: 1 CorsConfiguration: CorsRules: - AllowedHeaders: - '*' AllowedMethods: - GET - HEAD AllowedOrigins: - '*' MaxAge: 3000 NotificationConfiguration: LambdaConfigurations: - Event: 's3:ObjectCreated:Put' Filter: S3Key: Rules: - Name: prefix Value: uploads/ Function: !Sub '${ResizeIconLambda.Arn}' LoggingConfiguration: !If - IsS3AccessLoggingEnabled - DestinationBucketName: !Ref AchievementsLoggingBucket LogFilePrefix: 'achievements-bucket-logs' - !Ref "AWS::NoValue" AchievementsLoggingBucket: Type: AWS::S3::Bucket Condition: IsS3AccessLoggingEnabled Properties: BucketName: !Sub 'gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}-achievements-bucket-log' AccessControl: LogDeliveryWrite BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: 'AES256' VersioningConfiguration: Status: Enabled PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true AchievementsIconsBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref AchievementsBucket PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: CanonicalUser: !GetAtt CloudFrontOriginIdentity.S3CanonicalUserId Action: 's3:GetObject' Resource: !Sub '${AchievementsBucket.Arn}/*' - Effect: Allow Principal: AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' Action: - 's3:PutObject' - 's3:GetObject' - 's3:DeleteObject' Resource: !Sub '${AchievementsBucket.Arn}/icons/*' - Effect: Allow Principal: AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' Action: 's3:ListBucket' Resource: !Sub '${AchievementsBucket.Arn}' AchievementsIconsDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CacheBehaviors: - PathPattern: '*' AllowedMethods: - HEAD - GET CachedMethods: - HEAD - GET Compress: false ForwardedValues: Cookies: Forward: none QueryString: false Headers: - 'Origin' TargetOriginId: !Sub 'S3-${AchievementsBucket}/icons' ViewerProtocolPolicy: redirect-to-https - PathPattern: 'Cors' AllowedMethods: - HEAD - GET - OPTIONS CachedMethods: - HEAD - GET - OPTIONS Compress: false ForwardedValues: Cookies: Forward: none QueryString: false Headers: - 'Accept' - 'Access-Control-Request-Headers' - 'Access-Control-Request-Method' - 'Origin' TargetOriginId: !Sub 'S3-${AchievementsBucket}/icons' ViewerProtocolPolicy: allow-all Comment: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName} distribution for achievement icons' DefaultCacheBehavior: AllowedMethods: - HEAD - GET - OPTIONS CachedMethods: - HEAD - GET - OPTIONS Compress: false ForwardedValues: Cookies: Forward: none QueryString: false Headers: - 'Access-Control-Request-Headers' - 'Access-Control-Request-Method' - 'Origin' TargetOriginId: !Sub 'S3-${AchievementsBucket}/icons' ViewerProtocolPolicy: allow-all Origins: - DomainName: !GetAtt AchievementsBucket.RegionalDomainName Id: !Sub 'S3-${AchievementsBucket}/icons' S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginIdentity}" PriceClass: 'PriceClass_100' Enabled: true EmptyAchievementsBucketOnDelete: Type: Custom::LambdaTrigger Properties: ServiceToken: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:EmptyS3BucketOnDelete' bucket_name: !Ref AchievementsBucket EmptyAchievementsLoggingBucketOnDelete: Type: Custom::LambdaTrigger Properties: ServiceToken: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:EmptyS3BucketOnDelete' bucket_name: !Ref AchievementsLoggingBucket delete_bucket: true AchievementsAdminInvokeRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" Action: "sts:AssumeRole" Policies: - PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: execute-api:Invoke Resource: !Sub "arn:aws:execute-api:*:${AWS::AccountId}:*/*/*/achievements/admin" PolicyName: !Ref AchievementsAdminInvokePolicyName RoleName: !Ref AchievementsAdminInvokeRoleName TokenAuthorizer: Condition: IsUsingThirdPartyIdentityProvider Type: 'AWS::ApiGateway::Authorizer' Properties: Name: Achievements-Token-Authorizer Type: TOKEN IdentitySource: method.request.header.authorization RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' AuthorizerUri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AchievementsTokenAuthorizerLambda.Arn}/invocations' AuthorizerResultTtlInSeconds: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:TokenAuthorizerCacheTtlInSeconds' CognitoAuthorizer: Condition: IsNotUsingThirdPartyIdentityProvider Type: 'AWS::ApiGateway::Authorizer' Properties: Name: Achievements-Cognito-Authorizer Type: COGNITO_USER_POOLS IdentitySource: method.request.header.authorization RestApiId: !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' ProviderARNs: - !ImportValue 'Fn::Sub': 'gamekit-${GameKitEnv}-${GameKitGameName}-identity:${AWS::Region}:GameKitUserPoolArn' CloudWatchDashboardStack: Condition: IsCloudWatchDashboardEnabled Type: 'AWS::CloudFormation::Stack' Properties: TemplateURL: !Sub https://do-not-delete-gamekit-${GameKitEnv}-${GameKitShortAwsRegionCode}-${GameKitBase36AwsAccountId}-${GameKitGameName}.s3.${AWS::Region}.amazonaws.com/cloudformation/achievements/dashboard.yml TimeoutInMinutes: '15' Parameters: GameKitEnv: !Sub ${GameKitEnv} GameKitGameName: !Sub ${GameKitGameName} AdminDeleteAchievementsLambdaName: !Ref AdminDeleteAchievementsLambdaName AchievementsTableName: !Ref AchievementsTableName PlayerAchievementsTableName: !Ref PlayerAchievementsTableName AchievementsAdminLambdaRoleName: !Ref AchievementsAdminLambdaRoleName AchievementsLambdaRoleName: !Ref AchievementsLambdaRoleName AdminAddAchievementsLambdaName: !Ref AdminAddAchievementsLambdaName AdminGetAchievementsLambdaName: !Ref AdminGetAchievementsLambdaName UpdateAchievementsLambdaName: !Ref UpdateAchievementsLambdaName GetAchievementsLambdaName: !Ref GetAchievementsLambdaName GetAchievementLambdaName: !Ref GetAchievementLambdaName ResizeIconLambdaName: !Ref ResizeIconLambdaName Outputs: AchievementsApiGatewayBaseUrl: Description: The API Gateway base url for the achievements feature Value: !Sub - 'https://${MainRestApi}.execute-api.${AWS::Region}.amazonaws.com/${GameKitEnv}/achievements' - MainRestApi: Fn::ImportValue: !Sub 'gamekit-${GameKitEnv}-${GameKitGameName}-main:${AWS::Region}:MainRestApi' Export: Name: !Sub '${AWS::StackName}:${AWS::Region}:AchievementsApiGatewayBaseUrl' AchievementsRegion: Description: Region Value: !Sub '${AWS::Region}' Export: Name: !Sub '${AWS::StackName}:${AWS::Region}:AchievementsRegion' AchievementsIconsCloudFrontBaseUrl: Description: The CloudFront base url for achievement icons Value: !Sub - 'https://${CloudFrontDomain}' - CloudFrontDomain: !GetAtt AchievementsIconsDistribution.DomainName Export: Name: !Sub '${AWS::StackName}:${AWS::Region}:AchievementsIconsCloudFrontBaseUrl'