# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. --- AWSTemplateFormatVersion: '2010-09-09' Description: AWS template for SiteWise demo Outputs: StackArn: Value: {Ref: 'AWS::StackId'} SiteWiseAsset1Id: Description: The AssetId for Asset 1 in AWS IoT SiteWise, Data Scientists use this for L4E model Value: Ref: IoTSiteWiseDemoPumpAsset1 SiteWiseAsset2Id: Description: The AssetId for Asset 2 in AWS IoT SiteWise, Data Scientists use this for L4E model Value: Ref: IoTSiteWiseDemoPumpAsset2 Parameters: DemoDurationDays: Type: Number Default: 7 AllowedValues: [2, 3, 4, 5, 6, 7, 14] FirstPropertyGroup: Type: String Description: The list of property names Default: Sensor0 Sensor1 Sensor2 Sensor3 Sensor4 Sensor5 SecondPropertyGroup: Type: String Description: The list of property names Default: Sensor6 Sensor7 Sensor8 Sensor9 Sensor10 Sensor11 ThirdPropertyGroup: Type: String Description: The list of property names Default: Sensor12 Sensor13 Sensor14 Sensor15 Sensor16 Sensor17 FourthPropertyGroup: Type: String Description: The list of property names Default: Sensor18 Sensor19 Sensor20 Sensor21 Sensor22 Sensor23 FifthPropertyGroup: Type: String Description: The list of property names Default: Sensor24 Sensor25 Sensor26 Sensor27 Sensor28 Sensor29 Conditions: # SiteWise (and our lambda bucket) only exists in these regions ValidRegion: Fn::Or: - Fn::Equals: - Ref: AWS::Region - us-east-1 - Fn::Equals: - Ref: AWS::Region - us-west-2 - Fn::Equals: - Ref: AWS::Region - eu-west-1 - Fn::Equals: - Ref: AWS::Region - eu-central-1 - Fn::Equals: - Ref: AWS::Region - ap-southeast-1 - Fn::Equals: - Ref: AWS::Region - ap-southeast-2 - Fn::Equals: - Ref: AWS::Region - cn-north-1 Resources: # IoT Events Alarm Models IoTSiteWiseDemoSiteWiseSubscriptionRole: Type: AWS::IAM::Role Condition: ValidRegion Properties: Path: "/" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - iotsitewise.amazonaws.com Policies: - PolicyName: IotEventBatchPutMessageAccessPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - iotevents:BatchPutMessage Resource: "*" IoTSiteWiseDemoIotEventsActionExecutionRole: Type: AWS::IAM::Role Properties: Path: "/" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - iotevents.amazonaws.com - iot.amazonaws.com Policies: - PolicyName: IoTSiteWiseDemoIoTEventsAllowPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - iotsitewise:BatchPutAssetPropertyValue - sns:Publish - firehose:PutRecord - lambda:InvokeFunction - sqs:SendMessage - firehose:PutRecordBatch - iot:Publish - iotevents:DescribeLoggingOptions - iotevents:ListDetectorModels - iotevents:PutLoggingOptions - iotevents:ListInputs - sso-directory:DescribeUser Resource: "*" IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction: Type: AWS::Lambda::Function Condition: ValidRegion Properties: Description: IoT SiteWise Demo function handling the lifecycle of IoTEvents Alarm Model resources. This function will be deleted at the end of the demo. Code: S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region} S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip Handler: iotevents_alarm_models.handler MemorySize: 128 Role: Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, Arn] Runtime: python3.7 Timeout: 900 IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole: Type: AWS::IAM::Role Condition: ValidRegion Properties: Description: Role for IoT SiteWise Demo IoTEvents Alarm Model resources lifecycle. This role will be deleted at the end of the demo. AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com Version: '2012-10-17' Policies: - PolicyName: IoTSiteWiseDemo-IoTEventsAlarmModelLifecycleFunction-RolePolicy PolicyDocument: Statement: # CloudWatch logging - Action: - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogGroup Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" - Action: - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogGroup Effect: Deny NotResource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" # SiteWise & IoT Events & pass role - Action: - iotsitewise:UpdateAssetModel - iotsitewise:DescribeAssetModel - iotsitewise:UpdateSubscription - iotsitewise:UpdateAssetModelPropertyRouting - iotevents:CreateAlarmModel - iotevents:DeleteAlarmModel - iotevents:DescribeAlarmModel - iotevents:updateAlarmModel - iam:PassRole Effect: Allow Resource: "*" Version: '2012-10-17' IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup: Type: AWS::Logs::LogGroup DependsOn: - IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction - IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole Condition: ValidRegion Properties: LogGroupName: Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction}" IoTSiteWiseDemoPumpL4EAlarmModel: Type: Custom::IoTSiteWiseDemoPumpL4EAlarmModel DependsOn: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, IoTSiteWiseDemoSiteWiseSubscriptionRole, IoTSiteWiseDemoIotEventsActionExecutionRole, IoTSiteWiseDemoPumpAssetModel, IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup] Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction, Arn] name: DemoPumpL4EAlarmModel description: SiteWise Demo Alarm model for L4E alarm. It will be deleted at the end of the demo. assetModelId: { Ref: IoTSiteWiseDemoPumpAssetModel } assetModelCompositeModelName: l4eAlarm roleArn: Fn::GetAtt: [IoTSiteWiseDemoIotEventsActionExecutionRole, Arn] sitewiseSubscriptionArn: Fn::GetAtt: [IoTSiteWiseDemoSiteWiseSubscriptionRole, Arn] severity: 1 alarmRule: { simpleRule: { inputProperty: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] }, comparisonOperator: GREATER_OR_EQUAL, threshold: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, L4E Alarm Threshold id] }, } } alarmCapabilities: { initializationConfiguration: { disabledOnInitialization: false }, acknowledgeFlow: { enabled: false } } alarmEventActions: { alarmActions: [ { iotSiteWise: { assetId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] }, propertyId: lambda function will find alarm state property by composite model name } } ] } IoTSiteWiseDemoStationAbnormalyAlarmModel: Type: Custom::IoTSiteWiseDemoStationAbnormalyAlarmModel DependsOn: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, IoTSiteWiseDemoSiteWiseSubscriptionRole, IoTSiteWiseDemoIotEventsActionExecutionRole, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup] Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction, Arn] name: DemoStationAbnormalyAlarmModel description: SiteWise Demo Alarm model for station abnormaly alarm. It will be deleted at the end of the demo. assetModelId: { Ref: IoTSiteWiseDemoPumpStationAssetModel } assetModelCompositeModelName: StationAbnormalyAlarm roleArn: Fn::GetAtt: [IoTSiteWiseDemoIotEventsActionExecutionRole, Arn] sitewiseSubscriptionArn: Fn::GetAtt: [IoTSiteWiseDemoSiteWiseSubscriptionRole, Arn] severity: 1 alarmRule: { simpleRule: { inputProperty: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Total L4E Score id] }, comparisonOperator: GREATER_OR_EQUAL, threshold: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Station Abnormaly Threshold id] }, } } alarmCapabilities: { initializationConfiguration: { disabledOnInitialization: false }, acknowledgeFlow: { enabled: true } } alarmEventActions: { alarmActions: [ { iotSiteWise: { assetId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Total L4E Score id] }, propertyId: lambda function will find alarm state property by composite model name } } ] } # Asset Models IoTSiteWiseDemoAssetModelLifecycleFunction: Type: AWS::Lambda::Function DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: IoT SiteWise Demo function handling the lifecycle of asset model resources. This function will be deleted at the end of the demo. Code: S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region} S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip Handler: sitewise_asset_models.handler MemorySize: 128 Role: Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunctionRole, Arn] Runtime: python3.7 Timeout: 900 IoTSiteWiseDemoAssetModelLifecycleFunctionRole: Type: AWS::IAM::Role DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Role for IoT SiteWise Demo asset model lifecycle. This role will be deleted at the end of the demo. AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: '2012-10-17' Policies: - PolicyName: IoTSiteWiseDemo-AssetModelLifecycleFunction-RolePolicy PolicyDocument: Statement: # CloudWatch logging - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Deny NotResource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" # SiteWise - Action: ['iotsitewise:CreateAssetModel','iotsitewise:DescribeAssetModel','iotsitewise:DeleteAssetModel', 'iotsitewise:UpdateAssetProperty'] Effect: Allow Resource: "*" Version: '2012-10-17' IoTSiteWiseDemoAssetModelLifecycleFunctionLogGroup: Type: AWS::Logs::LogGroup DependsOn: [IoTSiteWiseDemoAssetModelLifecycleFunction, IoTSiteWiseDemoDataGenerationFunctionRole] Condition: ValidRegion Properties: LogGroupName: Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoAssetModelLifecycleFunction}" IoTSiteWiseDemoPumpAssetModel: Type: Custom::IoTSiteWiseDemoPumpAssetModel DependsOn: [IoTSiteWiseDemoAssetModelLifecycleFunctionLogGroup, IoTSiteWiseDemoDataGenerationFunctionRole] Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunction, Arn] # These sitewise properties id will be available as attributes using Fn::GetAtt after asset model creation # For example, given metadata_sitewise_property_ids: [ Average Power, Overdrive State Time] # Fn::GetAtt: [IoTSiteWiseDemoPumpAssetModel, Average Power id] returns the id of the property named Average Power # Note: # A property must have the name field in order to be used as a metadata_sitewise_property_ids # This will only work on top level properties with string values metadata_sitewise_property_ids: [ L4E Alarm Threshold, Asset L4E Score, AVG L4E Score, ] name: Demo Pump Asset Model description: This is an asset model used in the IoT SiteWise Demo for representing a turbine in a wind farm. It will be deleted at the end of the demo. properties: [ # Attributes { name: Make, dataType: STRING, type: { attribute: { defaultValue: Amazon } } }, { name: Model, dataType: INTEGER, type: { attribute: { defaultValue: 500 } } }, { name: Location, dataType: STRING, type: { attribute: { defaultValue: Renton } } }, { name: L4E Alarm Threshold, dataType: DOUBLE, type: { attribute: { defaultValue: 0.9 } } }, # Measurements { name: Sensor0, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor1, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor2, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor3, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor4, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor5, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor6, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor7, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor8, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor9, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor10, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor11, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor12, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor13, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor14, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor15, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor16, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor17, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor18, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor19, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor20, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor21, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor22, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor23, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor24, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor25, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor26, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor27, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor28, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor29, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor0 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor1 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor2 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor3 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor4 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor5 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor6 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor7 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor8 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor9 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor10 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor11 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor12 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor13 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor14 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor15 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor16 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor17 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor18 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor19 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor20 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor21 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor22 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor23 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor24 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor25 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor26 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor27 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor28 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Sensor29 L4EScore, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, { name: Asset L4E Score, dataType: DOUBLE, unit: NA, type: { measurement: {} } }, #metric { name: AVG L4E Score, dataType: DOUBLE, unit: NA, type: { metric: { expression: avg(l4e_score), variables: [ { name: l4e_score, value: { propertyId: Asset L4E Score } } ], window: { tumbling: { interval: 5m } } } } } ] hierarchies: [ # optional, added for simplicity in lambda (not requiring to have a special case for with/without hierarchies) ] assetModelCompositeModels: [ { name: l4eAlarm, type: AWS/ALARM, properties: [ { name: AWS/ALARM_TYPE, dataType: STRING, unit: none, type: { attribute: { defaultValue: IOT_EVENTS } } }, { name: AWS/ALARM_STATE, dataType: STRUCT, dataTypeSpec: AWS/ALARM_STATE, unit: none, type: { measurement: {} } } ] } ] IoTSiteWiseDemoPumpStationAssetModel: Type: Custom::IoTSiteWiseDemoPumpStationAssetModel DependsOn: [IoTSiteWiseDemoPumpAssetModel, IoTSiteWiseDemoDataGenerationFunctionRole] Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunction, Arn] metadata_sitewise_property_ids: [ Total L4E Score, Station Abnormaly Threshold ] name: Demo Pump Station Asset Model description: This is an asset model used in the IoT SiteWise Demo for representing a pump station. It will be deleted at the end of the demo. properties: [ # Attributes { name: Reliability Manager, dataType: STRING, type: { attribute: { defaultValue: Mary Major } } }, { name: Code, dataType: INTEGER, type: { attribute: { defaultValue: 300 } } }, { name: Location, dataType: STRING, type: { attribute: { defaultValue: Renton } } }, { name: Station Abnormaly Threshold, dataType: DOUBLE, type: { attribute: { defaultValue: 1.8 } } }, # metric { name: Total L4E Score, dataType: DOUBLE, unit: NA, type: { metric: { expression: sum(abnormaly_score), variables: [ { name: abnormaly_score, value: { # Here we are referencing one of the "metadata_sitewise_property_ids" from the IoTSiteWiseDemoTurbineAssetModel propertyId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] }, hierarchyId: Pump Asset Model } } ], window: { tumbling: { interval: 5m } } } } } ] hierarchies: [ { name: Pump Asset Model, childAssetModelId: { Ref: IoTSiteWiseDemoPumpAssetModel } } ] assetModelCompositeModels: [ { name: StationAbnormalyAlarm, type: AWS/ALARM, properties: [ { name: AWS/ALARM_TYPE, dataType: STRING, unit: none, type: { attribute: { defaultValue: IOT_EVENTS } } }, { name: AWS/ALARM_STATE, dataType: STRUCT, dataTypeSpec: AWS/ALARM_STATE, unit: none, type: { measurement: {} } } ] } ] # Assets IoTSiteWiseDemoAssetLifecycleFunction: Type: AWS::Lambda::Function DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: IoT SiteWise Demo function handling the lifecycle of asset resources. This function will be deleted at the end of the demo. Code: S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region} S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip Handler: sitewise_assets.handler MemorySize: 128 Role: Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunctionRole, Arn] Runtime: python3.7 Timeout: 900 IoTSiteWiseDemoAssetLifecycleFunctionRole: Type: AWS::IAM::Role DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Role for IoT SiteWise Demo asset lifecycle. This role will be deleted at the end of the demo. AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: '2012-10-17' Policies: - PolicyName: IoTSiteWiseDemo-AssetLifecycleFunction-RolePolicy PolicyDocument: Statement: # CloudWatch logging - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Deny NotResource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" # SiteWise - Action: ['iotsitewise:CreateAsset','iotsitewise:DescribeAsset','iotsitewise:AssociateAssets','iotsitewise:DisassociateAssets','iotsitewise:DeleteAsset','iotsitewise:UpdateAssetProperty'] Effect: Allow Resource: "*" Version: '2012-10-17' IoTSiteWiseDemoAssetLifecycleFunctionLogGroup: DependsOn: IoTSiteWiseDemoAssetLifecycleFunction Type: AWS::Logs::LogGroup Condition: ValidRegion Properties: LogGroupName: Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoAssetLifecycleFunction}" IoTSiteWiseDemoPumpAsset1: DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoPumpL4EAlarmModel] Type: Custom::IoTSiteWiseDemoAsset Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn] name: Demo Pump Asset 1 model: { Ref: IoTSiteWiseDemoPumpAssetModel } asset_ids_to_associate: [] IoTSiteWiseDemoPumpAsset2: DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoPumpL4EAlarmModel] Type: Custom::IoTSiteWiseDemoAsset Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn] name: Demo Pump Asset 2 model: { Ref: IoTSiteWiseDemoPumpAssetModel } asset_ids_to_associate: [] IoTSiteWiseDemoPumpStationAsset: DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoStationAbnormalyAlarmModel] Type: Custom::IoTSiteWiseDemoAsset Condition: ValidRegion Properties: ServiceToken: Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn] name: Demo Pump Station Asset model: { Ref: IoTSiteWiseDemoPumpStationAssetModel } asset_ids_to_associate: [ { Ref: IoTSiteWiseDemoPumpAsset1 }, { Ref: IoTSiteWiseDemoPumpAsset2 } ] # Data generation IoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Function Condition: ValidRegion Properties: Description: IoT SiteWise Demo function handling data generation. This function will be deleted at the end of the demo. Code: S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region} S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip Handler: sitewise_data_generation.handler MemorySize: 256 Role: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunctionRole, Arn] Runtime: python3.7 Timeout: 900 IoTSiteWiseDemoDataGenerationFunctionRole: Type: AWS::IAM::Role Condition: ValidRegion Properties: Description: Role allowing fake data to be generated and put into IoT SiteWise Demo asset properties and stack deletion at the end of the demo. This function will be deleted at the end of the demo. AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: '2012-10-17' Policies: - PolicyName: IoTSiteWiseDemo-DataGenerationFunction-RolePolicy PolicyDocument: Statement: # CloudWatch logging - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup'] Effect: Deny NotResource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*" # SiteWise - Action: ['iotsitewise:BatchPutAssetPropertyValue', 'iotsitewise:DescribeAsset', 'iotsitewise:GetAssetPropertyValue'] Effect: Allow Resource: "*" # Stack cleanup - Action: ['lambda:DeleteFunction', 'lambda:InvokeFunction', 'lambda:RemovePermission'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${AWS::StackName}-*" - Action: ['iam:DeleteRole', 'iam:DeleteRolePolicy'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWS::StackName}-*" # technically DescribeAsset is used in cleanup but it is already allowed for putting data - Action: ['iotsitewise:DisassociateAssets', 'iotsitewise:DeleteAsset', 'iotsitewise:DeleteAssetModel','iotsitewise:UpdateAssetProperty'] Effect: Allow Resource: "*" - Action: ['logs:DeleteLogGroup'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-*" - Action: ['events:RemoveTargets', 'events:DeleteRule'] Effect: Allow Resource: Fn::Sub: "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${AWS::StackName}-*" - Action: ['cloudformation:DescribeStacks', 'cloudformation:DescribeStackEvents', 'cloudformation:DeleteStack'] Effect: Allow Resource: {Ref: 'AWS::StackId'} Version: '2012-10-17' IoTSiteWiseDemoDataGenerationFunctionLogGroup: Type: AWS::Logs::LogGroup DependsOn: IoTSiteWiseDemoDataGenerationFunction Condition: ValidRegion Properties: LogGroupName: Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoDataGenerationFunction}" IoTSiteWiseDemoDataGenerationScheduledRule1a: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FirstPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule1b: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${SecondPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule1c: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${ThirdPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule1d: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FourthPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule1e: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FifthPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule2a: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FirstPropertyGroup}" }' } IoTSiteWiseDemoDataGenerationScheduledRule2b: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${SecondPropertyGroup}" }' } IoTSiteWiseDemoDataGenerationScheduledRule2c: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${ThirdPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule2d: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FourthPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule2e: Type: AWS::Events::Rule DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets ScheduleExpression: rate(1 minute) State: "ENABLED" Targets: - Arn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn] Id: IoTSiteWiseDemoDataGenerationFunction Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FifthPropertyGroup}"}' } IoTSiteWiseDemoDataGenerationScheduledRule1aPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1a, Arn] IoTSiteWiseDemoDataGenerationScheduledRule1bPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1b, Arn] IoTSiteWiseDemoDataGenerationScheduledRule1cPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1c, Arn] IoTSiteWiseDemoDataGenerationScheduledRule1dPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1d, Arn] IoTSiteWiseDemoDataGenerationScheduledRule1ePermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1e, Arn] IoTSiteWiseDemoDataGenerationScheduledRule2aPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2a, Arn] IoTSiteWiseDemoDataGenerationScheduledRule2bPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2b, Arn] IoTSiteWiseDemoDataGenerationScheduledRule2cPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2c, Arn] IoTSiteWiseDemoDataGenerationScheduledRule2dPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2d, Arn] IoTSiteWiseDemoDataGenerationScheduledRule2ePermissionToInvokeIoTSiteWiseDemoDataGenerationFunction: Type: AWS::Lambda::Permission DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole Condition: ValidRegion Properties: FunctionName: Ref: IoTSiteWiseDemoDataGenerationFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2e, Arn]