# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > Template to deploy lambda functions as part of bootstrap Parameters: CognitoOperationUsersUserPoolId: Type: String CognitoOperationUsersUserPoolClientId: Type: String CognitoUserPoolId: Type: String CognitoUserPoolClientId: Type: String TenantDetailsTableArn: Type: String ServerlessSaaSSettingsTableArn: Type: String ApiKeyOperationUsersParameter: Type: String ApiKeyPlatinumTierParameter: Type: String ApiKeyPremiumTierParameter: Type: String ApiKeyStandardTierParameter: Type: String ApiKeyBasicTierParameter: Type: String TenantStackMappingTableArn: Type: String TenantUserMappingTableArn: Type: String TenantStackMappingTableName: Type: String TenantUserPoolCallbackURLParameter: Type: String Description: "Enter Tenant Management userpool call back url" LambdaCanaryDeploymentPreference: Type: String Default: "False" Globals: Function: Timeout: 29 Layers: - !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14" Environment: Variables: LOG_LEVEL: DEBUG POWERTOOLS_METRICS_NAMESPACE: "ServerlessSaaS" Resources: ServerlessSaaSLayers: Type: AWS::Serverless::LayerVersion Properties: LayerName: serverless-saas-dependencies Description: Utilities for project ContentUri: ../../layers/ CompatibleRuntimes: - python3.9 LicenseInfo: "MIT" RetentionPolicy: Retain Metadata: BuildMethod: python3.9 #Tenant Authorizer AuthorizerExecutionRole: Type: AWS::IAM::Role Properties: RoleName: authorizer-execution-role Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: authorizer-execution-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cognito-idp:List* Resource: - !Sub arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/* - Effect: Allow Action: - dynamodb:GetItem Resource: - !Ref TenantDetailsTableArn AuthorizerAccessRole: Type: AWS::IAM::Role DependsOn: AuthorizerExecutionRole Properties: RoleName: authorizer-access-role Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: - !GetAtt 'AuthorizerExecutionRole.Arn' Action: - sts:AssumeRole Policies: - PolicyName: authorizer-access-role-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:BatchGetItem - dynamodb:GetItem - dynamodb:PutItem - dynamodb:DeleteItem - dynamodb:UpdateItem - dynamodb:Query - dynamodb:Scan Resource: - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/* SharedServicesAuthorizerFunction: Type: AWS::Serverless::Function DependsOn: AuthorizerAccessRole Properties: CodeUri: ../../Resources/ Handler: shared_service_authorizer.lambda_handler Runtime: python3.9 Role: !GetAtt AuthorizerExecutionRole.Arn MemorySize: 256 Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: OPERATION_USERS_USER_POOL: !Ref CognitoOperationUsersUserPoolId OPERATION_USERS_APP_CLIENT: !Ref CognitoOperationUsersUserPoolClientId OPERATION_USERS_API_KEY : !Ref ApiKeyOperationUsersParameter BusinessServicesAuthorizerFunction: Type: AWS::Serverless::Function DependsOn: AuthorizerAccessRole Properties: CodeUri: ../../Resources/ Handler: tenant_authorizer.lambda_handler Runtime: python3.9 Role: !GetAtt AuthorizerExecutionRole.Arn MemorySize: 256 Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: OPERATION_USERS_USER_POOL: !Ref CognitoOperationUsersUserPoolId OPERATION_USERS_APP_CLIENT: !Ref CognitoOperationUsersUserPoolClientId OPERATION_USERS_API_KEY : !Ref ApiKeyOperationUsersParameter #Create user pool for the tenant TenantUserPoolLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub tenant-userpool-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub tenant-userpool-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cognito-idp:* Resource: "*" - Effect: Allow Action: - dynamodb:GetItem Resource: - !Ref TenantDetailsTableArn - Effect: Allow Action: - dynamodb:GetItem - dynamodb:Query Resource: - !Ref TenantUserMappingTableArn CreateUserLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub create-user-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub create-user-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cognito-idp:* Resource: "*" - Effect: Allow Action: - dynamodb:PutItem Resource: - !Ref TenantUserMappingTableArn - Effect: Allow Action: - dynamodb:GetItem Resource: - !Ref TenantDetailsTableArn CreateTenantAdminUserFunction: Type: AWS::Serverless::Function DependsOn: CreateUserLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.create_tenant_admin_user Runtime: python3.9 Role: !GetAtt CreateUserLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: TENANT_USER_POOL_ID: !Ref CognitoUserPoolId TENANT_APP_CLIENT_ID: !Ref CognitoUserPoolClientId TENANT_USER_POOL_CALLBACK_URL: !Join ["",["https://",!Ref TenantUserPoolCallbackURLParameter, "/"]] POWERTOOLS_SERVICE_NAME: "UserManagement.CreateTenantAdmin" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref CreateTenantAdminUserFunctionCanaryErrorsAlarm CreateTenantAdminUserFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${CreateTenantAdminUserFunction}:live" - Name: FunctionName Value: !Ref CreateTenantAdminUserFunction - Name: ExecutedVersion Value: !GetAtt CreateTenantAdminUserFunction.Version.Version #User management CreateUserFunction: Type: AWS::Serverless::Function DependsOn: CreateUserLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.create_user Runtime: python3.9 Role: !GetAtt CreateUserLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.CreateUser" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref CreateUserFunctionCanaryErrorsAlarm CreateUserFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${CreateUserFunction}:live" - Name: FunctionName Value: !Ref CreateUserFunction - Name: ExecutedVersion Value: !GetAtt CreateUserFunction.Version.Version UpdateUserFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.update_user Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.UpdateUser" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref UpdateUserFunctionCanaryErrorsAlarm UpdateUserFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${UpdateUserFunction}:live" - Name: FunctionName Value: !Ref UpdateUserFunction - Name: ExecutedVersion Value: !GetAtt UpdateUserFunction.Version.Version DisableUserFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.disable_user Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.DisableUser" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref DisableUserFunctionCanaryErrorsAlarm DisableUserFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${DisableUserFunction}:live" - Name: FunctionName Value: !Ref DisableUserFunction - Name: ExecutedVersion Value: !GetAtt DisableUserFunction.Version.Version DisableUsersByTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.disable_users_by_tenant Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.DisableUsersByTenant" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref DisableUsersByTenantFunctionCanaryErrorsAlarm DisableUsersByTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${DisableUsersByTenantFunction}:live" - Name: FunctionName Value: !Ref DisableUsersByTenantFunction - Name: ExecutedVersion Value: !GetAtt DisableUsersByTenantFunction.Version.Version EnableUsersByTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.enable_users_by_tenant Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.EnableUsersByTenant" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref EnableUsersByTenantFunctionCanaryErrorsAlarm EnableUsersByTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${EnableUsersByTenantFunction}:live" - Name: FunctionName Value: !Ref EnableUsersByTenantFunction - Name: ExecutedVersion Value: !GetAtt EnableUsersByTenantFunction.Version.Version GetUserFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.get_user Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.GetUser" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref GetUserFunctionCanaryErrorsAlarm GetUserFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${GetUserFunction}:live" - Name: FunctionName Value: !Ref GetUserFunction - Name: ExecutedVersion Value: !GetAtt GetUserFunction.Version.Version GetUsersFunction: Type: AWS::Serverless::Function DependsOn: TenantUserPoolLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: user-management.get_users Runtime: python3.9 Role: !GetAtt TenantUserPoolLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "UserManagement.GetUsers" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref GetUsersFunctionCanaryErrorsAlarm GetUsersFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${GetUsersFunction}:live" - Name: FunctionName Value: !Ref GetUsersFunction - Name: ExecutedVersion Value: !GetAtt GetUsersFunction.Version.Version #Tenant Management TenantManagementLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub tenant-management-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub create-tenant-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:PutItem - dynamodb:GetItem - dynamodb:UpdateItem - dynamodb:Scan - dynamodb:Query Resource: - !Ref TenantDetailsTableArn - !Join ["", [!Ref TenantDetailsTableArn, '/index/*']] - Effect: Allow Action: - dynamodb:GetItem Resource: - !Ref ServerlessSaaSSettingsTableArn CreateTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.create_tenant Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "TenantManagement.CreateTenant" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref CreateTenantFunctionCanaryErrorsAlarm CreateTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${CreateTenantFunction}:live" - Name: FunctionName Value: !Ref CreateTenantFunction - Name: ExecutedVersion Value: !GetAtt CreateTenantFunction.Version.Version ActivateTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.activate_tenant Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "TenantManagement.ActivateTenant" ENABLE_USERS_BY_TENANT: "/users/enable" PROVISION_TENANT: "/provisioning/" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref ActivateTenantFunctionCanaryErrorsAlarm ActivateTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${ActivateTenantFunction}:live" - Name: FunctionName Value: !Ref ActivateTenantFunction - Name: ExecutedVersion Value: !GetAtt ActivateTenantFunction.Version.Version GetTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.get_tenant Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "TenantManagement.GetTenant" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref GetTenantFunctionCanaryErrorsAlarm GetTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${GetTenantFunction}:live" - Name: FunctionName Value: !Ref GetTenantFunction - Name: ExecutedVersion Value: !GetAtt GetTenantFunction.Version.Version DeactivateTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.deactivate_tenant Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "TenantManagement.DeactivateTenant" DEPROVISION_TENANT: "/provisioning/" DISABLE_USERS_BY_TENANT: "/users/disable" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref DeactivateTenantFunctionCanaryErrorsAlarm DeactivateTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${DeactivateTenantFunction}:live" - Name: FunctionName Value: !Ref DeactivateTenantFunction - Name: ExecutedVersion Value: !GetAtt DeactivateTenantFunction.Version.Version UpdateTenantFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.update_tenant Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: POWERTOOLS_SERVICE_NAME: "TenantManagement.UpdateTenant" PLATINUM_TIER_API_KEY: !Ref ApiKeyPlatinumTierParameter PREMIUM_TIER_API_KEY: !Ref ApiKeyPremiumTierParameter STANDARD_TIER_API_KEY: !Ref ApiKeyStandardTierParameter BASIC_TIER_API_KEY: !Ref ApiKeyBasicTierParameter AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref UpdateTenantFunctionCanaryErrorsAlarm UpdateTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${UpdateTenantFunction}:live" - Name: FunctionName Value: !Ref UpdateTenantFunction - Name: ExecutedVersion Value: !GetAtt UpdateTenantFunction.Version.Version GetTenantsFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.get_tenants Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref GetTenantsFunctionCanaryErrorsAlarm GetTenantsFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${GetTenantsFunction}:live" - Name: FunctionName Value: !Ref GetTenantsFunction - Name: ExecutedVersion Value: !GetAtt GetTenantsFunction.Version.Version GetTenantConfigFunction: Type: AWS::Serverless::Function DependsOn: TenantManagementLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-management.load_tenant_config Runtime: python3.9 Role: !GetAtt TenantManagementLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref GetTenantConfigFunctionCanaryErrorsAlarm GetTenantConfigFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${GetTenantConfigFunction}:live" - Name: FunctionName Value: !Ref GetTenantConfigFunction - Name: ExecutedVersion Value: !GetAtt GetTenantConfigFunction.Version.Version #Tenant Registration RegisterTenantLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub tenant-registration-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess RegisterTenantFunction: Type: AWS::Serverless::Function DependsOn: RegisterTenantLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-registration.register_tenant Runtime: python3.9 Role: !GetAtt RegisterTenantLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: # Need to find a better way than hard coding resource paths CREATE_TENANT_ADMIN_USER_RESOURCE_PATH: "/user/tenant-admin" CREATE_TENANT_RESOURCE_PATH: "/tenant" PROVISION_TENANT_RESOURCE_PATH: "/provisioning" PLATINUM_TIER_API_KEY: !Ref ApiKeyPlatinumTierParameter PREMIUM_TIER_API_KEY: !Ref ApiKeyPremiumTierParameter STANDARD_TIER_API_KEY: !Ref ApiKeyStandardTierParameter BASIC_TIER_API_KEY: !Ref ApiKeyBasicTierParameter POWERTOOLS_SERVICE_NAME: "TenantRegistration.RegisterTenant" AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref RegisterTenantFunctionCanaryErrorsAlarm RegisterTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${RegisterTenantFunction}:live" - Name: FunctionName Value: !Ref RegisterTenantFunction - Name: ExecutedVersion Value: !GetAtt RegisterTenantFunction.Version.Version #Tenant Provisioning ProvisionTenantLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub tenant-provisioning-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub tenant-provisioning-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:PutItem - dynamodb:DeleteItem Resource: - !Ref TenantStackMappingTableArn - Effect: Allow Action: - codepipeline:StartPipelineExecution Resource: - !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:serverless-saas-pipeline - Effect: Allow Action: - cloudformation:DeleteStack Resource: "*" ProvisionTenantFunction: Type: AWS::Serverless::Function DependsOn: ProvisionTenantLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-provisioning.provision_tenant Runtime: python3.9 Role: !GetAtt ProvisionTenantLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: TENANT_STACK_MAPPING_TABLE_NAME: !Ref TenantStackMappingTableName AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref ProvisionTenantFunctionCanaryErrorsAlarm ProvisionTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${ProvisionTenantFunction}:live" - Name: FunctionName Value: !Ref ProvisionTenantFunction - Name: ExecutedVersion Value: !GetAtt ProvisionTenantFunction.Version.Version DeProvisionTenantLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub tenant-deprovisioning-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub tenant-deprovisioning-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 #Since this lambda is invoking cloudformation which is inturn removing AWS resources, we are giving overly permissive permissions to this lambda. #You can limit this based upon your use case and AWS Resources you need to remove. Statement: - Effect: Allow Action: "*" Resource: "*" DeProvisionTenantFunction: Type: AWS::Serverless::Function DependsOn: DeProvisionTenantLambdaExecutionRole Properties: CodeUri: ../../TenantManagementService/ Handler: tenant-provisioning.deprovision_tenant Runtime: python3.9 Role: !GetAtt DeProvisionTenantLambdaExecutionRole.Arn Tracing: Active Layers: - !Ref ServerlessSaaSLayers Environment: Variables: TENANT_STACK_MAPPING_TABLE_NAME: !Ref TenantStackMappingTableName AutoPublishAlias: live DeploymentPreference: Enabled: !Ref LambdaCanaryDeploymentPreference Type: Canary10Percent5Minutes Alarms: - !Ref DeProvisionTenantFunctionCanaryErrorsAlarm DeProvisionTenantFunctionCanaryErrorsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function canary errors ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 2 MetricName: Errors Namespace: AWS/Lambda Period: 60 Statistic: Sum Threshold: 0 Dimensions: - Name: Resource Value: !Sub "${DeProvisionTenantFunction}:live" - Name: FunctionName Value: !Ref DeProvisionTenantFunction - Name: ExecutedVersion Value: !GetAtt DeProvisionTenantFunction.Version.Version UpdateSettingsTableLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub update-settingstable-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub update-settingstable-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:PutItem Resource: !Ref ServerlessSaaSSettingsTableArn UpdateSettingsTableFunction: Type: AWS::Serverless::Function DependsOn: UpdateSettingsTableLambdaExecutionRole Properties: CodeUri: ../../custom_resources/ Handler: update_settings_table.handler Runtime: python3.9 Role: !GetAtt UpdateSettingsTableLambdaExecutionRole.Arn Layers: - !Ref ServerlessSaaSLayers UpdateTenantStackMapTableLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub update-tenantstackmap-lambda-execution-role-${AWS::Region} Path: "/" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: !Sub update-tenantstackmap-lambda-execution-policy-${AWS::Region} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:PutItem Resource: !Ref TenantStackMappingTableArn UpdateTenantStackMapTableFunction: Type: AWS::Serverless::Function DependsOn: UpdateTenantStackMapTableLambdaExecutionRole Properties: CodeUri: ../../custom_resources/ Handler: update_tenantstackmap_table.handler Runtime: python3.9 Role: !GetAtt UpdateTenantStackMapTableLambdaExecutionRole.Arn Layers: - !Ref ServerlessSaaSLayers Outputs: RegisterTenantLambdaExecutionRoleArn: Value: !GetAtt RegisterTenantLambdaExecutionRole.Arn TenantManagementLambdaExecutionRoleArn: Value: !GetAtt TenantManagementLambdaExecutionRole.Arn RegisterTenantFunctionArn: Value: !GetAtt RegisterTenantFunction.Arn ProvisionTenantFunctionArn: Value: !GetAtt ProvisionTenantFunction.Arn DeProvisionTenantFunctionArn: Value: !GetAtt DeProvisionTenantFunction.Arn ActivateTenantFunctionArn: Value: !GetAtt ActivateTenantFunction.Arn GetTenantConfigFunctionArn: Value: !GetAtt GetTenantConfigFunction.Arn GetTenantsFunctionArn: Value: !GetAtt GetTenantsFunction.Arn CreateTenantFunctionArn: Value: !GetAtt CreateTenantFunction.Arn GetTenantFunctionArn: Value: !GetAtt GetTenantFunction.Arn DeactivateTenantFunctionArn: Value: !GetAtt DeactivateTenantFunction.Arn UpdateTenantFunctionArn: Value: !GetAtt UpdateTenantFunction.Arn GetUsersFunctionArn: Value: !GetAtt GetUsersFunction.Arn GetUserFunctionArn: Value: !GetAtt GetUserFunction.Arn UpdateUserFunctionArn: Value: !GetAtt UpdateUserFunction.Arn DisableUserFunctionArn: Value: !GetAtt DisableUserFunction.Arn CreateTenantAdminUserFunctionArn: Value: !GetAtt CreateTenantAdminUserFunction.Arn CreateUserFunctionArn: Value: !GetAtt CreateUserFunction.Arn DisableUsersByTenantFunctionArn: Value: !GetAtt DisableUsersByTenantFunction.Arn EnableUsersByTenantFunctionArn: Value: !GetAtt EnableUsersByTenantFunction.Arn SharedServicesAuthorizerFunctionArn: Value: !GetAtt SharedServicesAuthorizerFunction.Arn BusinessServicesAuthorizerFunctionArn: Value: !GetAtt BusinessServicesAuthorizerFunction.Arn UpdateSettingsTableFunctionArn: Value: !GetAtt UpdateSettingsTableFunction.Arn UpdateTenantStackMapTableFunctionArn: Value: !GetAtt UpdateTenantStackMapTableFunction.Arn