AWSTemplateFormatVersion: 2010-09-09 Description: 'This template creates SidewalkSampleApplication stack. **WARNING** You will be billed for the AWS resources used if you create a stack from this template' Parameters: SidewalkDestinationName: Type: String Default: SidewalkDestination SidewalkDestinationAlreadyExists: Type: String AllowedValues: - true - false Default: false Conditions: ShouldCreateDestination: !Equals - !Ref SidewalkDestinationAlreadyExists - false Resources: # --------------------------- # DynamoDb related resources # --------------------------- # Table for storing Sidewalk devices SidewalkDevices: Type: AWS::DynamoDB::Table Properties: BillingMode: PROVISIONED AttributeDefinitions: - AttributeName: wireless_device_id AttributeType: "S" KeySchema: - AttributeName: wireless_device_id KeyType: HASH TimeToLiveSpecification: AttributeName: time_to_live Enabled: true ProvisionedThroughput: ReadCapacityUnits: 2 WriteCapacityUnits: 2 TableName: SidewalkDevices # Table for storing sensor measurements SidewalkMeasurements: Type: AWS::DynamoDB::Table Properties: TableName: SidewalkMeasurements BillingMode: PROVISIONED AttributeDefinitions: - AttributeName: timestamp AttributeType: "N" - AttributeName: wireless_device_id AttributeType: "S" KeySchema: - AttributeName: timestamp KeyType: HASH GlobalSecondaryIndexes: - IndexName: "wireless_device_id" KeySchema: - AttributeName: wireless_device_id KeyType: HASH - AttributeName: timestamp KeyType: RANGE Projection: ProjectionType: ALL ProvisionedThroughput: ReadCapacityUnits: 2 WriteCapacityUnits: 2 TimeToLiveSpecification: AttributeName: time_to_live Enabled: true ProvisionedThroughput: ReadCapacityUnits: 2 WriteCapacityUnits: 2 # ------------------------- # Lambda related resources # ------------------------- # Uplink Lambda's execution role with CloudWatch write access SidewalkUplinkLambdaExecutionRole: Type: AWS::IAM::Role DependsOn: - SidewalkDownlinkLambda - SidewalkDevices - SidewalkMeasurements Properties: RoleName: SidewalkUplinkLambdaExecutionRole Description: Allows SidewalkUplinkLambda to call AWS services on your behalf. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: SidewalkUplinkLambdaInlinePolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/SidewalkUplinkLambda:* - Effect: Allow Action: - lambda:InvokeFunction Resource: - !GetAtt SidewalkDownlinkLambda.Arn - Effect: Allow Action: - dynamodb:BatchGetItem - dynamodb:UpdateTimeToLive - dynamodb:PutItem - dynamodb:DescribeTable - dynamodb:DeleteItem - dynamodb:GetItem - dynamodb:Scan - dynamodb:Query - dynamodb:UpdateItem - dynamodb:DescribeTimeToLive Resource: - !GetAtt SidewalkDevices.Arn - !GetAtt SidewalkMeasurements.Arn # Downlink Lambda's execution role with CloudWatch write access and iot device access SidewalkDownlinkLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkDownlinkLambdaExecutionRole Description: Allows SidewalkDownlinkLambda to call AWS services on your behalf. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: SidewalkDownlinkLambdaInlinePolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/SidewalkDownlinkLambda:* - Effect: Allow Action: - iotwireless:SendDataToWirelessDevice Resource: - !Sub arn:aws:iotwireless:${AWS::Region}:${AWS::AccountId}:WirelessDevice/* # Db handler Lambda's execution role with CloudWatch write access and iot device access SidewalkDbHandlerLambdaExecutionRole: Type: AWS::IAM::Role DependsOn: - SidewalkDevices - SidewalkMeasurements Properties: RoleName: SidewalkDbHandlerLambdaExecutionRole Description: Allows SidewalkDbHandlerLambda to call AWS services on your behalf. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: SidewalkDbHandlerLambdaInlinePolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/SidewalkDbHandlerLambda:* - Effect: Allow Action: - dynamodb:BatchGetItem - dynamodb:UpdateTimeToLive - dynamodb:PutItem - dynamodb:DescribeTable - dynamodb:DeleteItem - dynamodb:GetItem - dynamodb:Scan - dynamodb:Query - dynamodb:UpdateItem - dynamodb:DescribeTimeToLive Resource: - !GetAtt SidewalkDevices.Arn - !GetAtt SidewalkMeasurements.Arn # Token generator Lambda's execution role with basic lambda permissions. SidewalkTokenGeneratorLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkTokenGeneratorLambdaExecutionRole Description: Allows SidewalkTokenGeneratorLambda to assume cloudfront role and authenticate requests. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com - apigateway.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' DeletionPolicy: Delete # User authenticator Lambda's execution role with basic lambda permissions. SidewalkUserAuthenticatorLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkUserAuthenticatorLambdaExecutionRole Description: Allows SidewalkUserAuthenticatorLambda to assume cloudfront role and authenticate requests. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com - apigateway.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' DeletionPolicy: Delete # Token authenticator Lambda's execution role with basic lambda permissions. SidewalkTokenAuthenticatorLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkTokenAuthenticatorLambdaExecutionRole Description: Allows SidewalkTokenAuthenticatorLambda to assume cloudfront role and authenticate requests. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com - apigateway.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' DeletionPolicy: Delete # SidewalkUplinkLambda function. Handles uplink messages SidewalkUplinkLambda: Type: AWS::Lambda::Function DependsOn: SidewalkUplinkLambdaExecutionRole Properties: FunctionName: SidewalkUplinkLambda Description: Receives uplink messages and logs them in the CloudWatch log group. Handler: uplink_lambda_handler.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkUplinkLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." # SidewalkDownlinkLambda function. Handles downlink messages SidewalkDownlinkLambda: Type: AWS::Lambda::Function DependsOn: - SidewalkDownlinkLambdaExecutionRole - CloudFrontDistribution Properties: FunctionName: SidewalkDownlinkLambda Description: Sends downlink messages and logs them in the CloudWatch log group. Handler: downlink_lambda_handler.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkDownlinkLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." Environment: Variables: GUI_BUCKET_URL: Fn::Join: - '' - - https:// - !GetAtt CloudFrontDistribution.DomainName # SidewalkDbHandlerLambda function. Handles read requests to databases SidewalkDbHandlerLambda: Type: AWS::Lambda::Function DependsOn: - SidewalkDbHandlerLambdaExecutionRole - CloudFrontDistribution Properties: FunctionName: SidewalkDbHandlerLambda Description: Handles communication with db. Handler: db_handler_lambda_handler.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkDbHandlerLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." Environment: Variables: GUI_BUCKET_URL: Fn::Join: - '' - - https:// - !GetAtt CloudFrontDistribution.DomainName # SidewalkTokenGeneratorLambda function. Handles signing jwt tokens with login info SidewalkTokenGeneratorLambda: Type: AWS::Lambda::Function Properties: FunctionName: SidewalkTokenGeneratorLambda Description: Signs user requests jwt Handler: index.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkTokenGeneratorLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." DeletionPolicy: Delete # SidewalkUserAuthenticatorLambda function. Handles api gw user authentication. SidewalkUserAuthenticatorLambda: Type: AWS::Lambda::Function Properties: FunctionName: SidewalkUserAuthenticatorLambda Description: Authentication cloudfront users Handler: index.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkUserAuthenticatorLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." DeletionPolicy: Delete # SidewalkTokenAuthenticatorLambda function. Handles jwt authentication. SidewalkTokenAuthenticatorLambda: Type: AWS::Lambda::Function Properties: FunctionName: SidewalkTokenAuthenticatorLambda Description: Authenticates user jwt token Handler: index.lambda_handler MemorySize: 128 Role: !GetAtt SidewalkTokenAuthenticatorLambdaExecutionRole.Arn Runtime: python3.9 Timeout: 3 PackageType: Zip Code: ZipFile: "Please run deploy_stack.py script to upload the code." DeletionPolicy: Delete # ----------------------------- # CloudWatch related resources # ----------------------------- # Log group for storing IoT rule errors SidewalkRuleErrorsLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: SidewalkRuleErrors RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkUplinkLambda logs SidewalkUplinkLambdaLogGroup: DependsOn: SidewalkUplinkLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkUplinkLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkDownlinkLambda logs SidewalkDownlinkLambdaLogGroup: DependsOn: SidewalkDownlinkLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkDownlinkLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkDbHandlerLambda logs SidewalkDbHandlerLambdaLogGroup: DependsOn: SidewalkDbHandlerLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkDbHandlerLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkUserAuthenticatorLambda logs SidewalkUserAuthenticatorLambdaLogGroup: DependsOn: SidewalkUserAuthenticatorLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkUserAuthenticatorLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkTokenGeneratorLambdaLambda logs SidewalkTokenGeneratorLambdaLogGroup: DependsOn: SidewalkTokenGeneratorLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkTokenGeneratorLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # Log group for storing SidewalkTokenAuthenticatorLambda logs SidewalkTokenAuthenticatorLambdaLogGroup: DependsOn: SidewalkTokenAuthenticatorLambda Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/lambda/${SidewalkTokenAuthenticatorLambda}' RetentionInDays: 7 UpdateReplacePolicy: Delete DeletionPolicy: Delete # ------------------------------ # API Gateway related resources # ------------------------------ # API Gateway methods SidewalkApiGateway: Type: AWS::ApiGateway::RestApi Properties: Name: sensor-monitoring-app Description: Sensor Monitoring App API ApiResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt SidewalkApiGateway.RootResourceId RestApiId: !Ref SidewalkApiGateway PathPart: api ApiPostMethod: Type: AWS::ApiGateway::Method DependsOn: - SidewalkTokenAuthorizer Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref SidewalkTokenAuthorizer HttpMethod: POST Integration: IntegrationHttpMethod: POST Type: AWS_PROXY IntegrationResponses: - StatusCode: 200 Uri: !Sub - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations - lambdaArn: !GetAtt SidewalkDownlinkLambda.Arn MethodResponses: - StatusCode: 200 ResponseModels: application/json: 'Empty' ResponseParameters: method.response.header.Access-Control-Allow-Origin: false ResourceId: !Ref ApiResource RestApiId: !Ref SidewalkApiGateway AuthResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt ApiResource.ResourceId RestApiId: !Ref SidewalkApiGateway PathPart: auth ApiAuthPostMethod: Type: AWS::ApiGateway::Method DependsOn: - SidewalkUserAuthorizer - SidewalkTokenGeneratorLambda - AuthResource Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref SidewalkUserAuthorizer HttpMethod: POST Integration: IntegrationHttpMethod: POST Type: AWS_PROXY IntegrationResponses: - StatusCode: 200 Uri: !Sub - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations - lambdaArn: !GetAtt SidewalkTokenGeneratorLambda.Arn MethodResponses: - StatusCode: 200 ResponseModels: application/json: 'Empty' ResponseParameters: method.response.header.Access-Control-Allow-Origin: false ResourceId: !Ref AuthResource RestApiId: !Ref SidewalkApiGateway ApiOptionsMethod: Type: AWS::ApiGateway::Method DependsOn: - SidewalkTokenAuthorizer Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref SidewalkTokenAuthorizer HttpMethod: OPTIONS Integration: Type: MOCK PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Origin: "'*'" MethodResponses: - StatusCode: 200 ResponseModels: application/json: 'Empty' ResponseParameters: method.response.header.Access-Control-Allow-Headers: false method.response.header.Access-Control-Allow-Methods: false method.response.header.Access-Control-Allow-Origin: false ResourceId: !Ref ApiResource RestApiId: !Ref SidewalkApiGateway ProxyResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt ApiResource.ResourceId RestApiId: !Ref SidewalkApiGateway PathPart: '{proxy+}' ProxyGetMethod: Type: AWS::ApiGateway::Method DependsOn: - SidewalkTokenAuthorizer Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref SidewalkTokenAuthorizer HttpMethod: GET Integration: IntegrationHttpMethod: POST Type: AWS_PROXY IntegrationResponses: - StatusCode: 200 Uri: !Sub - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations - lambdaArn: !GetAtt SidewalkDbHandlerLambda.Arn MethodResponses: - StatusCode: 200 ResponseModels: application/json: 'Empty' ResponseParameters: method.response.header.Access-Control-Allow-Origin: false ResourceId: !Ref ProxyResource RestApiId: !Ref SidewalkApiGateway ProxyOptionsMethod: Type: AWS::ApiGateway::Method DependsOn: - SidewalkTokenAuthorizer Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref SidewalkTokenAuthorizer HttpMethod: OPTIONS Integration: Type: MOCK PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'" method.response.header.Access-Control-Allow-Origin: "'*'" MethodResponses: - StatusCode: 200 ResponseModels: application/json: 'Empty' ResponseParameters: method.response.header.Access-Control-Allow-Headers: false method.response.header.Access-Control-Allow-Methods: false method.response.header.Access-Control-Allow-Origin: false ResourceId: !Ref ProxyResource RestApiId: !Ref SidewalkApiGateway # API Gateway jwt authorizer SidewalkTokenAuthorizer: Type: AWS::ApiGateway::Authorizer DependsOn: - SidewalkApiGateway - SidewalkTokenAuthenticatorLambda Properties: Name: SidewalkTokenAuthorizer RestApiId: !Ref SidewalkApiGateway AuthorizerResultTtlInSeconds: 3600 Type: TOKEN AuthorizerUri: !Join - '' - - !Sub arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/ - !GetAtt SidewalkTokenAuthenticatorLambda.Arn - /invocations IdentitySource: method.request.header.AuthorizationToken # API Gateway username authorizer SidewalkUserAuthorizer: Type: AWS::ApiGateway::Authorizer DependsOn: - SidewalkApiGateway - SidewalkUserAuthenticatorLambda Properties: Name: SidewalkUserAuthorizer RestApiId: !Ref SidewalkApiGateway AuthorizerResultTtlInSeconds: 0 # no caching Type: REQUEST AuthorizerUri: !Join - '' - - !Sub arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/ - !GetAtt SidewalkUserAuthenticatorLambda.Arn - /invocations IdentitySource: method.request.header.Username # API Gateway deployment SidewalkApiGatewayDeployment: Type: AWS::ApiGateway::Deployment DependsOn: - ApiPostMethod - ApiOptionsMethod - ProxyGetMethod - ProxyOptionsMethod Properties: RestApiId: !Ref SidewalkApiGateway StageName: dev # ApiGw usage plan. Provides throttling SidewalkApiGatewayUsagePlan: Type: AWS::ApiGateway::UsagePlan DependsOn: - SidewalkApiGateway - SidewalkApiGatewayDeployment Properties: ApiStages: - ApiId: !Ref SidewalkApiGateway Stage: dev Description: Provides throttling for SidewalkSampleApplication api gw Quota: Limit: 86400 # limit to one request per second Period: DAY Throttle: BurstLimit: 30 # how many requests can happen in burst RateLimit: 30 # how many requests can happen in a second UsagePlanName: SidewalkSampleApplication usage plan # Set SidewalkDownlinkLambda permissions regarding API Gateway SidewalkDownlinkLambdaPermissionsForApiGateway: Type: AWS::Lambda::Permission DependsOn: - SidewalkDownlinkLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkDownlinkLambda Principal: apigateway.amazonaws.com SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SidewalkApiGateway}/*/POST/api # Set SidewalkDbHandlerLambda permissions regarding API Gateway SidewalkDbHandlerLambdaPermissionsForApiGateway: Type: AWS::Lambda::Permission DependsOn: - SidewalkDbHandlerLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkDbHandlerLambda Principal: apigateway.amazonaws.com SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SidewalkApiGateway}/*/GET/api/* # Set SidewalkUserAuthenticatorLambda permissions regarding API Gateway SidewalkUserAuthenticatorLambdaPermissionsForApiGateway: Type: AWS::Lambda::Permission DependsOn: - SidewalkUserAuthenticatorLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkUserAuthenticatorLambda Principal: apigateway.amazonaws.com SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SidewalkApiGateway}/* # Set SidewalkTokenGeneratorLambda permissions regarding API Gateway SidewalkTokenGeneratorLambdaPermissionsForApiGateway: Type: AWS::Lambda::Permission DependsOn: - SidewalkTokenGeneratorLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkTokenGeneratorLambda Principal: apigateway.amazonaws.com SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SidewalkApiGateway}/*/POST/api/auth # Set SidewalkTokenAuthenticatorLambda permissions regarding API Gateway SidewalkTokenAuthenticatorLambdaPermissionsForApiGateway: Type: AWS::Lambda::Permission DependsOn: - SidewalkTokenAuthenticatorLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkTokenAuthenticatorLambda Principal: apigateway.amazonaws.com SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SidewalkApiGateway}/* # ------------------------------------------- # IoT related resources for uplink reception # ------------------------------------------- # AWS IoT wireless destination role with access to the sidewalk/app_data topic SidewalkDestinationRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkDestinationRole Description: Allows destination to publish to the sidewalk/app_data topic on your behalf. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - iotwireless.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: SidewalkDestinationRoleInlinePolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - iot:Publish Resource: - !Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/sidewalk/app_data - Effect: Allow Action: - iot:DescribeEndpoint Resource: - '*' # AWS IoT wireless destination SidewalkDestination: Type: AWS::IoTWireless::Destination DependsOn: SidewalkDestinationRole Condition: ShouldCreateDestination Properties: Name: Ref: SidewalkDestinationName Description: Destination for uplink messages from Sidewalk devices. ExpressionType: MqttTopic Expression: sidewalk/app_data RoleArn: !GetAtt SidewalkDestinationRole.Arn # AWS IoT wireless rule role with write access to the SidewalkRuleErrors SidewalkRuleRole: Type: AWS::IAM::Role Properties: RoleName: SidewalkRuleRole Description: Role assumed by the sidewalk rules, which preprocess and dispatch messages. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - iot.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: SidewalkRuleInlinePolicy-SidewalkRuleErrorsWriteAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:DescribeLogStreams - logs:PutLogEvents Resource: - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:SidewalkRuleErrors:* # AWS IoT wireless rule for uplink messages. Passes incoming uplink messages to the SidewalkUplinkLambda SidewalkUplinkRule: Type: AWS::IoT::TopicRule DependsOn: - SidewalkUplinkLambda - SidewalkRuleRole Properties: RuleName: SidewalkUplinkRule TopicRulePayload: AwsIotSqlVersion: 2016-03-23 Description: Rule for processing Sidewalk uplink messages for Sample Application purposes. Sql: SELECT * as uplink FROM 'sidewalk/app_data' Actions: - Lambda: FunctionArn: !GetAtt SidewalkUplinkLambda.Arn ErrorAction: CloudwatchLogs: LogGroupName: SidewalkRuleErrors RoleArn: !GetAtt SidewalkRuleRole.Arn RuleDisabled: False # Set SidewalkUplinkLambda permissions regarding SidewalkUplinkRule SidewalkUplinkLambdaPermissionsForUplinks: Type: AWS::Lambda::Permission DependsOn: - SidewalkUplinkLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkUplinkLambda Principal: iot.amazonaws.com SourceArn: !Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:rule/SidewalkUplinkRule # ------------------------------------------------- # IoT related resources for notification reception # ------------------------------------------------- # Policy for receiving wireless event notifications SidewalkReceiveWirelessEventNotificationsPolicy: Type: AWS::IoT::Policy Properties: PolicyName: SidewalkReceiveWirelessEventNotificationsPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - iot:Subscribe - iot:Receive Resource: - !Sub arn:aws:iotwireless:${AWS::Region}:${AWS::AccountId}:/$aws/iotwireless/events/device_registration_state/* - !Sub arn:aws:iotwireless:${AWS::Region}:${AWS::AccountId}:/$aws/iotwireless/events/proximity/* - !Sub arn:aws:iotwireless:${AWS::Region}:${AWS::AccountId}:/$aws/iotwireless/events/message_delivery_status/* # AWS IoT wireless rule for notification. Passes incoming notifications to the SidewalkUplinkLambda SidewalkNotificationRule: Type: AWS::IoT::TopicRule DependsOn: - SidewalkUplinkLambda - SidewalkRuleRole Properties: RuleName: SidewalkNotificationRule TopicRulePayload: AwsIotSqlVersion: 2016-03-23 Description: Rule for processing Sidewalk notifications. Sql: SELECT * as notification FROM '$aws/iotwireless/events/+/+/sidewalk/wireless_devices' Actions: - Lambda: FunctionArn: !GetAtt SidewalkUplinkLambda.Arn ErrorAction: CloudwatchLogs: LogGroupName: SidewalkRuleErrors RoleArn: !GetAtt SidewalkRuleRole.Arn RuleDisabled: False # Set permissions for SidewalkUplinkLambda SidewalkUplinkLambdaPermissionsForNotifications: Type: AWS::Lambda::Permission DependsOn: - SidewalkUplinkLambda Properties: Action: lambda:InvokeFunction FunctionName: SidewalkUplinkLambda Principal: iot.amazonaws.com SourceArn: !Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:rule/SidewalkNotificationRule # --------------------- # S3 related resources # --------------------- # S3 bucket for hosting Web Application SidewalkWebAppBucket: Type: 'AWS::S3::Bucket' Properties: # BucketName consists of 'sensor-monitoring-app-' prefix and 32 chars-long GUID taken from the StackId BucketName: !Join - '-' - - sensor-monitoring-app - !Select [2, !Split [/, !Ref AWS::StackId ]] AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: TRUE BlockPublicPolicy: TRUE IgnorePublicAcls: TRUE RestrictPublicBuckets: TRUE DeletionPolicy: Delete # Bucket policy to allow communication with cloudFront S3BucketPolicy: Type: AWS::S3::BucketPolicy DependsOn: - SidewalkWebAppBucket - CloudFrontDistribution Properties: Bucket: Ref: SidewalkWebAppBucket PolicyDocument: Version: '2012-10-17' Statement: - Action: - s3:GetObject Effect: Allow Resource: Fn::Join: - '' - - !GetAtt SidewalkWebAppBucket.Arn - /* Principal: Service: cloudfront.amazonaws.com Condition: StringEquals: AWS:SourceArn: Fn::Join: - '/' - - !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution - !Ref CloudFrontDistribution # ------------------------------ # Cloud Front related resources # ------------------------------ # Cloud Front Origin Access Control CloudFrontOAC: Type: AWS::CloudFront::OriginAccessControl Properties: OriginAccessControlConfig: Description: SidewalkSampleApplication OAC to s3 bucket Name: SidewalkSampleApplicationOAC OriginAccessControlOriginType: s3 SigningBehavior: always SigningProtocol: sigv4 # Cloud Front Origin Request Policy. Whitelists AuthorizationToken and Username headers. CloudFrontAuthOriginRequestPolicy: Type: AWS::CloudFront::OriginRequestPolicy Properties: OriginRequestPolicyConfig: Comment: SidewalkSampleApp Authorization origin access policy CookiesConfig: CookieBehavior: none HeadersConfig: HeaderBehavior: whitelist Headers: - 'AuthorizationToken' - 'Username' Name: SidewalkSampleApplicationAuthOriginRequestPolicy QueryStringsConfig: QueryStringBehavior: none # Cloud Front distribution. Hosts S3 bucket CloudFrontDistribution: Type: AWS::CloudFront::Distribution DependsOn: - SidewalkWebAppBucket - SidewalkApiGateway - CloudFrontOAC Properties: DistributionConfig: DefaultCacheBehavior: Compress: true DefaultTTL: 100 ForwardedValues: QueryString: true MaxTTL: 500 TargetOriginId: Fn::Sub: ${AWS::StackName}-root ViewerProtocolPolicy: redirect-to-https Enabled: true DefaultRootObject: index.html IPV6Enabled: true Origins: - DomainName: !GetAtt SidewalkWebAppBucket.DomainName Id: Fn::Sub: ${AWS::StackName}-root OriginAccessControlId: !Ref CloudFrontOAC S3OriginConfig: OriginAccessIdentity: "" # empty access identity allows use of OAC - DomainName: Fn::Join: - '.' - - !Ref SidewalkApiGateway - "execute-api" - Fn::Sub: ${AWS::Region} - "amazonaws.com" Id: Fn::Sub: ${AWS::StackName}-root-Api-Gw CustomOriginConfig: OriginProtocolPolicy: https-only OriginReadTimeout: 20 OriginPath: /dev OriginGroups: Items: - FailoverCriteria: StatusCodes: Items: - 400 Quantity: 1 Id: Bucket and apiGw Members: Items: - OriginId: Fn::Sub: ${AWS::StackName}-root-Api-Gw - OriginId: Fn::Sub: ${AWS::StackName}-root Quantity: 2 Quantity: 1 CacheBehaviors: - AllowedMethods: - GET - HEAD - OPTIONS - PUT - PATCH - POST - DELETE PathPattern: /api/* OriginRequestPolicyId: !Ref CloudFrontAuthOriginRequestPolicy TargetOriginId: Fn::Sub: ${AWS::StackName}-root-Api-Gw ViewerProtocolPolicy: redirect-to-https CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # Caching disabled PriceClass: PriceClass_All Outputs: SidewalkApiId: Value: !Ref SidewalkApiGateway SidewalkWebAppBucketName: Value: !Ref SidewalkWebAppBucket Description: SidewalkWebAppBucketName CloudFrontDistribution: Description: CloudFront distribution Value: Fn::GetAtt: - CloudFrontDistribution - DomainName