Repository: awslabs/aws-ddk (language: python)

Issue:
Beta Testing 1.0.0b.0 Corrections
- [x] Default DDK Alarms Threshold to `1`
- [x] Base Stack Default permissions boundary function needs to be a member method for JSII conversion
- [x] `get_codeartifact_publish_action` conversion
- [x] `Configurator.getTags()`
- [x] Databrew Job Props
- [x] SqsToLambda Stage `functionName`
- [x] Pass `ruleName` in `DataPipeline.addStage ()
- [x] Crawler Props refactor
- [x] Glue Security Configuration duplicated in `GlueFactory.job()`



Discussion / hints:

Fix patch:
diff --git a/API.md b/API.md
index d1ccf795..3db42e36 100644
--- a/API.md
+++ b/API.md
@@ -878,6 +878,7 @@ Convert an object, potentially containing tokens, to a JSON string.
 | <code><a href="#aws-ddk-core.BaseStack.isConstruct">isConstruct</a></code> | Checks if `x` is a construct. |
 | <code><a href="#aws-ddk-core.BaseStack.isStack">isStack</a></code> | Return whether the given object is a Stack. |
 | <code><a href="#aws-ddk-core.BaseStack.of">of</a></code> | Looks up the first stack scope in which `construct` is defined. |
+| <code><a href="#aws-ddk-core.BaseStack.createDefaultPermissionsBoundary">createDefaultPermissionsBoundary</a></code> | *No description.* |
 
 ---
 
@@ -937,6 +938,32 @@ The construct to start the search from.
 
 ---
 
+##### `createDefaultPermissionsBoundary` <a name="createDefaultPermissionsBoundary" id="aws-ddk-core.BaseStack.createDefaultPermissionsBoundary"></a>
+
+```typescript
+import { BaseStack } from 'aws-ddk-core'
+
+BaseStack.createDefaultPermissionsBoundary(scope: Construct, id: string, props: PermissionsBoundaryProps)
+```
+
+###### `scope`<sup>Required</sup> <a name="scope" id="aws-ddk-core.BaseStack.createDefaultPermissionsBoundary.parameter.scope"></a>
+
+- *Type:* constructs.Construct
+
+---
+
+###### `id`<sup>Required</sup> <a name="id" id="aws-ddk-core.BaseStack.createDefaultPermissionsBoundary.parameter.id"></a>
+
+- *Type:* string
+
+---
+
+###### `props`<sup>Required</sup> <a name="props" id="aws-ddk-core.BaseStack.createDefaultPermissionsBoundary.parameter.props"></a>
+
+- *Type:* <a href="#aws-ddk-core.PermissionsBoundaryProps">PermissionsBoundaryProps</a>
+
+---
+
 #### Properties <a name="Properties" id="Properties"></a>
 
 | **Name** | **Type** | **Description** |
@@ -1869,6 +1896,7 @@ public synth(): CICDPipelineStack
 | <code><a href="#aws-ddk-core.CICDPipelineStack.isConstruct">isConstruct</a></code> | Checks if `x` is a construct. |
 | <code><a href="#aws-ddk-core.CICDPipelineStack.isStack">isStack</a></code> | Return whether the given object is a Stack. |
 | <code><a href="#aws-ddk-core.CICDPipelineStack.of">of</a></code> | Looks up the first stack scope in which `construct` is defined. |
+| <code><a href="#aws-ddk-core.CICDPipelineStack.createDefaultPermissionsBoundary">createDefaultPermissionsBoundary</a></code> | *No description.* |
 
 ---
 
@@ -1928,6 +1956,32 @@ The construct to start the search from.
 
 ---
 
+##### `createDefaultPermissionsBoundary` <a name="createDefaultPermissionsBoundary" id="aws-ddk-core.CICDPipelineStack.createDefaultPermissionsBoundary"></a>
+
+```typescript
+import { CICDPipelineStack } from 'aws-ddk-core'
+
+CICDPipelineStack.createDefaultPermissionsBoundary(scope: Construct, id: string, props: PermissionsBoundaryProps)
+```
+
+###### `scope`<sup>Required</sup> <a name="scope" id="aws-ddk-core.CICDPipelineStack.createDefaultPermissionsBoundary.parameter.scope"></a>
+
+- *Type:* constructs.Construct
+
+---
+
+###### `id`<sup>Required</sup> <a name="id" id="aws-ddk-core.CICDPipelineStack.createDefaultPermissionsBoundary.parameter.id"></a>
+
+- *Type:* string
+
+---
+
+###### `props`<sup>Required</sup> <a name="props" id="aws-ddk-core.CICDPipelineStack.createDefaultPermissionsBoundary.parameter.props"></a>
+
+- *Type:* <a href="#aws-ddk-core.PermissionsBoundaryProps">PermissionsBoundaryProps</a>
+
+---
+
 #### Properties <a name="Properties" id="Properties"></a>
 
 | **Name** | **Type** | **Description** |
@@ -6430,12 +6484,26 @@ const dataBrewTransformStageProps: DataBrewTransformStageProps = { ... }
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.stateMachineInput">stateMachineInput</a></code> | <code>{[ key: string ]: any}</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.stateMachineName">stateMachineName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.createJob">createJob</a></code> | <code>boolean</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.databaseOutputs">databaseOutputs</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.DatabaseOutputProperty[]</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.dataCatalogOutputs">dataCatalogOutputs</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.DataCatalogOutputProperty[]</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.datasetName">datasetName</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.encryptionKeyArn">encryptionKeyArn</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.encryptionMode">encryptionMode</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.jobName">jobName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.jobRoleArn">jobRoleArn</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.jobSample">jobSample</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.JobSampleProperty</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.jobType">jobType</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.logSubscription">logSubscription</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.maxCapacity">maxCapacity</a></code> | <code>number</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.maxRetries">maxRetries</a></code> | <code>number</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.outputLocation">outputLocation</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.OutputLocationProperty</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.outputs">outputs</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.OutputProperty[]</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.profileConfiguration">profileConfiguration</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.ProfileConfigurationProperty</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.projectName">projectName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.recipe">recipe</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.RecipeProperty</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.tags">tags</a></code> | <code>aws-cdk-lib.CfnTag[]</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.timeout">timeout</a></code> | <code>number</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DataBrewTransformStageProps.property.validationConfigurations">validationConfigurations</a></code> | <code>aws-cdk-lib.aws_databrew.CfnJob.ValidationConfigurationProperty[]</code> | *No description.* |
 
 ---
 
@@ -6529,6 +6597,26 @@ public readonly createJob: boolean;
 
 ---
 
+##### `databaseOutputs`<sup>Optional</sup> <a name="databaseOutputs" id="aws-ddk-core.DataBrewTransformStageProps.property.databaseOutputs"></a>
+
+```typescript
+public readonly databaseOutputs: DatabaseOutputProperty[];
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.DatabaseOutputProperty[]
+
+---
+
+##### `dataCatalogOutputs`<sup>Optional</sup> <a name="dataCatalogOutputs" id="aws-ddk-core.DataBrewTransformStageProps.property.dataCatalogOutputs"></a>
+
+```typescript
+public readonly dataCatalogOutputs: DataCatalogOutputProperty[];
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.DataCatalogOutputProperty[]
+
+---
+
 ##### `datasetName`<sup>Optional</sup> <a name="datasetName" id="aws-ddk-core.DataBrewTransformStageProps.property.datasetName"></a>
 
 ```typescript
@@ -6539,6 +6627,26 @@ public readonly datasetName: string;
 
 ---
 
+##### `encryptionKeyArn`<sup>Optional</sup> <a name="encryptionKeyArn" id="aws-ddk-core.DataBrewTransformStageProps.property.encryptionKeyArn"></a>
+
+```typescript
+public readonly encryptionKeyArn: string;
+```
+
+- *Type:* string
+
+---
+
+##### `encryptionMode`<sup>Optional</sup> <a name="encryptionMode" id="aws-ddk-core.DataBrewTransformStageProps.property.encryptionMode"></a>
+
+```typescript
+public readonly encryptionMode: string;
+```
+
+- *Type:* string
+
+---
+
 ##### `jobName`<sup>Optional</sup> <a name="jobName" id="aws-ddk-core.DataBrewTransformStageProps.property.jobName"></a>
 
 ```typescript
@@ -6559,6 +6667,16 @@ public readonly jobRoleArn: string;
 
 ---
 
+##### `jobSample`<sup>Optional</sup> <a name="jobSample" id="aws-ddk-core.DataBrewTransformStageProps.property.jobSample"></a>
+
+```typescript
+public readonly jobSample: JobSampleProperty;
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.JobSampleProperty
+
+---
+
 ##### `jobType`<sup>Optional</sup> <a name="jobType" id="aws-ddk-core.DataBrewTransformStageProps.property.jobType"></a>
 
 ```typescript
@@ -6569,6 +6687,46 @@ public readonly jobType: string;
 
 ---
 
+##### `logSubscription`<sup>Optional</sup> <a name="logSubscription" id="aws-ddk-core.DataBrewTransformStageProps.property.logSubscription"></a>
+
+```typescript
+public readonly logSubscription: string;
+```
+
+- *Type:* string
+
+---
+
+##### `maxCapacity`<sup>Optional</sup> <a name="maxCapacity" id="aws-ddk-core.DataBrewTransformStageProps.property.maxCapacity"></a>
+
+```typescript
+public readonly maxCapacity: number;
+```
+
+- *Type:* number
+
+---
+
+##### `maxRetries`<sup>Optional</sup> <a name="maxRetries" id="aws-ddk-core.DataBrewTransformStageProps.property.maxRetries"></a>
+
+```typescript
+public readonly maxRetries: number;
+```
+
+- *Type:* number
+
+---
+
+##### `outputLocation`<sup>Optional</sup> <a name="outputLocation" id="aws-ddk-core.DataBrewTransformStageProps.property.outputLocation"></a>
+
+```typescript
+public readonly outputLocation: OutputLocationProperty;
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.OutputLocationProperty
+
+---
+
 ##### `outputs`<sup>Optional</sup> <a name="outputs" id="aws-ddk-core.DataBrewTransformStageProps.property.outputs"></a>
 
 ```typescript
@@ -6579,6 +6737,26 @@ public readonly outputs: OutputProperty[];
 
 ---
 
+##### `profileConfiguration`<sup>Optional</sup> <a name="profileConfiguration" id="aws-ddk-core.DataBrewTransformStageProps.property.profileConfiguration"></a>
+
+```typescript
+public readonly profileConfiguration: ProfileConfigurationProperty;
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.ProfileConfigurationProperty
+
+---
+
+##### `projectName`<sup>Optional</sup> <a name="projectName" id="aws-ddk-core.DataBrewTransformStageProps.property.projectName"></a>
+
+```typescript
+public readonly projectName: string;
+```
+
+- *Type:* string
+
+---
+
 ##### `recipe`<sup>Optional</sup> <a name="recipe" id="aws-ddk-core.DataBrewTransformStageProps.property.recipe"></a>
 
 ```typescript
@@ -6589,6 +6767,36 @@ public readonly recipe: RecipeProperty;
 
 ---
 
+##### `tags`<sup>Optional</sup> <a name="tags" id="aws-ddk-core.DataBrewTransformStageProps.property.tags"></a>
+
+```typescript
+public readonly tags: CfnTag[];
+```
+
+- *Type:* aws-cdk-lib.CfnTag[]
+
+---
+
+##### `timeout`<sup>Optional</sup> <a name="timeout" id="aws-ddk-core.DataBrewTransformStageProps.property.timeout"></a>
+
+```typescript
+public readonly timeout: number;
+```
+
+- *Type:* number
+
+---
+
+##### `validationConfigurations`<sup>Optional</sup> <a name="validationConfigurations" id="aws-ddk-core.DataBrewTransformStageProps.property.validationConfigurations"></a>
+
+```typescript
+public readonly validationConfigurations: ValidationConfigurationProperty[];
+```
+
+- *Type:* aws-cdk-lib.aws_databrew.CfnJob.ValidationConfigurationProperty[]
+
+---
+
 ### DataPipelineProps <a name="DataPipelineProps" id="aws-ddk-core.DataPipelineProps"></a>
 
 #### Initializer <a name="Initializer" id="aws-ddk-core.DataPipelineProps.Initializer"></a>
@@ -6678,6 +6886,89 @@ public readonly alarmsEnabled: boolean;
 
 ---
 
+### DeliveryStreamProps <a name="DeliveryStreamProps" id="aws-ddk-core.DeliveryStreamProps"></a>
+
+#### Initializer <a name="Initializer" id="aws-ddk-core.DeliveryStreamProps.Initializer"></a>
+
+```typescript
+import { DeliveryStreamProps } from 'aws-ddk-core'
+
+const deliveryStreamProps: DeliveryStreamProps = { ... }
+```
+
+#### Properties <a name="Properties" id="Properties"></a>
+
+| **Name** | **Type** | **Description** |
+| --- | --- | --- |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.deliveryStreamName">deliveryStreamName</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.destinations">destinations</a></code> | <code>@aws-cdk/aws-kinesisfirehose-alpha.IDestination[]</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.encryption">encryption</a></code> | <code>@aws-cdk/aws-kinesisfirehose-alpha.StreamEncryption</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.encryptionKey">encryptionKey</a></code> | <code>aws-cdk-lib.aws_kms.IKey</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.role">role</a></code> | <code>aws-cdk-lib.aws_iam.IRole</code> | *No description.* |
+| <code><a href="#aws-ddk-core.DeliveryStreamProps.property.sourceStream">sourceStream</a></code> | <code>aws-cdk-lib.aws_kinesis.IStream</code> | *No description.* |
+
+---
+
+##### `deliveryStreamName`<sup>Optional</sup> <a name="deliveryStreamName" id="aws-ddk-core.DeliveryStreamProps.property.deliveryStreamName"></a>
+
+```typescript
+public readonly deliveryStreamName: string;
+```
+
+- *Type:* string
+
+---
+
+##### `destinations`<sup>Optional</sup> <a name="destinations" id="aws-ddk-core.DeliveryStreamProps.property.destinations"></a>
+
+```typescript
+public readonly destinations: IDestination[];
+```
+
+- *Type:* @aws-cdk/aws-kinesisfirehose-alpha.IDestination[]
+
+---
+
+##### `encryption`<sup>Optional</sup> <a name="encryption" id="aws-ddk-core.DeliveryStreamProps.property.encryption"></a>
+
+```typescript
+public readonly encryption: StreamEncryption;
+```
+
+- *Type:* @aws-cdk/aws-kinesisfirehose-alpha.StreamEncryption
+
+---
+
+##### `encryptionKey`<sup>Optional</sup> <a name="encryptionKey" id="aws-ddk-core.DeliveryStreamProps.property.encryptionKey"></a>
+
+```typescript
+public readonly encryptionKey: IKey;
+```
+
+- *Type:* aws-cdk-lib.aws_kms.IKey
+
+---
+
+##### `role`<sup>Optional</sup> <a name="role" id="aws-ddk-core.DeliveryStreamProps.property.role"></a>
+
+```typescript
+public readonly role: IRole;
+```
+
+- *Type:* aws-cdk-lib.aws_iam.IRole
+
+---
+
+##### `sourceStream`<sup>Optional</sup> <a name="sourceStream" id="aws-ddk-core.DeliveryStreamProps.property.sourceStream"></a>
+
+```typescript
+public readonly sourceStream: IStream;
+```
+
+- *Type:* aws-cdk-lib.aws_kinesis.IStream
+
+---
+
 ### EventStageProps <a name="EventStageProps" id="aws-ddk-core.EventStageProps"></a>
 
 #### Initializer <a name="Initializer" id="aws-ddk-core.EventStageProps.Initializer"></a>
@@ -6735,10 +7026,12 @@ const firehoseToS3StageProps: FirehoseToS3StageProps = { ... }
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.name">name</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.alarmsEnabled">alarmsEnabled</a></code> | <code>boolean</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.dataOutputPrefix">dataOutputPrefix</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.dataStream">dataStream</a></code> | <code>aws-cdk-lib.aws_kinesis.Stream</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.dataStreamEnabled">dataStreamEnabled</a></code> | <code>boolean</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.deliveryStreamDataFreshnessErrorsAlarmThreshold">deliveryStreamDataFreshnessErrorsAlarmThreshold</a></code> | <code>number</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.deliveryStreamDataFreshnessErrorsEvaluationPeriods">deliveryStreamDataFreshnessErrorsEvaluationPeriods</a></code> | <code>number</code> | *No description.* |
-| <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.firehoseDeliveryStreamProps">firehoseDeliveryStreamProps</a></code> | <code>@aws-cdk/aws-kinesisfirehose-alpha.DeliveryStreamProps</code> | *No description.* |
+| <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.firehoseDeliveryStream">firehoseDeliveryStream</a></code> | <code>@aws-cdk/aws-kinesisfirehose-alpha.DeliveryStream</code> | *No description.* |
+| <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.firehoseDeliveryStreamProps">firehoseDeliveryStreamProps</a></code> | <code><a href="#aws-ddk-core.DeliveryStreamProps">DeliveryStreamProps</a></code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.kinesisFirehoseDestinationsS3BucketProps">kinesisFirehoseDestinationsS3BucketProps</a></code> | <code>@aws-cdk/aws-kinesisfirehose-destinations-alpha.S3BucketProps</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.s3Bucket">s3Bucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | *No description.* |
 | <code><a href="#aws-ddk-core.FirehoseToS3StageProps.property.s3BucketProps">s3BucketProps</a></code> | <code>aws-cdk-lib.aws_s3.BucketProps</code> | *No description.* |
@@ -6785,6 +7078,16 @@ public readonly dataOutputPrefix: string;
 
 ---
 
+##### `dataStream`<sup>Optional</sup> <a name="dataStream" id="aws-ddk-core.FirehoseToS3StageProps.property.dataStream"></a>
+
+```typescript
+public readonly dataStream: Stream;
+```
+
+- *Type:* aws-cdk-lib.aws_kinesis.Stream
+
+---
+
 ##### `dataStreamEnabled`<sup>Optional</sup> <a name="dataStreamEnabled" id="aws-ddk-core.FirehoseToS3StageProps.property.dataStreamEnabled"></a>
 
 ```typescript
@@ -6815,13 +7118,23 @@ public readonly deliveryStreamDataFreshnessErrorsEvaluationPeriods: number;
 
 ---
 
+##### `firehoseDeliveryStream`<sup>Optional</sup> <a name="firehoseDeliveryStream" id="aws-ddk-core.FirehoseToS3StageProps.property.firehoseDeliveryStream"></a>
+
+```typescript
+public readonly firehoseDeliveryStream: DeliveryStream;
+```
+
+- *Type:* @aws-cdk/aws-kinesisfirehose-alpha.DeliveryStream
+
+---
+
 ##### `firehoseDeliveryStreamProps`<sup>Optional</sup> <a name="firehoseDeliveryStreamProps" id="aws-ddk-core.FirehoseToS3StageProps.property.firehoseDeliveryStreamProps"></a>
 
 ```typescript
 public readonly firehoseDeliveryStreamProps: DeliveryStreamProps;
 ```
 
-- *Type:* @aws-cdk/aws-kinesisfirehose-alpha.DeliveryStreamProps
+- *Type:* <a href="#aws-ddk-core.DeliveryStreamProps">DeliveryStreamProps</a>
 
 ---
 
@@ -7021,6 +7334,45 @@ public readonly rolePolicyStatements: PolicyStatement[];
 
 ---
 
+### GetTagsProps <a name="GetTagsProps" id="aws-ddk-core.GetTagsProps"></a>
+
+#### Initializer <a name="Initializer" id="aws-ddk-core.GetTagsProps.Initializer"></a>
+
+```typescript
+import { GetTagsProps } from 'aws-ddk-core'
+
+const getTagsProps: GetTagsProps = { ... }
+```
+
+#### Properties <a name="Properties" id="Properties"></a>
+
+| **Name** | **Type** | **Description** |
+| --- | --- | --- |
+| <code><a href="#aws-ddk-core.GetTagsProps.property.configPath">configPath</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.GetTagsProps.property.environmentId">environmentId</a></code> | <code>string</code> | *No description.* |
+
+---
+
+##### `configPath`<sup>Required</sup> <a name="configPath" id="aws-ddk-core.GetTagsProps.property.configPath"></a>
+
+```typescript
+public readonly configPath: string;
+```
+
+- *Type:* string
+
+---
+
+##### `environmentId`<sup>Optional</sup> <a name="environmentId" id="aws-ddk-core.GetTagsProps.property.environmentId"></a>
+
+```typescript
+public readonly environmentId: string;
+```
+
+- *Type:* string
+
+---
+
 ### GlueTransformStageProps <a name="GlueTransformStageProps" id="aws-ddk-core.GlueTransformStageProps"></a>
 
 #### Initializer <a name="Initializer" id="aws-ddk-core.GlueTransformStageProps.Initializer"></a>
@@ -7046,12 +7398,15 @@ const glueTransformStageProps: GlueTransformStageProps = { ... }
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.crawlerAllowFailure">crawlerAllowFailure</a></code> | <code>boolean</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.crawlerName">crawlerName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.crawlerProps">crawlerProps</a></code> | <code>aws-cdk-lib.aws_glue.CfnCrawlerProps</code> | *No description.* |
+| <code><a href="#aws-ddk-core.GlueTransformStageProps.property.crawlerRole">crawlerRole</a></code> | <code>string</code> | *No description.* |
+| <code><a href="#aws-ddk-core.GlueTransformStageProps.property.databaseName">databaseName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.jobName">jobName</a></code> | <code>string</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.jobProps">jobProps</a></code> | <code>@aws-cdk/aws-glue-alpha.JobProps</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.jobRunArgs">jobRunArgs</a></code> | <code>{[ key: string ]: any}</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.stateMachineRetryBackoffRate">stateMachineRetryBackoffRate</a></code> | <code>number</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.stateMachineRetryInterval">stateMachineRetryInterval</a></code> | <code>aws-cdk-lib.Duration</code> | *No description.* |
 | <code><a href="#aws-ddk-core.GlueTransformStageProps.property.stateMachineRetryMaxAttempts">stateMachineRetryMaxAttempts</a></code> | <code>number</code> | *No description.* |
+| <code><a href="#aws-ddk-core.GlueTransformStageProps.property.targets">targets</a></code> | <code>aws-cdk-lib.aws_glue.CfnCrawler.TargetsProperty</code> | *No description.* |
 
 ---
 
@@ -7165,6 +7520,26 @@ public readonly crawlerProps: CfnCrawlerProps;
 
 ---
 
+##### `crawlerRole`<sup>Optional</sup> <a name="crawlerRole" id="aws-ddk-core.GlueTransformStageProps.property.crawlerRole"></a>
+
+```typescript
+public readonly crawlerRole: string;
+```
+
+- *Type:* string
+
+---
+
+##### `databaseName`<sup>Optional</sup> <a name="databaseName" id="aws-ddk-core.GlueTransformStageProps.property.databaseName"></a>
+
+```typescript
+public readonly databaseName: string;
+```
+
+- *Type:* string
+
+---
+
 ##### `jobName`<sup>Optional</sup> <a name="jobName" id="aws-ddk-core.GlueTransformStageProps.property.jobName"></a>
 
 ```typescript
@@ -7225,6 +7600,16 @@ public readonly stateMachineRetryMaxAttempts: number;
 
 ---
 
+##### `targets`<sup>Optional</sup> <a name="targets" id="aws-ddk-core.GlueTransformStageProps.property.targets"></a>
+
+```typescript
+public readonly targets: TargetsProperty;
+```
+
+- *Type:* aws-cdk-lib.aws_glue.CfnCrawler.TargetsProperty
+
+---
+
 ### PermissionsBoundaryProps <a name="PermissionsBoundaryProps" id="aws-ddk-core.PermissionsBoundaryProps"></a>
 
 #### Initializer <a name="Initializer" id="aws-ddk-core.PermissionsBoundaryProps.Initializer"></a>
@@ -9137,6 +9522,7 @@ public tagConstruct(scope: Construct, tags: {[ key: string ]: string}): void
 | **Name** | **Description** |
 | --- | --- |
 | <code><a href="#aws-ddk-core.Configurator.getEnvConfig">getEnvConfig</a></code> | *No description.* |
+| <code><a href="#aws-ddk-core.Configurator.getTags">getTags</a></code> | *No description.* |
 
 ---
 
@@ -9154,6 +9540,20 @@ Configurator.getEnvConfig(props: GetEnvConfigProps)
 
 ---
 
+##### `getTags` <a name="getTags" id="aws-ddk-core.Configurator.getTags"></a>
+
+```typescript
+import { Configurator } from 'aws-ddk-core'
+
+Configurator.getTags(props: GetTagsProps)
+```
+
+###### `props`<sup>Required</sup> <a name="props" id="aws-ddk-core.Configurator.getTags.parameter.props"></a>
+
+- *Type:* <a href="#aws-ddk-core.GetTagsProps">GetTagsProps</a>
+
+---
+
 #### Properties <a name="Properties" id="Properties"></a>
 
 | **Name** | **Type** | **Description** |
diff --git a/src/base/stack.ts b/src/base/stack.ts
index 5d9461b4..2008eeb7 100644
--- a/src/base/stack.ts
+++ b/src/base/stack.ts
@@ -9,7 +9,86 @@ export interface BaseStackProps extends cdk.StackProps {
   readonly config?: string | object;
 }
 
+export interface PermissionsBoundaryProps {
+  readonly environmentId?: string;
+  readonly prefix?: string;
+  readonly qualifier?: string;
+}
+
 export class BaseStack extends cdk.Stack {
+  public static createDefaultPermissionsBoundary(
+    scope: Construct,
+    id: string,
+    props: PermissionsBoundaryProps,
+  ): iam.IManagedPolicy {
+    const prefix = props.prefix ?? "ddk";
+    const environmentId = props.environmentId ?? "dev";
+    const qualifier = props.environmentId ?? "hnb659fds";
+
+    const policyStatements = [
+      new iam.PolicyStatement({
+        effect: iam.Effect.DENY,
+        actions: ["s3:PutAccountPublicAccessBlock"],
+        resources: ["*"],
+      }),
+      new iam.PolicyStatement({
+        effect: iam.Effect.DENY,
+        actions: [
+          "iam:CreatePolicyVersion",
+          "iam:DeletePolicy",
+          "iam:DeletePolicyVersion",
+          "iam:SetDefaultPolicyVersion",
+        ],
+        resources: [
+          `arn:${cdk.Stack.of(scope).partition}:iam::${
+            cdk.Stack.of(scope).account
+          }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
+            cdk.Stack.of(scope).region
+          }`,
+        ],
+      }),
+      new iam.PolicyStatement({
+        effect: iam.Effect.DENY,
+        actions: ["iam:DeleteRolePermissionsBoundary"],
+        resources: [`arn:${cdk.Stack.of(scope).partition}:iam::${cdk.Stack.of(scope).account}:role/*`],
+        conditions: {
+          "ForAnyValue:StringEquals": {
+            "iam:PermissionsBoundary": `arn:${cdk.Stack.of(scope).partition}:iam::${
+              cdk.Stack.of(scope).account
+            }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
+              cdk.Stack.of(scope).region
+            }`,
+          },
+        },
+      }),
+      new iam.PolicyStatement({
+        effect: iam.Effect.DENY,
+        actions: ["iam:PutRolePermissionsBoundary"],
+        resources: [`arn:${cdk.Stack.of(scope).partition}:iam::${cdk.Stack.of(scope).account}:role/*`],
+        conditions: {
+          "ForAnyValue:StringNotEquals": {
+            "iam:PermissionsBoundary": `arn:${cdk.Stack.of(scope).partition}:iam::${
+              cdk.Stack.of(scope).account
+            }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
+              cdk.Stack.of(scope).region
+            }`,
+          },
+        },
+      }),
+      new iam.PolicyStatement({
+        effect: iam.Effect.ALLOW,
+        actions: ["*"],
+        resources: ["*"],
+      }),
+    ];
+    return new iam.ManagedPolicy(scope, id, {
+      statements: policyStatements,
+      managedPolicyName: `${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
+        cdk.Stack.of(scope).region
+      }`,
+      description: "AWS-DDK: Deny dangerous actions that could escalate privilege or cause security incident",
+    });
+  }
   readonly terminationProtection?: boolean | undefined;
 
   constructor(scope: Construct, id: string, props: BaseStackProps) {
@@ -27,79 +106,3 @@ export class BaseStack extends cdk.Stack {
     }
   }
 }
-
-export interface PermissionsBoundaryProps {
-  readonly environmentId?: string;
-  readonly prefix?: string;
-  readonly qualifier?: string;
-}
-
-export function createDefaultPermissionsBoundary(scope: Construct, id: string, props: PermissionsBoundaryProps) {
-  const prefix = props.prefix ?? "ddk";
-  const environmentId = props.environmentId ?? "dev";
-  const qualifier = props.environmentId ?? "hnb659fds";
-
-  const policyStatements = [
-    new iam.PolicyStatement({
-      effect: iam.Effect.DENY,
-      actions: ["s3:PutAccountPublicAccessBlock"],
-      resources: ["*"],
-    }),
-    new iam.PolicyStatement({
-      effect: iam.Effect.DENY,
-      actions: [
-        "iam:CreatePolicyVersion",
-        "iam:DeletePolicy",
-        "iam:DeletePolicyVersion",
-        "iam:SetDefaultPolicyVersion",
-      ],
-      resources: [
-        `arn:${cdk.Stack.of(scope).partition}:iam::${
-          cdk.Stack.of(scope).account
-        }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
-          cdk.Stack.of(scope).region
-        }`,
-      ],
-    }),
-    new iam.PolicyStatement({
-      effect: iam.Effect.DENY,
-      actions: ["iam:DeleteRolePermissionsBoundary"],
-      resources: [`arn:${cdk.Stack.of(scope).partition}:iam::${cdk.Stack.of(scope).account}:role/*`],
-      conditions: {
-        "ForAnyValue:StringEquals": {
-          "iam:PermissionsBoundary": `arn:${cdk.Stack.of(scope).partition}:iam::${
-            cdk.Stack.of(scope).account
-          }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
-            cdk.Stack.of(scope).region
-          }`,
-        },
-      },
-    }),
-    new iam.PolicyStatement({
-      effect: iam.Effect.DENY,
-      actions: ["iam:PutRolePermissionsBoundary"],
-      resources: [`arn:${cdk.Stack.of(scope).partition}:iam::${cdk.Stack.of(scope).account}:role/*`],
-      conditions: {
-        "ForAnyValue:StringNotEquals": {
-          "iam:PermissionsBoundary": `arn:${cdk.Stack.of(scope).partition}:iam::${
-            cdk.Stack.of(scope).account
-          }:policy/${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
-            cdk.Stack.of(scope).region
-          }`,
-        },
-      },
-    }),
-    new iam.PolicyStatement({
-      effect: iam.Effect.ALLOW,
-      actions: ["*"],
-      resources: ["*"],
-    }),
-  ];
-  return new iam.ManagedPolicy(scope, id, {
-    statements: policyStatements,
-    managedPolicyName: `${prefix}-${environmentId}-${qualifier}-permissions-boundary-${cdk.Stack.of(scope).account}-${
-      cdk.Stack.of(scope).region
-    }`,
-    description: "AWS-DDK: Deny dangerous actions that could escalate privilege or cause security incident",
-  });
-}
diff --git a/src/config/configurator.ts b/src/config/configurator.ts
index a3f0faff..29509602 100644
--- a/src/config/configurator.ts
+++ b/src/config/configurator.ts
@@ -129,11 +129,26 @@ export interface GetEnvConfigProps {
   readonly environmentId: string;
 }
 
+export interface GetTagsProps {
+  readonly configPath: string;
+  readonly environmentId?: string;
+}
+
 export class Configurator {
   public static getEnvConfig(props: GetEnvConfigProps): any {
     const config = getConfig({ config: props.configPath });
     return config.environments ? config.environments[props.environmentId] : undefined;
   }
+  public static getTags(props: GetTagsProps): any {
+    const config = getConfig({ config: props.configPath });
+    return props.environmentId
+      ? config.environments
+        ? config.environments[props.environmentId].tags
+        : {}
+      : config.tags
+      ? config.tags
+      : {};
+  }
   public readonly config: any;
   public readonly environmentId?: string;
   constructor(scope: constructs.Construct, config: string | object, environmentId?: string) {
diff --git a/src/core/glue-factory.ts b/src/core/glue-factory.ts
index b3d5e1fe..0b74ac89 100644
--- a/src/core/glue-factory.ts
+++ b/src/core/glue-factory.ts
@@ -5,15 +5,18 @@ import { overrideProps } from "./utils";
 
 export class GlueFactory {
   public static job(scope: Construct, id: string, props: glue.JobProps) {
+    const securityConfiguration = !props.securityConfiguration
+      ? new glue.SecurityConfiguration(scope, `${id}-security-configuration`, {
+          s3Encryption: {
+            mode: glue.S3EncryptionMode.S3_MANAGED,
+          },
+        })
+      : undefined;
     const defaultProps: Partial<glue.JobProps> = {
       maxConcurrentRuns: 1,
       maxRetries: 1,
       timeout: cdk.Duration.hours(10),
-      securityConfiguration: new glue.SecurityConfiguration(scope, `${id}-security-configuration`, {
-        s3Encryption: {
-          mode: glue.S3EncryptionMode.S3_MANAGED,
-        },
-      }),
+      securityConfiguration: securityConfiguration,
     };
 
     const mergedProps = overrideProps(defaultProps, props);
diff --git a/src/pipelines/pipelines.ts b/src/pipelines/pipelines.ts
index 1eb4e21f..4825511f 100644
--- a/src/pipelines/pipelines.ts
+++ b/src/pipelines/pipelines.ts
@@ -48,7 +48,7 @@ export class DataPipeline extends Construct {
     const skipRule = props.skipRule ?? false;
 
     if (props.overrideRule) {
-      this.addRule({ overrideRule: props.overrideRule, schedule: props.schedule });
+      this.addRule({ overrideRule: props.overrideRule, schedule: props.schedule, ruleName: props.ruleName });
     } else if (this.previousStage && skipRule === false) {
       if (stage.targets === undefined) {
         throw new Error(
@@ -61,6 +61,7 @@ export class DataPipeline extends Construct {
         eventPattern: this.previousStage?.eventPattern,
         eventTargets: stage.targets,
         schedule: props.schedule,
+        ruleName: props.ruleName,
       });
     }
 
diff --git a/src/pipelines/stage.ts b/src/pipelines/stage.ts
index 118aa959..79d9e2ec 100644
--- a/src/pipelines/stage.ts
+++ b/src/pipelines/stage.ts
@@ -53,7 +53,7 @@ export abstract class DataStage extends Stage {
         new cloudwatch.Alarm(this, id, {
           metric: props.metric,
           comparisonOperator: props.comparisonOperator ?? cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
-          threshold: props.threshold ?? 5,
+          threshold: props.threshold ?? 1,
           evaluationPeriods: props.evaluationPeriods ?? 1,
         }),
       );
diff --git a/src/stages/databrew-transform.ts b/src/stages/databrew-transform.ts
index ae1194e1..efb4788e 100644
--- a/src/stages/databrew-transform.ts
+++ b/src/stages/databrew-transform.ts
@@ -1,3 +1,4 @@
+import * as cdk from "aws-cdk-lib";
 import * as databrew from "aws-cdk-lib/aws-databrew";
 import * as events from "aws-cdk-lib/aws-events";
 import * as iam from "aws-cdk-lib/aws-iam";
@@ -12,9 +13,23 @@ export interface DataBrewTransformStageProps extends StateMachineStageProps {
   readonly jobRoleArn?: string;
   readonly jobType?: string;
   readonly datasetName?: string;
-  readonly recipe?: databrew.CfnJob.RecipeProperty;
-  readonly outputs?: databrew.CfnJob.OutputProperty[];
   readonly createJob?: boolean;
+  readonly dataCatalogOutputs?: databrew.CfnJob.DataCatalogOutputProperty[];
+  readonly databaseOutputs?: databrew.CfnJob.DatabaseOutputProperty[];
+  readonly encryptionKeyArn?: string;
+  readonly encryptionMode?: string;
+  readonly jobSample?: databrew.CfnJob.JobSampleProperty;
+  readonly logSubscription?: string;
+  readonly maxCapacity?: number;
+  readonly maxRetries?: number;
+  readonly outputLocation?: databrew.CfnJob.OutputLocationProperty;
+  readonly outputs?: databrew.CfnJob.OutputProperty[];
+  readonly profileConfiguration?: databrew.CfnJob.ProfileConfigurationProperty;
+  readonly projectName?: string;
+  readonly recipe?: databrew.CfnJob.RecipeProperty;
+  readonly tags?: cdk.CfnTag[];
+  readonly timeout?: number;
+  readonly validationConfigurations?: databrew.CfnJob.ValidationConfigurationProperty[];
 }
 
 export class DataBrewTransformStage extends StateMachineStage {
@@ -28,21 +43,34 @@ export class DataBrewTransformStage extends StateMachineStage {
   constructor(scope: Construct, id: string, props: DataBrewTransformStageProps) {
     super(scope, id, props);
 
-    const { jobName, jobRoleArn, jobType, datasetName, recipe, outputs, createJob } = props;
-    this.jobName = jobName ? jobName : `${id}-job`;
-    this.createJob = jobName && !createJob ? false : true;
+    this.jobName = props.jobName ? props.jobName : `${id}-job`;
+    this.createJob = props.jobName && !props.createJob ? false : true;
 
     if (this.createJob) {
-      if (!jobType) {
+      if (!props.jobType) {
         throw new Error("if 'jobType' is a required property when creating a new DataBrew job");
       }
       this.job = new databrew.CfnJob(this, "DataBrew Job", {
         name: this.jobName,
-        roleArn: jobRoleArn ? jobRoleArn : this.createDefaultDataBrewJobRole().roleArn,
-        type: jobType,
-        datasetName: datasetName,
-        recipe: recipe,
-        outputs: outputs,
+        roleArn: props.jobRoleArn ? props.jobRoleArn : this.createDefaultDataBrewJobRole().roleArn,
+        type: props.jobType,
+        datasetName: props.datasetName,
+        dataCatalogOutputs: props.dataCatalogOutputs,
+        databaseOutputs: props.databaseOutputs,
+        encryptionKeyArn: props.encryptionKeyArn,
+        encryptionMode: props.encryptionMode,
+        jobSample: props.jobSample,
+        logSubscription: props.logSubscription,
+        maxCapacity: props.maxCapacity,
+        maxRetries: props.maxRetries,
+        outputLocation: props.outputLocation,
+        outputs: props.outputs,
+        profileConfiguration: props.profileConfiguration,
+        projectName: props.projectName,
+        recipe: props.recipe,
+        tags: props.tags,
+        timeout: props.timeout,
+        validationConfigurations: props.validationConfigurations,
       });
     }
     const startJobRun = new tasks.GlueDataBrewStartJobRun(this, "Start DataBrew Job", {
diff --git a/src/stages/glue-transform.ts b/src/stages/glue-transform.ts
index 8ae4d34e..3703694d 100644
--- a/src/stages/glue-transform.ts
+++ b/src/stages/glue-transform.ts
@@ -13,6 +13,9 @@ export interface GlueTransformStageProps extends StateMachineStageProps {
   readonly jobProps?: glue_alpha.JobProps;
   readonly jobRunArgs?: { [key: string]: any };
   readonly crawlerName?: string;
+  readonly crawlerRole?: string;
+  readonly databaseName?: string;
+  readonly targets?: glue.CfnCrawler.TargetsProperty;
   readonly crawlerProps?: glue.CfnCrawlerProps;
   readonly crawlerAllowFailure?: boolean;
   readonly stateMachineRetryMaxAttempts?: number;
@@ -93,11 +96,22 @@ export class GlueTransformStage extends StateMachineStage {
   }
 
   private getCrawler(props: GlueTransformStageProps): glue.CfnCrawler {
-    if (!props.crawlerProps) {
-      throw TypeError("'crawlerName' or 'crawlerProps' must be set to instantiate this stage");
+    const role = props.crawlerRole ?? props.crawlerProps?.role;
+    if (!role) {
+      throw TypeError("Crawler Role must be set either by 'crawlerRole' or 'crawlerProps.role");
     }
 
-    const crawler = new glue.CfnCrawler(this, "Crawler", props.crawlerProps);
+    const targets = props.targets ?? props.crawlerProps?.targets;
+    if (!targets) {
+      throw TypeError("Crawler Targets must be set either by 'targets' or 'crawlerProps.targets");
+    }
+
+    const crawler = new glue.CfnCrawler(this, "Crawler", {
+      role: role,
+      databaseName: props.databaseName,
+      targets: targets,
+      ...props.crawlerProps,
+    });
     return crawler;
   }
 }
diff --git a/src/stages/kinesis-s3.ts b/src/stages/kinesis-s3.ts
index a4d7b7d3..7bf27dba 100644
--- a/src/stages/kinesis-s3.ts
+++ b/src/stages/kinesis-s3.ts
@@ -2,21 +2,33 @@ import * as firehose from "@aws-cdk/aws-kinesisfirehose-alpha";
 import * as destinations from "@aws-cdk/aws-kinesisfirehose-destinations-alpha";
 import * as cdk from "aws-cdk-lib";
 import * as events from "aws-cdk-lib/aws-events";
+import * as iam from "aws-cdk-lib/aws-iam";
 import * as kinesis from "aws-cdk-lib/aws-kinesis";
+import * as kms from "aws-cdk-lib/aws-kms";
 import * as s3 from "aws-cdk-lib/aws-s3";
 import { Construct } from "constructs";
 import { overrideProps } from "../core";
 import { S3Factory } from "../core/s3-factory";
 import { DataStage, DataStageProps } from "../pipelines/stage";
 
+export interface DeliveryStreamProps {
+  readonly destinations?: firehose.IDestination[];
+  readonly deliveryStreamName?: string;
+  readonly encryption?: firehose.StreamEncryption;
+  readonly encryptionKey?: kms.IKey;
+  readonly role?: iam.IRole;
+  readonly sourceStream?: kinesis.IStream;
+}
+
 export interface FirehoseToS3StageProps extends DataStageProps {
   readonly s3Bucket?: s3.IBucket;
   readonly s3BucketProps?: s3.BucketProps;
-  readonly firehoseDeliveryStreamProps?: firehose.DeliveryStreamProps;
+  readonly firehoseDeliveryStream?: firehose.DeliveryStream;
+  readonly firehoseDeliveryStreamProps?: DeliveryStreamProps;
   readonly kinesisFirehoseDestinationsS3BucketProps?: destinations.S3BucketProps;
-
   readonly dataOutputPrefix?: string;
   readonly dataStreamEnabled?: boolean;
+  readonly dataStream?: kinesis.Stream;
   readonly deliveryStreamDataFreshnessErrorsAlarmThreshold?: number;
   readonly deliveryStreamDataFreshnessErrorsEvaluationPeriods?: number;
 }
@@ -43,9 +55,10 @@ export class FirehoseToS3Stage extends DataStage {
       throw TypeError("'s3Bucket' or 's3BucketProps' must be set to instantiate this stage");
     }
 
-    const dataStreamEnabled = props.dataStreamEnabled ?? false;
-    if (dataStreamEnabled == true) {
+    if (props.dataStreamEnabled == true && !props.dataStream) {
       this.dataStream = new kinesis.Stream(this, "Data Stream", {});
+    } else if (props.dataStreamEnabled != false && props.dataStream) {
+      this.dataStream = props.dataStream;
     }
 
     const destinationsBucketProps = overrideProps(
@@ -59,11 +72,13 @@ export class FirehoseToS3Stage extends DataStage {
         dataOutputPrefix: props.dataOutputPrefix,
       },
     );
-    this.deliveryStream = new firehose.DeliveryStream(this, "Delivery Stream", {
-      destinations: [new destinations.S3Bucket(this.bucket, destinationsBucketProps)],
-      sourceStream: this.dataStream,
-      ...props.firehoseDeliveryStreamProps,
-    });
+    this.deliveryStream = props.firehoseDeliveryStream
+      ? props.firehoseDeliveryStream
+      : new firehose.DeliveryStream(this, "Delivery Stream", {
+          destinations: [new destinations.S3Bucket(this.bucket, destinationsBucketProps)],
+          sourceStream: this.dataStream,
+          ...props.firehoseDeliveryStreamProps,
+        });
     const dataOutputPrefix: string = destinationsBucketProps.dataOutputPrefix;
 
     this.addAlarm("Data Freshness Errors", {
diff --git a/src/stages/sqs-lambda.ts b/src/stages/sqs-lambda.ts
index 7f3dfbdf..2d750109 100644
--- a/src/stages/sqs-lambda.ts
+++ b/src/stages/sqs-lambda.ts
@@ -48,18 +48,14 @@ export class SqsToLambdaStage extends DataStage {
       const functionProps: SqsToLambdaStageFunctionProps = props.lambdaFunctionProps;
 
       this.function = new lambda.Function(this, "Process Function", {
-        code: functionProps.code,
-        runtime: functionProps.runtime,
-        handler: functionProps.handler,
         timeout: functionProps.timeout ?? cdk.Duration.seconds(120),
         memorySize: functionProps.memorySize ?? 256,
-        layers: functionProps.layers,
-        role: functionProps.role,
         environment: {
           EVENT_SOURCE: eventSource,
           EVENT_DETAIL_TYPE: eventDetailType,
           ...(functionProps.environment ?? {}),
         },
+        ...functionProps,
       });
     } else {
       throw TypeError("'lambdaFunction' or 'lambdaFunctionProps' must be set to instantiate this stage");
@@ -92,6 +88,7 @@ export class SqsToLambdaStage extends DataStage {
             }
           : undefined,
         fifo: props.sqsQueueProps?.fifo ? props.sqsQueueProps?.fifo : undefined,
+        ...props.sqsQueueProps,
       });
     }
 


Test patch:
diff --git a/test/appflow-ingestion-stage.test.ts b/test/appflow-ingestion-stage.test.ts
index 5daaf5fd..610e05bd 100644
--- a/test/appflow-ingestion-stage.test.ts
+++ b/test/appflow-ingestion-stage.test.ts
@@ -34,7 +34,7 @@ test("AppFlow Ingestion stage creates State Machine, Lambda & Alarm", () => {
     Namespace: "AWS/States",
     Period: 300,
     Statistic: "Sum",
-    Threshold: 5,
+    Threshold: 1,
   });
 });
 
diff --git a/test/base-stack.test.ts b/test/base-stack.test.ts
index 334d3b37..94b1bd24 100644
--- a/test/base-stack.test.ts
+++ b/test/base-stack.test.ts
@@ -4,7 +4,7 @@ import * as cdk from "aws-cdk-lib";
 import { Template } from "aws-cdk-lib/assertions";
 import * as lambda from "aws-cdk-lib/aws-lambda";
 
-import { BaseStack, createDefaultPermissionsBoundary, SqsToLambdaStage } from "../src";
+import { BaseStack, SqsToLambdaStage } from "../src";
 
 test("Base Stack No Bootstrap Config", () => {
   const sampleConfig = {
@@ -310,7 +310,11 @@ test("Base Stack Permissions Boundary", () => {
 test("Test Permissions Boundary Creation and Usage in BaseStack", () => {
   const app = new cdk.App();
   const bootstrapStack = new cdk.Stack(app, "my-bootstrap-stack");
-  const permissionsBoundary = createDefaultPermissionsBoundary(bootstrapStack, "DDK Default Permissions Boundary", {});
+  const permissionsBoundary = BaseStack.createDefaultPermissionsBoundary(
+    bootstrapStack,
+    "DDK Default Permissions Boundary",
+    {},
+  );
   const stack = new BaseStack(app, "my-stack", {
     environmentId: "dev",
     permissionsBoundaryArn: permissionsBoundary.managedPolicyArn,
@@ -337,7 +341,7 @@ test("Test Permissions Boundary Creation and Usage in BaseStack", () => {
 test("Permissions Boundary Creation Full", () => {
   const app = new cdk.App();
   const bootstrapStack = new cdk.Stack(app, "my-bootstrap-stack");
-  createDefaultPermissionsBoundary(bootstrapStack, "DDK Default Permissions Boundary", {
+  BaseStack.createDefaultPermissionsBoundary(bootstrapStack, "DDK Default Permissions Boundary", {
     prefix: "custom",
     environmentId: "stage",
     qualifier: "abcdefgh",
diff --git a/test/config.test.ts b/test/config.test.ts
index 866c169a..e1b32778 100644
--- a/test/config.test.ts
+++ b/test/config.test.ts
@@ -467,3 +467,12 @@ test("Get Env Config Static Method", () => {
   assert(config === expectedDevConfig);
   assert(nullConfig === undefined);
 });
+
+test("Get Tags", () => {
+  const devTags = Configurator.getTags({ configPath: "./test/test-config.yaml", environmentId: "dev" });
+  const prodTags = Configurator.getTags({ configPath: "./test/test-config.yaml", environmentId: "prod" });
+  const globalTags = Configurator.getTags({ configPath: "./test/test-config.yaml" });
+  assert(devTags.CostCenter === "2014");
+  assert(prodTags.CostCenter === "2015");
+  assert(globalTags["global:foo"] === "bar");
+});
diff --git a/test/data-pipelines.test.ts b/test/data-pipelines.test.ts
index 360fdd06..4359540d 100644
--- a/test/data-pipelines.test.ts
+++ b/test/data-pipelines.test.ts
@@ -181,3 +181,46 @@ test("DataPipeline with skip rule", () => {
   const template = Template.fromStack(stack);
   template.resourceCountIs("AWS::Events::Rule", 0);
 });
+
+test("DataPipeline Rule Name", () => {
+  const stack = new cdk.Stack();
+
+  const bucket = new s3.Bucket(stack, "Bucket");
+
+  const firehoseToS3Stage = new FirehoseToS3Stage(stack, "Firehose To S3 Stage", { s3Bucket: bucket });
+
+  const sqsToLambdaStage = new SqsToLambdaStage(stack, "SQS To Lambda Stage 2", {
+    lambdaFunctionProps: {
+      code: lambda.Code.fromAsset(path.join(__dirname, "/../src/")),
+      handler: "commons.handlers.lambda_handler",
+      memorySize: 512,
+      runtime: lambda.Runtime.PYTHON_3_9,
+      layers: [
+        lambda.LayerVersion.fromLayerVersionArn(stack, "Layer", "arn:aws:lambda:us-east-1:222222222222:layer:dummy:1"),
+      ],
+    },
+  });
+
+  const pipeline = new DataPipeline(stack, "Pipeline", {});
+
+  pipeline.addStage({ stage: firehoseToS3Stage }).addStage({ stage: sqsToLambdaStage, ruleName: "foobar" });
+
+  const template = Template.fromStack(stack);
+
+  template.resourceCountIs("AWS::Events::Rule", 1);
+  template.hasResourceProperties("AWS::Events::Rule", {
+    State: "ENABLED",
+    Name: "foobar",
+    EventPattern: Match.objectLike({
+      "detail-type": firehoseToS3Stage.eventPattern?.detailType,
+      source: firehoseToS3Stage.eventPattern?.source,
+    }),
+    Targets: Match.arrayEquals([
+      Match.objectLike({
+        Arn: {
+          "Fn::GetAtt": [stack.resolve((sqsToLambdaStage.queue.node.defaultChild as cdk.CfnElement).logicalId), "Arn"],
+        },
+      }),
+    ]),
+  });
+});
diff --git a/test/databrew-transform-stage.test.ts b/test/databrew-transform-stage.test.ts
index cb892af6..5eae078b 100644
--- a/test/databrew-transform-stage.test.ts
+++ b/test/databrew-transform-stage.test.ts
@@ -24,7 +24,7 @@ test("DataBrew Transfrom stage creates State Machine & Alarm", () => {
     Namespace: "AWS/States",
     Period: 300,
     Statistic: "Sum",
-    Threshold: 5,
+    Threshold: 1,
   });
 });
 
@@ -108,3 +108,38 @@ test("DataBrew Transform must have 'jobType' if 'createJob' is enabled or no exi
     });
   }).toThrowError("if 'jobType' is a required property when creating a new DataBrew job");
 });
+
+test("DataBrew Transfrom stage additional properties", () => {
+  const stack = new cdk.Stack();
+
+  new DataBrewTransformStage(stack, "databrew-transform", {
+    jobName: "dummy-job",
+    jobType: "PROFILE",
+    createJob: true,
+    maxCapacity: 2,
+    maxRetries: 2,
+    encryptionMode: "SSE-S3",
+  });
+
+  const template = Template.fromStack(stack);
+  template.hasResourceProperties("AWS::DataBrew::Job", {
+    Name: "dummy-job",
+    Type: "PROFILE",
+    MaxCapacity: 2,
+    MaxRetries: 2,
+  });
+  template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
+    DefinitionString: {
+      "Fn::Join": ["", Match.arrayWith([Match.stringLikeRegexp("Start DataBrew Job")])],
+    },
+  });
+  template.hasResourceProperties("AWS::CloudWatch::Alarm", {
+    ComparisonOperator: "GreaterThanThreshold",
+    EvaluationPeriods: 1,
+    MetricName: "ExecutionsFailed",
+    Namespace: "AWS/States",
+    Period: 300,
+    Statistic: "Sum",
+    Threshold: 1,
+  });
+});
diff --git a/test/glue-transform-stage.test.ts b/test/glue-transform-stage.test.ts
index bcd17687..a92be247 100644
--- a/test/glue-transform-stage.test.ts
+++ b/test/glue-transform-stage.test.ts
@@ -75,6 +75,31 @@ test("GlueTransformStage stage creates Glue Crawler", () => {
   });
 });
 
+test("GlueTransformStage stage creates Glue Crawler 2", () => {
+  const stack = new cdk.Stack();
+
+  new GlueTransformStage(stack, "glue-transform", {
+    jobName: "myJob",
+    crawlerRole: "role",
+    targets: {
+      s3Targets: [
+        {
+          path: "s3://my-bucket/crawl-path",
+        },
+      ],
+    },
+  });
+
+  const template = Template.fromStack(stack);
+  template.resourceCountIs("AWS::Glue::Job", 0);
+  template.hasResourceProperties("AWS::Glue::Crawler", {
+    Role: "role",
+    Targets: {
+      S3Targets: [{ Path: "s3://my-bucket/crawl-path" }],
+    },
+  });
+});
+
 test("GlueTranformStage must have 'jobName' or 'jobProps' set", () => {
   const stack = new cdk.Stack();
   expect(() => {
@@ -82,13 +107,23 @@ test("GlueTranformStage must have 'jobName' or 'jobProps' set", () => {
   }).toThrowError("'jobName' or 'jobProps' must be set to instantiate this stage");
 });
 
-test("GlueTranformStage must have 'crawlerName' or 'crawlerProps' set", () => {
+test("GlueTranformStage must set crawler role ", () => {
+  const stack = new cdk.Stack();
+  expect(() => {
+    new GlueTransformStage(stack, "Stage", {
+      jobName: "myJob",
+    });
+  }).toThrowError("Crawler Role must be set either by 'crawlerRole' or 'crawlerProps.role");
+});
+
+test("GlueTranformStage must set crawler targets", () => {
   const stack = new cdk.Stack();
   expect(() => {
     new GlueTransformStage(stack, "Stage", {
       jobName: "myJob",
+      crawlerRole: "arn:aws:iam::role/dummy-role",
     });
-  }).toThrowError("'crawlerName' or 'crawlerProps' must be set to instantiate this stage");
+  }).toThrowError("Crawler Targets must be set either by 'targets' or 'crawlerProps.targets");
 });
 
 test("GlueTransformStage retry settings", () => {
diff --git a/test/kinesis-s3-stage.test.ts b/test/kinesis-s3-stage.test.ts
index 8d6a3394..c10b2363 100644
--- a/test/kinesis-s3-stage.test.ts
+++ b/test/kinesis-s3-stage.test.ts
@@ -1,6 +1,9 @@
+import * as firehose from "@aws-cdk/aws-kinesisfirehose-alpha";
+import * as destinations from "@aws-cdk/aws-kinesisfirehose-destinations-alpha";
 import * as cdk from "aws-cdk-lib";
 import { Size } from "aws-cdk-lib";
 import { Match, Template } from "aws-cdk-lib/assertions";
+import * as kinesis from "aws-cdk-lib/aws-kinesis";
 import { Bucket } from "aws-cdk-lib/aws-s3";
 
 import { FirehoseToS3Stage } from "../src";
@@ -51,7 +54,7 @@ test("FirehoseToS3Stage creates Firehose DeliveryStream and S3 Bucket", () => {
 
   template.hasResourceProperties("AWS::CloudWatch::Alarm", {
     MetricName: "DeliveryToS3.DataFreshness",
-    Threshold: 5,
+    Threshold: 1,
     EvaluationPeriods: 1,
     Dimensions: Match.arrayWith([
       Match.objectLike({
@@ -95,6 +98,48 @@ test("FirehoseToS3Stage uses S3 Bucket and creates Kinesis DataStream", () => {
   });
 });
 
+test("FirehoseToS3Stage uses existing S3 Bucket and Kinesis DataStream", () => {
+  const stack = new cdk.Stack();
+
+  const stage = new FirehoseToS3Stage(stack, "Stage", {
+    s3Bucket: new Bucket(stack, "Bucket"),
+    dataStream: new kinesis.Stream(stack, "Stream"),
+    deliveryStreamDataFreshnessErrorsAlarmThreshold: 10,
+  });
+
+  const template = Template.fromStack(stack);
+
+  template.resourceCountIs("AWS::S3::Bucket", 1);
+  template.resourceCountIs("AWS::Kinesis::Stream", 1);
+
+  template.hasResourceProperties("AWS::KinesisFirehose::DeliveryStream", {
+    KinesisStreamSourceConfiguration: Match.objectLike({
+      KinesisStreamARN: Match.objectLike({
+        "Fn::GetAtt": Match.arrayWith([
+          stack.resolve((stage.dataStream?.node.defaultChild as cdk.CfnElement).logicalId),
+          "Arn",
+        ]),
+      }),
+    }),
+  });
+});
+
+test("FirehoseToS3Stage uses existing S3 Bucket and Firehose DeliveryStream", () => {
+  const stack = new cdk.Stack();
+  const s3Bucket = new Bucket(stack, "Bucket");
+  new FirehoseToS3Stage(stack, "Stage", {
+    s3Bucket: s3Bucket,
+    firehoseDeliveryStream: new firehose.DeliveryStream(stack, "DeliveryStream", {
+      destinations: [new destinations.S3Bucket(s3Bucket, {})],
+    }),
+  });
+
+  const template = Template.fromStack(stack);
+
+  template.resourceCountIs("AWS::S3::Bucket", 1);
+  template.resourceCountIs("AWS::KinesisFirehose::DeliveryStream", 1);
+});
+
 test("FirehoseToS3Stage uses dataOutputPrefix in Firehose DeliveryStream", () => {
   const stack = new cdk.Stack();
   const bucket = new Bucket(stack, "Bucket");
diff --git a/test/sqs-lambda-stage.test.ts b/test/sqs-lambda-stage.test.ts
index aa3c38d1..3993f6e9 100644
--- a/test/sqs-lambda-stage.test.ts
+++ b/test/sqs-lambda-stage.test.ts
@@ -205,6 +205,7 @@ test("SQSToLambdaStage additional properties", () => {
 
   new SqsToLambdaStage(stack, "Stage", {
     lambdaFunctionProps: {
+      functionName: "dummy-function",
       code: lambda.Code.fromAsset(path.join(__dirname, "/../src/")),
       handler: "commons.handlers.lambda_handler",
       runtime: lambda.Runtime.PYTHON_3_8,
@@ -213,6 +214,7 @@ test("SQSToLambdaStage additional properties", () => {
     maxReceiveCount: 2,
     dlqEnabled: true,
     sqsQueueProps: {
+      queueName: "dummy-queue.fifo",
       fifo: true,
       visibilityTimeout: cdk.Duration.minutes(5),
     },
@@ -222,9 +224,11 @@ test("SQSToLambdaStage additional properties", () => {
 
   template.hasResourceProperties("AWS::Lambda::Function", {
     Runtime: "python3.8",
+    FunctionName: "dummy-function",
   });
   template.resourceCountIs("AWS::SQS::Queue", 2);
   template.hasResourceProperties("AWS::SQS::Queue", {
     VisibilityTimeout: 300,
+    QueueName: "dummy-queue.fifo",
   });
 });