-
Notifications
You must be signed in to change notification settings - Fork 247
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(aws-iot-sqs): initial implementation (#267)
* Initial design commit for new pattern: aws-iot-sqs * Corrections to README. renamed to and removed a typo * feat(aws-iot-sqs): initial implementation fixes #266 Added implementation of new pattern Added unit and integration tests * Revert aws-iot-sqs versions in package.json * Update integration tests to resolve CFN Nag warnings * Refreshing unit and integration test snapshots after merging from main * PR feedback updates: * Removed references to lambda from .gitignore and .eslintignore * Use service namespaces instead of named imports * Updated architecture diagram Co-authored-by: Quinones <[email protected]> Co-authored-by: biffgaut <[email protected]>
- Loading branch information
1 parent
b79664b
commit 5411ab7
Showing
25 changed files
with
6,403 additions
and
0 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
source/patterns/@aws-solutions-constructs/aws-iot-sqs/.eslintignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
lib/*.js | ||
test/*.js | ||
*.d.ts | ||
coverage |
15 changes: 15 additions & 0 deletions
15
source/patterns/@aws-solutions-constructs/aws-iot-sqs/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
lib/*.js | ||
test/*.js | ||
*.js.map | ||
*.d.ts | ||
node_modules | ||
*.generated.ts | ||
dist | ||
.jsii | ||
|
||
.LAST_BUILD | ||
.nyc_output | ||
coverage | ||
.nycrc | ||
.LAST_PACKAGE | ||
*.snk |
21 changes: 21 additions & 0 deletions
21
source/patterns/@aws-solutions-constructs/aws-iot-sqs/.npmignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Exclude typescript source and config | ||
*.ts | ||
tsconfig.json | ||
coverage | ||
.nyc_output | ||
*.tgz | ||
*.snk | ||
*.tsbuildinfo | ||
|
||
# Include javascript files and typescript declarations | ||
!*.js | ||
!*.d.ts | ||
|
||
# Exclude jsii outdir | ||
dist | ||
|
||
# Include .jsii | ||
!.jsii | ||
|
||
# Include .jsii | ||
!.jsii |
101 changes: 101 additions & 0 deletions
101
source/patterns/@aws-solutions-constructs/aws-iot-sqs/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# aws-iot-sqs module | ||
<!--BEGIN STABILITY BANNER--> | ||
|
||
--- | ||
|
||
![Stability: Experimental](https://img.shields.io/badge/stability-Experimental-important.svg?style=for-the-badge) | ||
|
||
> All classes are under active development and subject to non-backward compatible changes or removal in any | ||
> future version. These are not subject to the [Semantic Versioning](https://semver.org/) model. | ||
> This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package. | ||
--- | ||
<!--END STABILITY BANNER--> | ||
|
||
| **Reference Documentation**:| <span style="font-weight: normal">https://docs.aws.amazon.com/solutions/latest/constructs/</span>| | ||
|:-------------|:-------------| | ||
<div style="height:8px"></div> | ||
|
||
| **Language** | **Package** | | ||
|:-------------|-----------------| | ||
|![Python Logo](https://docs.aws.amazon.com/cdk/api/latest/img/python32.png) Python|`aws_solutions_constructs.aws_iot_sqs`| | ||
|![Typescript Logo](https://docs.aws.amazon.com/cdk/api/latest/img/typescript32.png) Typescript|`@aws-solutions-constructs/aws-iot-sqs`| | ||
|![Java Logo](https://docs.aws.amazon.com/cdk/api/latest/img/java32.png) Java|`software.amazon.awsconstructs.services.iotsqs`| | ||
|
||
This AWS Solutions Construct implements an AWS IoT MQTT topic rule and an AWS SQS Queue pattern. | ||
|
||
Here is a minimal deployable pattern definition in Typescript: | ||
|
||
``` typescript | ||
const { IotToSqsProps, IotToSqs } from '@aws-solutions-constructs/aws-iot-sqs'; | ||
|
||
const props: IotToSqsProps = { | ||
iotTopicRuleProps: { | ||
topicRulePayload: { | ||
ruleDisabled: false, | ||
description: "Testing the IotToSqs Pattern", | ||
sql: "SELECT * FROM 'iot/sqs/#'", | ||
actions: [] | ||
} | ||
} | ||
}; | ||
|
||
new IotToSqs(this, 'test-iot-sqs-integration', props); | ||
``` | ||
|
||
## Initializer | ||
|
||
``` text | ||
new IotToSqs(scope: Construct, id: string, props: IotToSqsProps); | ||
``` | ||
|
||
_Parameters_ | ||
|
||
* scope [`Construct`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Construct.html) | ||
* id `string` | ||
* props [`IotToSqsProps`](#pattern-construct-props) | ||
|
||
## Pattern Construct Props | ||
|
||
| **Name** | **Type** | **Description** | | ||
|:-------------|:----------------|-----------------| | ||
|existingQueueObj?|[`sqs.Queue`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sqs.Queue.html)|Existing instance of SQS queue object, providing both this and `queueProps` will cause an error.| | ||
|queueProps?|[`sqs.QueueProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sqs.QueueProps.html)|User provided props to override the default props for the SQS queue.| | ||
|deadLetterQueueProps?|[`sqs.QueueProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sqs.QueueProps.html)|Optional user provided properties for the dead letter queue.| | ||
|deployDeadLetterQueue?|`boolean`|Whether to deploy a secondary queue to be used as a dead letter queue. Default `true`.| | ||
|maxReceiveCount?|`number`|The number of times a message can be unsuccessfully dequeued before being moved to the dead-letter queue. Required field if `deployDeadLetterQueue`=`true`.| | ||
|enableEncryptionWithCustomerManagedKey?|`boolean`|Use a KMS Key, either managed by this CDK app, or imported. If importing an encryption key, it must be specified in the `encryptionKey` property for this construct.| | ||
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-kms.Key.html)|An optional, imported encryption key to encrypt the SQS queue.| | ||
|encryptionKeyProps?|[`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-kms.KeyProps.html)|Optional user-provided props to override the default props for the encryption key.| | ||
|iotTopicRuleProps?|[`iot.CfnTopicRuleProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-iot.CfnTopicRuleProps.html)|User provided CfnTopicRuleProps to override the defaults| | ||
|
||
## Pattern Properties | ||
|
||
| **Name** | **Type** | **Description** | | ||
|:-------------|:----------------|-----------------| | ||
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-kms.Key.html)|Returns an instance of `kms.Key` used for the SQS queue.| | ||
|iotActionsRole|[`iam.Role`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-iam.Role.html)|Returns an instance of `iam.Role` created by the construct, which allows IoT to publish messages to the SQS Queue| | ||
|sqsQueue|[`sqs.Queue`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sqs.Queue.html)|Returns an instance of `sqs.Queue` created by the construct| | ||
|deadLetterQueue?|[`sqs.Queue`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sqs.Queue.html)|Returns an instance of the dead-letter SQS queue created by the pattern.| | ||
|iotTopicRule|[`iot.CfnTopicRule`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-iot.CfnTopicRule.html)|Returns an instance of `iot.CfnTopicRule` created by the construct| | ||
|
||
## Default settings | ||
|
||
Out of the box implementation of the Construct without any override will set the following defaults: | ||
|
||
### Amazon IoT Rule | ||
* Configure an IoT Rule to send messages to the SQS Queue | ||
|
||
### Amazon IAM Role | ||
* Configure least privilege access IAM role for Amazon IoT to be able to publish messages to the SQS Queue | ||
|
||
### Amazon SQS Queue | ||
* Deploy a dead-letter queue for the source queue. | ||
* Enable server-side encryption for the source queue using a customer-managed AWS KMS key. | ||
* Enforce encryption of data in transit. | ||
|
||
## Architecture | ||
![Architecture Diagram](architecture.png) | ||
|
||
*** | ||
© Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
Binary file added
BIN
+293 KB
source/patterns/@aws-solutions-constructs/aws-iot-sqs/architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
157 changes: 157 additions & 0 deletions
157
source/patterns/@aws-solutions-constructs/aws-iot-sqs/lib/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/** | ||
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance | ||
* with the License. A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES | ||
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions | ||
* and limitations under the License. | ||
*/ | ||
|
||
import * as cdk from '@aws-cdk/core'; | ||
import * as sqs from '@aws-cdk/aws-sqs'; | ||
import * as iot from '@aws-cdk/aws-iot'; | ||
import * as kms from '@aws-cdk/aws-kms'; | ||
import * as iam from '@aws-cdk/aws-iam'; | ||
import * as defaults from '@aws-solutions-constructs/core'; | ||
|
||
/** | ||
* @summary The properties for the IotToSqs class. | ||
*/ | ||
export interface IotToSqsProps { | ||
/** | ||
* Existing instance of SQS queue object, providing both this and queueProps will cause an error. | ||
* | ||
* @default - None | ||
*/ | ||
readonly existingQueueObj?: sqs.Queue; | ||
|
||
/** | ||
* User provided props to override the default props for the SQS queue. | ||
* | ||
* @default - Default props are used | ||
*/ | ||
readonly queueProps?: sqs.QueueProps; | ||
|
||
/** | ||
* Optional user provided properties for the dead letter queue | ||
* | ||
* @default - Default props are used | ||
*/ | ||
readonly deadLetterQueueProps?: sqs.QueueProps; | ||
|
||
/** | ||
* Whether to deploy a secondary queue to be used as a dead letter queue. | ||
* | ||
* @default - true. | ||
*/ | ||
readonly deployDeadLetterQueue?: boolean; | ||
|
||
/** | ||
* The number of times a message can be unsuccessfully dequeued before being moved to the dead-letter queue. | ||
* | ||
* @default - required field if deployDeadLetterQueue=true. | ||
*/ | ||
readonly maxReceiveCount?: number; | ||
|
||
/** | ||
* Use a KMS Key, either managed by this CDK app, or imported. If importing an encryption key, it must be specified in | ||
* the encryptionKey property for this construct. | ||
* | ||
* @default - true (encryption enabled, managed by this CDK app). | ||
*/ | ||
readonly enableEncryptionWithCustomerManagedKey?: boolean; | ||
|
||
/** | ||
* An optional, imported encryption key to encrypt the SQS queue, and SNS Topic. | ||
* | ||
* @default - not specified. | ||
*/ | ||
readonly encryptionKey?: kms.Key; | ||
|
||
/** | ||
* Optional user-provided props to override the default props for the encryption key. | ||
* | ||
* @default - Default props are used. | ||
*/ | ||
readonly encryptionKeyProps?: kms.KeyProps; | ||
|
||
/** | ||
* User provided CfnTopicRuleProps to override the defaults | ||
* | ||
* @default - None | ||
*/ | ||
readonly iotTopicRuleProps: iot.CfnTopicRuleProps; | ||
} | ||
|
||
export class IotToSqs extends cdk.Construct { | ||
public readonly sqsQueue: sqs.Queue; | ||
public readonly deadLetterQueue?: sqs.DeadLetterQueue; | ||
public readonly encryptionKey?: kms.IKey; | ||
public readonly iotActionsRole: iam.Role; | ||
public readonly iotTopicRule: iot.CfnTopicRule; | ||
|
||
/** | ||
* @summary Constructs a new instance of the IotToSqs class. | ||
* @param {cdk.App} scope - represents the scope for all the resources. | ||
* @param {string} id - this is a a scope-unique id. | ||
* @param {IotToSqsProps} props - user provided props for the construct | ||
* @access public | ||
*/ | ||
constructor(scope: cdk.Construct, id: string, props: IotToSqsProps) { | ||
super(scope, id); | ||
defaults.CheckProps(props); | ||
|
||
// Setup the dead letter queue, if applicable | ||
this.deadLetterQueue = defaults.buildDeadLetterQueue(this, { | ||
existingQueueObj: props.existingQueueObj, | ||
deployDeadLetterQueue: props.deployDeadLetterQueue, | ||
deadLetterQueueProps: props.deadLetterQueueProps, | ||
maxReceiveCount: props.maxReceiveCount | ||
}); | ||
|
||
// Default to `true` if `enableEncryptionWithCustomerManagedKey` is undefined | ||
let enableEncryptionWithCustomerManagedKey = props.enableEncryptionWithCustomerManagedKey; | ||
if (enableEncryptionWithCustomerManagedKey === undefined) { | ||
enableEncryptionWithCustomerManagedKey = true; | ||
} | ||
|
||
// Setup the queue | ||
[this.sqsQueue, this.encryptionKey] = defaults.buildQueue(this, 'queue', { | ||
existingQueueObj: props.existingQueueObj, | ||
queueProps: props.queueProps, | ||
deadLetterQueue: this.deadLetterQueue, | ||
enableEncryptionWithCustomerManagedKey, | ||
encryptionKey: props.encryptionKey, | ||
encryptionKeyProps: props.encryptionKeyProps | ||
}); | ||
|
||
if (this.sqsQueue.fifo) { | ||
throw new Error('The IoT SQS action doesn\'t support Amazon SQS FIFO (First-In-First-Out) queues'); | ||
} | ||
|
||
// Role to allow IoT to send messages to the SQS Queue | ||
this.iotActionsRole = new iam.Role(this, 'iot-actions-role', { | ||
assumedBy: new iam.ServicePrincipal('iot.amazonaws.com') | ||
}); | ||
this.sqsQueue.grantSendMessages(this.iotActionsRole); | ||
|
||
if (this.encryptionKey) { | ||
this.encryptionKey.grantEncrypt(this.iotActionsRole); | ||
} | ||
|
||
const defaultIotTopicProps = defaults.DefaultCfnTopicRuleProps([{ | ||
sqs: { | ||
queueUrl: this.sqsQueue.queueUrl, | ||
roleArn: this.iotActionsRole.roleArn | ||
} | ||
}]); | ||
const iotTopicProps = defaults.overrideProps(defaultIotTopicProps, props.iotTopicRuleProps, true); | ||
|
||
// Create the IoT topic rule | ||
this.iotTopicRule = new iot.CfnTopicRule(this, 'IotTopicRule', iotTopicProps); | ||
} | ||
} |
Oops, something went wrong.