From e3d708796d3eaa2fc317c47ba4d4cf3da62d6232 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Fri, 8 Nov 2024 10:47:56 +0100 Subject: [PATCH 1/8] functioning pattern iot lambda publisher and receiver --- iot-lambda-pub-receiver-cdk/README.md | 60 +++++++++ .../bin/lambda-iot-cdk.ts | 7 ++ iot-lambda-pub-receiver-cdk/cdk.json | 80 ++++++++++++ .../example-pattern.json | 59 +++++++++ .../lib/lambda-iot-cdk-stack.ts | 116 ++++++++++++++++++ iot-lambda-pub-receiver-cdk/package.json | 26 ++++ .../src/publisher_function.py | 22 ++++ .../src/receiver_function.py | 8 ++ .../src/receiver_requirements.txt | 2 + iot-lambda-pub-receiver-cdk/tsconfig.json | 31 +++++ 10 files changed, 411 insertions(+) create mode 100644 iot-lambda-pub-receiver-cdk/README.md create mode 100644 iot-lambda-pub-receiver-cdk/bin/lambda-iot-cdk.ts create mode 100644 iot-lambda-pub-receiver-cdk/cdk.json create mode 100644 iot-lambda-pub-receiver-cdk/example-pattern.json create mode 100644 iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts create mode 100644 iot-lambda-pub-receiver-cdk/package.json create mode 100644 iot-lambda-pub-receiver-cdk/src/publisher_function.py create mode 100644 iot-lambda-pub-receiver-cdk/src/receiver_function.py create mode 100644 iot-lambda-pub-receiver-cdk/src/receiver_requirements.txt create mode 100644 iot-lambda-pub-receiver-cdk/tsconfig.json diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md new file mode 100644 index 000000000..3ca759d23 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -0,0 +1,60 @@ +# AWS Service 1 to AWS Service 2 + +This pattern << explain usage >> + +Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >> + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed + +## Deployment Instructions + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` + git clone https://github.com/aws-samples/serverless-patterns + ``` +1. Change directory to the pattern directory: + ``` + cd _patterns-model + ``` +1. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: + ``` + sam deploy --guided + ``` +1. During the prompts: + * Enter a stack name + * Enter the desired AWS Region + * Allow SAM CLI to create IAM roles with the required permissions. + + Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. + +1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. + +## How it works + +Explain how the service interaction works. + +## Testing + +Provide steps to trigger the integration and show what should be observed if successful. + +## Cleanup + +1. Delete the stack + ```bash + aws cloudformation delete-stack --stack-name STACK_NAME + ``` +1. Confirm the stack has been deleted + ```bash + aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus" + ``` +---- +Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 diff --git a/iot-lambda-pub-receiver-cdk/bin/lambda-iot-cdk.ts b/iot-lambda-pub-receiver-cdk/bin/lambda-iot-cdk.ts new file mode 100644 index 000000000..01233a158 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/bin/lambda-iot-cdk.ts @@ -0,0 +1,7 @@ +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from 'aws-cdk-lib'; +import { LambdaIotCdkStack } from '../lib/lambda-iot-cdk-stack'; + +const app = new cdk.App(); +new LambdaIotCdkStack(app, 'LambdaIotCdkStack', { }); \ No newline at end of file diff --git a/iot-lambda-pub-receiver-cdk/cdk.json b/iot-lambda-pub-receiver-cdk/cdk.json new file mode 100644 index 000000000..81db35d39 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/cdk.json @@ -0,0 +1,80 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/lambda-iot-cdk.ts", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, + "@aws-cdk/aws-eks:nodegroupNameAttribute": true, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true + } +} diff --git a/iot-lambda-pub-receiver-cdk/example-pattern.json b/iot-lambda-pub-receiver-cdk/example-pattern.json new file mode 100644 index 000000000..b7012bdfa --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/example-pattern.json @@ -0,0 +1,59 @@ +{ + "title": "Step Functions to Athena", + "description": "Create a Step Functions workflow to query Amazon Athena.", + "language": "Python", + "level": "200", + "framework": "CDK", + "introBox": { + "headline": "How it works", + "text": [ + "This sample project demonstrates how to use an AWS Step Functions state machine to query Athena and get the results. This pattern is leveraging the native integration between these 2 services which means only JSON-based, structured language is used to define the implementation.", + "With Amazon Athena you can get up to 1000 results per invocation of the GetQueryResults method and this is the reason why the Step Function has a loop to get more results. The results are sent to a Map which can be configured to handle (the DoSomething state) the items in parallel or one by one by modifying the max_concurrency parameter.", + "This pattern deploys one Step Functions, two S3 Buckets, one Glue table and one Glue database." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/sfn-athena-cdk-python", + "templateURL": "serverless-patterns/sfn-athena-cdk-python", + "projectFolder": "sfn-athena-cdk-python", + "templateFile": "sfn_athena_cdk_python_stack.py" + } + }, + "resources": { + "bullets": [ + { + "text": "Call Athena with Step Functions", + "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-athena.html" + }, + { + "text": "Amazon Athena - Serverless Interactive Query Service", + "link": "https://aws.amazon.com/athena/" + } + ] + }, + "deploy": { + "text": [ + "sam deploy" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: cdk delete." + ] + }, + "authors": [ + { + "name": "Your name", + "image": "link-to-your-photo.jpg", + "bio": "Your bio.", + "linkedin": "linked-in-ID", + "twitter": "twitter-handle" + } + ] +} diff --git a/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts new file mode 100644 index 000000000..b2c119c36 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts @@ -0,0 +1,116 @@ +import { CloudWatchLogsAction, LambdaFunctionAction } from '@aws-cdk/aws-iot-actions-alpha'; +import { IotSql, TopicRule } from '@aws-cdk/aws-iot-alpha'; +import { CfnOutput, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { Effect, PolicyStatement, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; +import { Architecture, Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda'; +import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from 'aws-cdk-lib/custom-resources'; +import { Construct } from 'constructs'; + +export class LambdaIotCdkStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + let mqttTopicName = "my/mqtt/topic" + let mqttTopicRegion = Stack.of(this).region + let mqttTopicAccount = Stack.of(this).account + let iotEndpointAddress = this.getIoTEndpoint().getResponseField('endpointAddress') + + // Publisher lambda function. + // Remark - if the Lambda is in the same account and region as the IoT Core endpoint, then setting the endpoint is optional. + // Documention - AWS IoT Core action resources: https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html + const iotPubPermission = new PolicyStatement(({ + effect: Effect.ALLOW, + resources: [ `arn:aws:iot:${mqttTopicRegion}:${mqttTopicAccount}:topic/${mqttTopicName}` ], + actions: [ "iot:Publish" ] + })); + const iotPubLambda = new Function(this, 'iotPubHandler', { + handler: 'publisher_function.handler', + code: Code.fromAsset('./src'), + description: 'This function publishes a message to AWS IoT Core - MTTQ', + runtime: Runtime.PYTHON_3_12, + architecture: Architecture.ARM_64, + logGroup: this.addLogGroup(`/aws/lambda/pub-lambda`), + environment: { + MQTT_TOPIC_REGION: mqttTopicRegion, + MQTT_TOPIC_NAME: mqttTopicName + } + }) + iotPubLambda.addToRolePolicy(iotPubPermission) + + // Receiver lambda function + const iotReceiverPermission = new PolicyStatement(({ + effect: Effect.ALLOW, + resources: [ `arn:aws:iot:${mqttTopicRegion}:${mqttTopicAccount}:topic/${mqttTopicName}` ], + actions: [ + "iot:Receive" + ] + })); + const iotReceiverLambda = new Function(this, 'iotReceiverHandler', { + handler: 'receiver_function.handler', + description: 'This function get invoked by AWS IoT Core through the action-rule', + code: Code.fromAsset('./src', { + bundling: { + image: Runtime.PYTHON_3_12.bundlingImage, + command: [ + 'bash', '-c', + 'pip install -r receiver_requirements.txt -t /asset-output && cp -au . /asset-output' + ], + }, + }), + runtime: Runtime.PYTHON_3_12, + architecture: Architecture.ARM_64, + logGroup: this.addLogGroup(`/aws/lambda/receiver-lambda`) + }) + iotReceiverLambda.addToRolePolicy(iotReceiverPermission) + + // Topic rule + const errorLogGroup = new LogGroup(this, 'RuleErrorLogGroup', { + logGroupName: '/aws/iot/rule-error-logs', + retention: RetentionDays.FIVE_DAYS, + removalPolicy: RemovalPolicy.DESTROY + }) + let topicRule = new TopicRule(this, 'IoTTopicRule', { + topicRuleName: 'ProcessIoTMessages', + description: 'Invokes the lambda function', + sql: IotSql.fromStringAsVer20160323("SELECT * FROM 'my/mqtt/topic'"), + actions: [ new LambdaFunctionAction(iotReceiverLambda) ], + errorAction: new CloudWatchLogsAction(errorLogGroup) + }) + + // Grant permission for AWS IoT to invoke the Lambda function + const iotServicePrincipal = new ServicePrincipal('iot.amazonaws.com'); + iotReceiverLambda.grantInvoke(iotServicePrincipal); + + // Outputs + new CfnOutput(this, "IoT Endpoint Address", { + value: iotEndpointAddress ?? "Error: can't get the IoT Endpoint Address!", + }); + } + + // Utility function to return a log-group object + private addLogGroup(logGroupName: string) { + const retentionDays = RetentionDays.FIVE_DAYS + const removalPolicy = RemovalPolicy.DESTROY + const props = { logGroupName, retentionDays, removalPolicy } + return new LogGroup(this, `${logGroupName}`, props) + } + + // Get the current account IoT-Endpoint + private getIoTEndpoint() { + const ioTEndpoint = new AwsCustomResource(this, 'IoTEndpoint', { + onCreate: { + service: 'Iot', + action: 'describeEndpoint', + physicalResourceId: PhysicalResourceId.fromResponse('endpointAddress'), + parameters: { + "endpointType": "iot:Data-ATS" + } + }, + policy: AwsCustomResourcePolicy.fromSdkCalls({resources: AwsCustomResourcePolicy.ANY_RESOURCE}) + }) + const IOT_ENDPOINT = ioTEndpoint.getResponseField('endpointAddress') + console.log(IOT_ENDPOINT) + return ioTEndpoint + } +} diff --git a/iot-lambda-pub-receiver-cdk/package.json b/iot-lambda-pub-receiver-cdk/package.json new file mode 100644 index 000000000..b8e16c664 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/package.json @@ -0,0 +1,26 @@ +{ + "name": "lambda-iot-cdk", + "version": "0.1.0", + "bin": { + "lambda-iot-cdk": "bin/lambda-iot-cdk.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "cdk": "cdk" + }, + "devDependencies": { + "aws-cdk": "2.165.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" + }, + "dependencies": { + "@aws-cdk/aws-iam": "^1.203.0", + "@aws-cdk/aws-iot-actions-alpha": "^2.165.0-alpha.0", + "@aws-cdk/aws-iot-alpha": "^2.165.0-alpha.0", + "@aws-cdk/aws-lambda": "^1.203.0", + "aws-cdk-lib": "2.165.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" + } +} diff --git a/iot-lambda-pub-receiver-cdk/src/publisher_function.py b/iot-lambda-pub-receiver-cdk/src/publisher_function.py new file mode 100644 index 000000000..74f154990 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/src/publisher_function.py @@ -0,0 +1,22 @@ +import boto3 +import logging +import os +import json + +logger = logging.getLogger() +logger.setLevel("INFO") +logger = logging.getLogger(__name__) + +def handler(event, context): + mqtt_topic_region = os.environ['MQTT_TOPIC_REGION'] + mqtt_topic_name = os.environ['MQTT_TOPIC_NAME'] + logger.info(f"""Started with env variables: + MQTT_TOPIC_REGION= + {mqtt_topic_region} + MQTT_TOPIC_NAME=" + {mqtt_topic_name}""") + iot_client = boto3.client('iot-data', region_name=mqtt_topic_region) + response = iot_client.publish( + topic=mqtt_topic_name, + qos=1, # The MQTT message is delivered at least once. + payload=json.dumps(event) + ) + logger.info("Msg published.") \ No newline at end of file diff --git a/iot-lambda-pub-receiver-cdk/src/receiver_function.py b/iot-lambda-pub-receiver-cdk/src/receiver_function.py new file mode 100644 index 000000000..4857d0602 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/src/receiver_function.py @@ -0,0 +1,8 @@ +import logging + +logger = logging.getLogger() +logger.setLevel("INFO") +logger = logging.getLogger(__name__) + +def handler(event, context): + logger.info(f"Event received: {event}") diff --git a/iot-lambda-pub-receiver-cdk/src/receiver_requirements.txt b/iot-lambda-pub-receiver-cdk/src/receiver_requirements.txt new file mode 100644 index 000000000..79f0d884f --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/src/receiver_requirements.txt @@ -0,0 +1,2 @@ +awsiotsdk +paho-mqtt \ No newline at end of file diff --git a/iot-lambda-pub-receiver-cdk/tsconfig.json b/iot-lambda-pub-receiver-cdk/tsconfig.json new file mode 100644 index 000000000..aaa7dc510 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": [ + "es2020", + "dom" + ], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + "cdk.out" + ] +} From c0b3555806800bc3f89924271818ad8159d66d38 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Fri, 8 Nov 2024 13:55:50 +0100 Subject: [PATCH 2/8] add description --- iot-lambda-pub-receiver-cdk/README.md | 36 +++++++-------- .../doc/architecture-diagram.png | Bin 0 -> 58614 bytes .../example-pattern.json | 43 ++++++++++-------- .../lib/lambda-iot-cdk-stack.ts | 1 - 4 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 iot-lambda-pub-receiver-cdk/doc/architecture-diagram.png diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md index 3ca759d23..76c4fd80a 100644 --- a/iot-lambda-pub-receiver-cdk/README.md +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -1,6 +1,6 @@ -# AWS Service 1 to AWS Service 2 +# AWS Lambda to AWS IoT Core -This pattern << explain usage >> +This pattern deploys one publisher AWS Lambda, which publishes a message in AWS IoT Core topic. The topic is watch by a rule which triggers an action when the condition is met. The action calls a AWS Lambda. Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >> @@ -11,7 +11,10 @@ Important: this application uses various AWS services and there are costs associ * [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. * [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured * [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed +* [AWS Cloud Development Kit (AWS CDK) installed](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) + +## Architecture diagram +![Architecture diagram](./doc/architecture-diagram.png) ## Deployment Instructions @@ -21,20 +24,18 @@ Important: this application uses various AWS services and there are costs associ ``` 1. Change directory to the pattern directory: ``` - cd _patterns-model + cd iot-lambda-pub-receiver-cdk + ``` +1. Install dependencies + ```bash + npm install ``` 1. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: ``` - sam deploy --guided + cdk deploy ``` -1. During the prompts: - * Enter a stack name - * Enter the desired AWS Region - * Allow SAM CLI to create IAM roles with the required permissions. - - Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. -1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. +2. Note the outputs from the CDK deployment process. These contain the IoT endpoint address which is not relevant if you have only one account. However, in multi-accounts deployment, especially when the IoT resources are not in the same as the lambdas, then the endpoint address has to be specified in the functions' code. ## How it works @@ -46,13 +47,10 @@ Provide steps to trigger the integration and show what should be observed if suc ## Cleanup -1. Delete the stack - ```bash - aws cloudformation delete-stack --stack-name STACK_NAME - ``` -1. Confirm the stack has been deleted - ```bash - aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus" +Run the given command to delete the resources that were created. It might take some time for the CloudFormation stack to get deleted. +```bash +cdk destroy +``` ``` ---- Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/iot-lambda-pub-receiver-cdk/doc/architecture-diagram.png b/iot-lambda-pub-receiver-cdk/doc/architecture-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..951e141620d1daa5457d00231cc3b5b202b63bff GIT binary patch literal 58614 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 ~ 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 literal 0 HcmV?d00001 diff --git a/iot-lambda-pub-receiver-cdk/example-pattern.json b/iot-lambda-pub-receiver-cdk/example-pattern.json index b7012bdfa..a89432d6b 100644 --- a/iot-lambda-pub-receiver-cdk/example-pattern.json +++ b/iot-lambda-pub-receiver-cdk/example-pattern.json @@ -1,40 +1,48 @@ { - "title": "Step Functions to Athena", - "description": "Create a Step Functions workflow to query Amazon Athena.", + "title": "Lambda to IoT Core to Lambda", + "description": "Create a Lambda publishing into IoT topic, triggering an action calling another Lambda.", "language": "Python", "level": "200", "framework": "CDK", "introBox": { "headline": "How it works", "text": [ - "This sample project demonstrates how to use an AWS Step Functions state machine to query Athena and get the results. This pattern is leveraging the native integration between these 2 services which means only JSON-based, structured language is used to define the implementation.", - "With Amazon Athena you can get up to 1000 results per invocation of the GetQueryResults method and this is the reason why the Step Function has a loop to get more results. The results are sent to a Map which can be configured to handle (the DoSomething state) the items in parallel or one by one by modifying the max_concurrency parameter.", - "This pattern deploys one Step Functions, two S3 Buckets, one Glue table and one Glue database." + "This sample project demonstrates how to use an AWS Lambda Function to publish messages into AWS IoT Core topic and get a rule triggered by a condition to process relevant messages into another Lambda. This pattern is leveraging CloudWatch logs to ease the debugging and visibility into the processed messages.", + "The function are written in Python and the infrastructure is described with AWS CDKv2 in Typescript. The patterns also shows an effective way to manage Python dependencies through Docker built image and requiements.txt file.", + "This pattern deploys 2 Lambda functions, 1 IoT rule and action, 3 log groups." ] }, "gitHub": { "template": { "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/sfn-athena-cdk-python", "templateURL": "serverless-patterns/sfn-athena-cdk-python", - "projectFolder": "sfn-athena-cdk-python", - "templateFile": "sfn_athena_cdk_python_stack.py" + "projectFolder": "iot-lambda-pub-receiver-cdk", + "templateFile": "lambda-iot-cdk-stack.ts" } }, "resources": { "bullets": [ { - "text": "Call Athena with Step Functions", - "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-athena.html" + "text": "AWS IoT Core - Getting started with AWS IoT Core tutorials", + "link": "https://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html" }, { - "text": "Amazon Athena - Serverless Interactive Query Service", - "link": "https://aws.amazon.com/athena/" + "text": "AWS IoT Core action resources", + "link": "https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html" + }, + { + "test": "Building Lambda with Python", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html" + }, + { + "text": "Working with the AWS CDK in TypeScript", + "link": "https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html" } ] }, "deploy": { "text": [ - "sam deploy" + "cdk deploy" ] }, "testing": { @@ -44,16 +52,15 @@ }, "cleanup": { "text": [ - "Delete the stack: cdk delete." + "Delete the stack: cdk destroy." ] }, "authors": [ { - "name": "Your name", - "image": "link-to-your-photo.jpg", - "bio": "Your bio.", - "linkedin": "linked-in-ID", - "twitter": "twitter-handle" + "name": "Philippe Wanner", + "image": "https://serverlessland.com/assets/images/resources/contributors/philippe-wanner.jpg", + "bio": "Philippe is a Senior Specialist Solutions Architect at Amazon Web Services based in Zurich, Switzerland. His role is to spread the migration and modernization best practices for large organisations.", + "linkedin": "philippe-wanner" } ] } diff --git a/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts index b2c119c36..aa41974c1 100644 --- a/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts +++ b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts @@ -18,7 +18,6 @@ export class LambdaIotCdkStack extends Stack { // Publisher lambda function. // Remark - if the Lambda is in the same account and region as the IoT Core endpoint, then setting the endpoint is optional. - // Documention - AWS IoT Core action resources: https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html const iotPubPermission = new PolicyStatement(({ effect: Effect.ALLOW, resources: [ `arn:aws:iot:${mqttTopicRegion}:${mqttTopicAccount}:topic/${mqttTopicName}` ], From ef4578f21e5418f7eabe53e4c00d8fe8a1616378 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Fri, 13 Dec 2024 14:39:41 +0100 Subject: [PATCH 3/8] Update iot-lambda-pub-receiver-cdk/README.md Co-authored-by: Marco --- iot-lambda-pub-receiver-cdk/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md index 76c4fd80a..bdafb6061 100644 --- a/iot-lambda-pub-receiver-cdk/README.md +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -1,6 +1,6 @@ # AWS Lambda to AWS IoT Core -This pattern deploys one publisher AWS Lambda, which publishes a message in AWS IoT Core topic. The topic is watch by a rule which triggers an action when the condition is met. The action calls a AWS Lambda. +This pattern deploys an AWS Lambda function, which publishes a message to an AWS IoT Core topic. The topic is watched by a rule which will trigger an action when the condition is met. The action calls an AWS Lambda function. Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >> From 484aaf22359d8f149357a99adeb944edce7f705b Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Fri, 13 Dec 2024 14:42:48 +0100 Subject: [PATCH 4/8] implemented feedback suggestions: 1/upgrade cdk version 2/improve readme.md --- iot-lambda-pub-receiver-cdk/README.md | 2 +- iot-lambda-pub-receiver-cdk/package.json | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md index bdafb6061..2a344f9ea 100644 --- a/iot-lambda-pub-receiver-cdk/README.md +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -2,7 +2,7 @@ This pattern deploys an AWS Lambda function, which publishes a message to an AWS IoT Core topic. The topic is watched by a rule which will trigger an action when the condition is met. The action calls an AWS Lambda function. -Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >> +Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/iot-lambda-pub-receiver-cdk Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. diff --git a/iot-lambda-pub-receiver-cdk/package.json b/iot-lambda-pub-receiver-cdk/package.json index b8e16c664..916953786 100644 --- a/iot-lambda-pub-receiver-cdk/package.json +++ b/iot-lambda-pub-receiver-cdk/package.json @@ -10,16 +10,14 @@ "cdk": "cdk" }, "devDependencies": { - "aws-cdk": "2.165.0", + "aws-cdk": "^2.173.0", "ts-node": "^10.9.2", - "typescript": "~5.6.3" + "typescript": "~5.7.2" }, "dependencies": { - "@aws-cdk/aws-iam": "^1.203.0", - "@aws-cdk/aws-iot-actions-alpha": "^2.165.0-alpha.0", - "@aws-cdk/aws-iot-alpha": "^2.165.0-alpha.0", - "@aws-cdk/aws-lambda": "^1.203.0", - "aws-cdk-lib": "2.165.0", + "@aws-cdk/aws-iot-actions-alpha": "^2.173.0-alpha.0", + "@aws-cdk/aws-iot-alpha": "^2.173.0-alpha.0", + "aws-cdk-lib": "2.173.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } From a9a3971afbefd707fefa73fec904726d5b09f588 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Sun, 15 Dec 2024 20:25:29 +0100 Subject: [PATCH 5/8] add architecture description --- iot-lambda-pub-receiver-cdk/README.md | 17 ++++++++++++----- .../doc/architecture-diagram.png | Bin 58614 -> 26767 bytes 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md index 2a344f9ea..d01e76e24 100644 --- a/iot-lambda-pub-receiver-cdk/README.md +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -16,6 +16,17 @@ Important: this application uses various AWS services and there are costs associ ## Architecture diagram ![Architecture diagram](./doc/architecture-diagram.png) +This CDK stack creates an AWS IoT Core setup with a publisher-receiver pattern using Lambda functions. +Here's a breakdown of the main components: + +1. An IoT MQTT topic named "my/mqtt/topic" + +1. Publisher Lambda Function, written in Python and using ARM64 architecture, has permissions to publish messages to the specified MQTT topic (1). Its environment variables include the MQTT topic region and name. + +1. Receiver Lambda Function, also in Python and using ARM64 architecture, has permissions to receive messages from the MQTT topic. + +1. IoT Topic Rule, named "ProcessIoTMessages, uses SQL version 2016-03-23 to select all messages from the MQTT topic. It triggers the receiver Lambda function when messages arrive and it includes error logging to CloudWatch Logs. + ## Deployment Instructions 1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: @@ -37,10 +48,6 @@ Important: this application uses various AWS services and there are costs associ 2. Note the outputs from the CDK deployment process. These contain the IoT endpoint address which is not relevant if you have only one account. However, in multi-accounts deployment, especially when the IoT resources are not in the same as the lambdas, then the endpoint address has to be specified in the functions' code. -## How it works - -Explain how the service interaction works. - ## Testing Provide steps to trigger the integration and show what should be observed if successful. @@ -48,10 +55,10 @@ Provide steps to trigger the integration and show what should be observed if suc ## Cleanup Run the given command to delete the resources that were created. It might take some time for the CloudFormation stack to get deleted. + ```bash cdk destroy ``` - ``` ---- Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/iot-lambda-pub-receiver-cdk/doc/architecture-diagram.png b/iot-lambda-pub-receiver-cdk/doc/architecture-diagram.png index 951e141620d1daa5457d00231cc3b5b202b63bff..79b36510cdfa83532adb2c4af534e712c0b2393d 100644 GIT binary patch literal 26767 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 KyiC-<=f40CANdym literal 58614 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 ~ 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 From 1d9b57aa1b870332dc20c2b6a069b4752e4970c4 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Mon, 16 Dec 2024 14:52:48 +0100 Subject: [PATCH 6/8] added testing section --- iot-lambda-pub-receiver-cdk/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/iot-lambda-pub-receiver-cdk/README.md b/iot-lambda-pub-receiver-cdk/README.md index d01e76e24..f278825b0 100644 --- a/iot-lambda-pub-receiver-cdk/README.md +++ b/iot-lambda-pub-receiver-cdk/README.md @@ -50,7 +50,16 @@ Here's a breakdown of the main components: ## Testing -Provide steps to trigger the integration and show what should be observed if successful. +The following steps will help you test the pattern from the AWS Console: +1. Trigger the publisher Lambda function + 1. Navigate to AWS Lambda service and open the `LambdaIotCdkStack-iotPubHandler*` function. + 1. From the `Test` tab, generate any event + 1. A green notification should appears detailing that the execution has succeeded + 1. Navigate to Amazon CloudWatch and open the Log group `/aws/lambda/pub-lambda`. The latest events will display the MQTT topic name and the AWS region where the message is sent. +1. Verify receiver execution + 1. Navigate to AWS Lambda service and open the `LambdaIotCdkStack-iotReceiverHandler*` function. + 1. From the `Monitor` tab, look for the Invocations metrics. A data point should be displayed indicated the execution of the receiver Lambda function just after that the publisher Lambda function has been triggered. + 1. Navigate to Amazon CloudWatch and open the Log group `/aws/lambda/receiver-lambda`. The latest events will display the input of the publisher Lambda function. ## Cleanup From e84eb39f164ccbc0d53ae8ba5aeed31bc913e938 Mon Sep 17 00:00:00 2001 From: Philippe Wanner Date: Tue, 17 Dec 2024 11:21:16 +0100 Subject: [PATCH 7/8] remove console log --- iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts index aa41974c1..08c55e405 100644 --- a/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts +++ b/iot-lambda-pub-receiver-cdk/lib/lambda-iot-cdk-stack.ts @@ -109,7 +109,6 @@ export class LambdaIotCdkStack extends Stack { policy: AwsCustomResourcePolicy.fromSdkCalls({resources: AwsCustomResourcePolicy.ANY_RESOURCE}) }) const IOT_ENDPOINT = ioTEndpoint.getResponseField('endpointAddress') - console.log(IOT_ENDPOINT) return ioTEndpoint } } From 6e45f48e8ae638ebdc363b65e996745dac171153 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 17 Dec 2024 11:24:05 +0100 Subject: [PATCH 8/8] Create pattern.json --- iot-lambda-pub-receiver-cdk/pattern.json | 95 ++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 iot-lambda-pub-receiver-cdk/pattern.json diff --git a/iot-lambda-pub-receiver-cdk/pattern.json b/iot-lambda-pub-receiver-cdk/pattern.json new file mode 100644 index 000000000..8fdb3ee88 --- /dev/null +++ b/iot-lambda-pub-receiver-cdk/pattern.json @@ -0,0 +1,95 @@ +{ + "title": "AWS Lambda to AWS IoT Core", + "description": "Create a Lambda publishing into IoT topic, triggering an action calling another Lambda.", + "language": "Python", + "level": "200", + "framework": "CDK", + "introBox": { + "headline": "How it works", + "text": [ + "This sample project demonstrates how to use an AWS Lambda Function to publish messages into AWS IoT Core topic and get a rule triggered by a condition to to forward and process relevant messages into a second Lambda. This pattern is leveraging CloudWatch logs to ease the debugging and visibility into the processed messages.", + "The function are written in Python and the infrastructure is described with AWS CDK v2 in Typescript. The patterns also shows an effective way to manage Python dependencies through Docker built image and requiements.txt file." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/sfn-athena-cdk-python", + "templateURL": "serverless-patterns/sfn-athena-cdk-python", + "projectFolder": "iot-lambda-pub-receiver-cdk", + "templateFile": "lambda-iot-cdk-stack.ts" + } + }, + "resources": { + "bullets": [ + { + "text": "AWS IoT Core - Getting started with AWS IoT Core tutorials", + "link": "https://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html" + }, + { + "text": "AWS IoT Core action resources", + "link": "https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html" + }, + { + "test": "Building Lambda with Python", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html" + }, + { + "text": "Working with the AWS CDK in TypeScript", + "link": "https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html" + } + ] + }, + "deploy": { + "text": [ + "cdk deploy" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: cdk destroy." + ] + }, + "authors": [ + { + "name": "Philippe Wanner", + "image": "https://serverlessland.com/assets/images/resources/contributors/philippe-wanner.jpg", + "bio": "Philippe is a Senior Specialist Solutions Architect at Amazon Web Services based in Zurich, Switzerland. His role is to spread the migration and modernization best practices for large organisations.", + "linkedin": "philippe-wanner" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon2": { + "x": 50, + "y": 50, + "service": "iot", + "label": "AWS IoT Core" + }, + "icon3": { + "x": 80, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "line1": { + "from": "icon1", + "to": "icon2", + "label": "" + }, + "line2": { + "from": "icon2", + "to": "icon3", + "label": "" + } + } +}