Repository: cloudcomponents/cdk-constructs (language: python)

Issue:
Stripe Webhook does not work with secrets vended by SecretsManager
What I'm trying to do:
```ts
...
const secretKey = SecretValue.secretsManager(stripeKeySecretName)
...

new StripeWebhook(this, 'StripeWebhook', {
            secretKey: secretKey.toString(),
            url: api.url,
            events,
            logLevel: 'debug',
        })
```

That is to read stripe secret key value from SecretsManager vs providing it in code which is problematic.  
I get the following error when trying to deploy this:

```
6:44:59 PM | CREATE_FAILED        | Custom::StripeWebhook       | StripeWebhookCustomResource8D1A2FEA
Failed to create resource. Invalid API Key provided: {{resolv********************************************************
*************************************************::}}
```

**Expected outcome:**

The key can be resolved from secrets manager.

---
Ideally I think this interface would actually accept the `SecretValue` instead of a string (and you can build that either directly from text or from SecretsManager/SSM/etc


Discussion / hints:
It's been on my to-do list for a long time. But unfortunately cloudformation doesn't support that yet:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html
_Dynamic references for secure values, such as ssm-secure and secretsmanager, are not currently supported in custom resources._

One possible solution would be pass the ARN as a parameter and read the secret in the lambda
>One possible solution would be pass the ARN as a parameter and read the secret in the lambda

I think that'd be the  best approach given current limitations. 

a very basic level support can be just resolving secret into env variables in lambda (which is not idea but cfn-supported)

Fix patch:
diff --git a/README.md b/README.md
index bc8ae703d..e0d794de1 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ This repository is a monorepo managed with [Lerna](https://github.com/lerna/lern
 | [cdk-temp-stack](/packages/cdk-temp-stack) | A stack that destroys itself after a given time (ttl)        | ![npm](https://img.shields.io/npm/dm/@cloudcomponents/cdk-temp-stack) |
 | [cdk-lambda-at-edge-pattern](/packages/cdk-lambda-at-edge-pattern) | CDK Constructs for Lambda@Edge pattern: HttpHeaders     | ![npm](https://img.shields.io/npm/dm/@cloudcomponents/cdk-lambda-at-edge-pattern) |
 | [cdk-cloudfront-authorization](/packages/cdk-cloudfront-authorization) | CloudFront with Cognito authentication using Lambda@Edge     | ![npm](https://img.shields.io/npm/dm/@cloudcomponents/cdk-cloudfront-authorization) |
-
+| [cdk-secret-key](/packages/cdk-secret-key) | Provide secret keys to lambdas     | ![npm](https://img.shields.io/npm/dm/@cloudcomponents/cdk-secret-key) |
 ## Contributing
 
 We welcome community contributions and pull requests.
diff --git a/examples/contentful-webhook-example/package.json b/examples/contentful-webhook-example/package.json
index 58f8d2099..ce56e4d86 100644
--- a/examples/contentful-webhook-example/package.json
+++ b/examples/contentful-webhook-example/package.json
@@ -11,6 +11,7 @@
   "dependencies": {
     "@aws-cdk/aws-apigateway": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0",
     "@cloudcomponents/cdk-contentful-webhook": "^1.28.0",
     "source-map-support": "^0.5.19"
   },
diff --git a/examples/contentful-webhook-example/src/contentful-webhook-stack.ts b/examples/contentful-webhook-example/src/contentful-webhook-stack.ts
index 75259d3e1..f14b1317a 100644
--- a/examples/contentful-webhook-example/src/contentful-webhook-stack.ts
+++ b/examples/contentful-webhook-example/src/contentful-webhook-stack.ts
@@ -1,6 +1,7 @@
 import { RestApi } from '@aws-cdk/aws-apigateway';
 import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { ContentfulWebhook } from '@cloudcomponents/cdk-contentful-webhook';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export class ContentfulWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
@@ -9,7 +10,7 @@ export class ContentfulWebhookStack extends Stack {
     const api = new RestApi(this, 'Endpoint');
     api.root.addMethod('POST');
 
-    const accessToken = process.env.ACCESS_TOKEN as string;
+    const accessToken = SecretKey.fromPlainText(process.env.ACCESS_TOKEN as string);
 
     const spaceId = process.env.SPACE_ID as string;
 
diff --git a/examples/github-webhook-example/package.json b/examples/github-webhook-example/package.json
index 96e808765..3ae480a44 100644
--- a/examples/github-webhook-example/package.json
+++ b/examples/github-webhook-example/package.json
@@ -11,6 +11,7 @@
   "dependencies": {
     "@aws-cdk/aws-apigateway": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0",
     "@cloudcomponents/cdk-github-webhook": "^1.28.0",
     "source-map-support": "^0.5.19"
   },
diff --git a/examples/github-webhook-example/src/github-webhook-stack.ts b/examples/github-webhook-example/src/github-webhook-stack.ts
index 506f41b09..2b7b95877 100644
--- a/examples/github-webhook-example/src/github-webhook-stack.ts
+++ b/examples/github-webhook-example/src/github-webhook-stack.ts
@@ -1,6 +1,7 @@
 import { RestApi } from '@aws-cdk/aws-apigateway';
 import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { GithubWebhook } from '@cloudcomponents/cdk-github-webhook';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export class GithubWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
@@ -9,7 +10,7 @@ export class GithubWebhookStack extends Stack {
     const api = new RestApi(this, 'github-webhook');
     api.root.addMethod('POST');
 
-    const githubApiToken = process.env.API_TOKEN as string;
+    const githubApiToken = SecretKey.fromPlainText(process.env.API_TOKEN as string);
 
     // @example https://github.com/cloudcomponents/cdk-constructs
     const githubRepoUrl = process.env.REPO_URL as string;
diff --git a/examples/stripe-webhook-example/package.json b/examples/stripe-webhook-example/package.json
index 77005ee4d..a39466b27 100644
--- a/examples/stripe-webhook-example/package.json
+++ b/examples/stripe-webhook-example/package.json
@@ -11,6 +11,7 @@
   "dependencies": {
     "@aws-cdk/aws-apigateway": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0",
     "@cloudcomponents/cdk-stripe-webhook": "^1.28.0",
     "source-map-support": "^0.5.19"
   },
diff --git a/examples/stripe-webhook-example/src/stripe-webhook-stack.ts b/examples/stripe-webhook-example/src/stripe-webhook-stack.ts
index cdf4234b4..f1e60a348 100644
--- a/examples/stripe-webhook-example/src/stripe-webhook-stack.ts
+++ b/examples/stripe-webhook-example/src/stripe-webhook-stack.ts
@@ -1,7 +1,7 @@
 import { RestApi } from '@aws-cdk/aws-apigateway';
 import { Construct, Stack, StackProps } from '@aws-cdk/core';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 import { StripeWebhook } from '@cloudcomponents/cdk-stripe-webhook';
-
 export class StripeWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
     super(scope, id, props);
@@ -9,7 +9,7 @@ export class StripeWebhookStack extends Stack {
     const api = new RestApi(this, 'Endpoint');
     api.root.addMethod('POST');
 
-    const secretKey = process.env.SECRET_KEY as string;
+    const secretKey = SecretKey.fromPlainText(process.env.SECRET_KEY as string);
 
     const events = ['charge.failed', 'charge.succeeded'];
 
diff --git a/packages/cdk-contentful-webhook/API.md b/packages/cdk-contentful-webhook/API.md
index 2a5a058e5..5f3b4b43f 100644
--- a/packages/cdk-contentful-webhook/API.md
+++ b/packages/cdk-contentful-webhook/API.md
@@ -34,7 +34,7 @@ new ContentfulWebhook(scope: Construct, id: string, props: ContentfulWebhookProp
 * **scope** (<code>[Construct](#aws-cdk-core-construct)</code>)  *No description*
 * **id** (<code>string</code>)  *No description*
 * **props** (<code>[ContentfulWebhookProps](#cloudcomponents-cdk-contentful-webhook-contentfulwebhookprops)</code>)  *No description*
-  * **accessToken** (<code>string</code>)  *No description* 
+  * **accessToken** (<code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>)  *No description* 
   * **name** (<code>string</code>)  *No description* 
   * **spaceId** (<code>string</code>)  *No description* 
   * **topics** (<code>Array<string></code>)  *No description* 
@@ -53,7 +53,7 @@ new ContentfulWebhook(scope: Construct, id: string, props: ContentfulWebhookProp
 
 Name | Type | Description 
 -----|------|-------------
-**accessToken** | <code>string</code> | <span></span>
+**accessToken** | <code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code> | <span></span>
 **name** | <code>string</code> | <span></span>
 **spaceId** | <code>string</code> | <span></span>
 **topics** | <code>Array<string></code> | <span></span>
diff --git a/packages/cdk-contentful-webhook/README.md b/packages/cdk-contentful-webhook/README.md
index 60cca6e98..91ef5c7b6 100644
--- a/packages/cdk-contentful-webhook/README.md
+++ b/packages/cdk-contentful-webhook/README.md
@@ -24,9 +24,10 @@ pip install cloudcomponents.cdk-contentful-webhook
 ## How to use
 
 ```typescript
-import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { RestApi } from '@aws-cdk/aws-apigateway';
+import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { ContentfulWebhook } from '@cloudcomponents/cdk-contentful-webhook';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export class ContentfulWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
@@ -35,7 +36,7 @@ export class ContentfulWebhookStack extends Stack {
     const api = new RestApi(this, 'Endpoint');
     api.root.addMethod('POST');
 
-    const accessToken = process.env.ACCESS_TOKEN as string;
+    const accessToken = SecretKey.fromPlainText(process.env.ACCESS_TOKEN as string);
 
     const spaceId = process.env.SPACE_ID as string;
 
diff --git a/packages/cdk-contentful-webhook/lambda-file-sizes.json b/packages/cdk-contentful-webhook/lambda-file-sizes.json
index 280660b72..faa4fe28a 100644
--- a/packages/cdk-contentful-webhook/lambda-file-sizes.json
+++ b/packages/cdk-contentful-webhook/lambda-file-sizes.json
@@ -1,1 +1,1 @@
-[{"timestamp":1615022511778,"files":[{"filename":"contentful-webhook/index.js","previous":221344,"size":221347,"diff":3}]},{"timestamp":1609970894222,"files":[{"filename":"contentful-webhook/index.js","previous":217379,"size":221344,"diff":3965}]},{"timestamp":1609970375754,"files":[{"filename":"contentful-webhook/index.js","previous":203415,"size":217379,"diff":13964}]},{"timestamp":1607360020128,"files":[{"filename":"contentful-webhook/index.js","previous":203418,"size":203415,"diff":-3}]},{"timestamp":1600966253111,"files":[{"filename":"contentful-webhook/index.js","previous":203440,"size":203418,"diff":-22}]},{"timestamp":1599246565057,"files":[{"filename":"contentful-webhook/index.js","previous":202993,"size":203440,"diff":447}]},{"timestamp":1598552652514,"files":[{"filename":"contentful-webhook/index.js","previous":202992,"size":202993,"diff":1}]},{"timestamp":1596542526761,"files":[{"filename":"contentful-webhook/index.js","previous":207102,"size":202992,"diff":-4110}]},{"timestamp":1596540034638,"files":[{"filename":"contentful-webhook/index.js","previous":206593,"size":207102,"diff":509}]},{"timestamp":1596457456615,"files":[{"filename":"contentful-webhook/index.js","previous":206357,"size":206593,"diff":236}]},{"timestamp":1596440551356,"files":[{"filename":"contentful-webhook/index.js","previous":206424,"size":206357,"diff":-67}]},{"timestamp":1596437759972,"files":[{"filename":"contentful-webhook/index.js","previous":541950,"size":206424,"diff":-335526}]},{"timestamp":1596413723535,"files":[{"filename":"contentful-webhook/index.js","previous":542071,"size":541950,"diff":-121}]},{"timestamp":1596407623809,"files":[{"filename":"contentful-webhook/index.js","previous":191169,"size":542071,"diff":350902}]}]
+[{"timestamp":1615809010241,"files":[{"filename":"contentful-webhook/index.js","previous":221347,"size":1047464,"diff":826117}]},{"timestamp":1615022511778,"files":[{"filename":"contentful-webhook/index.js","previous":221344,"size":221347,"diff":3}]},{"timestamp":1609970894222,"files":[{"filename":"contentful-webhook/index.js","previous":217379,"size":221344,"diff":3965}]},{"timestamp":1609970375754,"files":[{"filename":"contentful-webhook/index.js","previous":203415,"size":217379,"diff":13964}]},{"timestamp":1607360020128,"files":[{"filename":"contentful-webhook/index.js","previous":203418,"size":203415,"diff":-3}]},{"timestamp":1600966253111,"files":[{"filename":"contentful-webhook/index.js","previous":203440,"size":203418,"diff":-22}]},{"timestamp":1599246565057,"files":[{"filename":"contentful-webhook/index.js","previous":202993,"size":203440,"diff":447}]},{"timestamp":1598552652514,"files":[{"filename":"contentful-webhook/index.js","previous":202992,"size":202993,"diff":1}]},{"timestamp":1596542526761,"files":[{"filename":"contentful-webhook/index.js","previous":207102,"size":202992,"diff":-4110}]},{"timestamp":1596540034638,"files":[{"filename":"contentful-webhook/index.js","previous":206593,"size":207102,"diff":509}]},{"timestamp":1596457456615,"files":[{"filename":"contentful-webhook/index.js","previous":206357,"size":206593,"diff":236}]},{"timestamp":1596440551356,"files":[{"filename":"contentful-webhook/index.js","previous":206424,"size":206357,"diff":-67}]},{"timestamp":1596437759972,"files":[{"filename":"contentful-webhook/index.js","previous":541950,"size":206424,"diff":-335526}]},{"timestamp":1596413723535,"files":[{"filename":"contentful-webhook/index.js","previous":542071,"size":541950,"diff":-121}]},{"timestamp":1596407623809,"files":[{"filename":"contentful-webhook/index.js","previous":191169,"size":542071,"diff":350902}]}]
diff --git a/packages/cdk-contentful-webhook/package.json b/packages/cdk-contentful-webhook/package.json
index cf6bca562..db499d3d9 100644
--- a/packages/cdk-contentful-webhook/package.json
+++ b/packages/cdk-contentful-webhook/package.json
@@ -60,14 +60,17 @@
   "peerDependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0",
     "constructs": "^3.2.0"
   },
   "dependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
-    "@aws-cdk/core": "^1.93.0"
+    "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0"
   },
   "devDependencies": {
     "@aws-cdk/assert": "^1.93.0",
+    "@cloudcomponents/lambda-utils": "^0.1.1",
     "contentful-management": "^6.1.1",
     "custom-resource-helper": "^1.0.15",
     "jest-cdk-snapshot": "^1.4.1"
diff --git a/packages/cdk-contentful-webhook/src/contentful-webhook.ts b/packages/cdk-contentful-webhook/src/contentful-webhook.ts
index afc22d252..8b0ac6cf2 100644
--- a/packages/cdk-contentful-webhook/src/contentful-webhook.ts
+++ b/packages/cdk-contentful-webhook/src/contentful-webhook.ts
@@ -1,9 +1,10 @@
 import * as path from 'path';
 import { SingletonFunction, Runtime, Code } from '@aws-cdk/aws-lambda';
 import { Construct, Duration, CustomResource } from '@aws-cdk/core';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export interface ContentfulWebhookProps {
-  readonly accessToken: string;
+  readonly accessToken: string | SecretKey;
   readonly spaceId: string;
   readonly name: string;
   readonly url: string;
@@ -15,6 +16,8 @@ export class ContentfulWebhook extends Construct {
   public constructor(scope: Construct, id: string, props: ContentfulWebhookProps) {
     super(scope, id);
 
+    const accessToken = typeof props.accessToken === 'string' ? SecretKey.fromPlainText(props.accessToken) : props.accessToken;
+
     const handler = new SingletonFunction(this, 'CustomResourceHandler', {
       uuid: '91f2075f-b950-4743-a66b-ee0f6febf50d',
       runtime: Runtime.NODEJS_12_X,
@@ -24,12 +27,21 @@ export class ContentfulWebhook extends Construct {
       timeout: Duration.minutes(15),
     });
 
+    if (accessToken.grantRead) {
+      accessToken.grantRead(handler);
+    }
+
     new CustomResource(this, 'CustomResource', {
       serviceToken: handler.functionArn,
       resourceType: 'Custom::ContentfulWebhook',
       pascalCaseProperties: true,
       properties: {
-        ...props,
+        accessTokenString: accessToken.serialize(),
+        spaceId: props.spaceId,
+        name: props.name,
+        url: props.url,
+        topics: props.topics,
+        logLevel: props.logLevel,
       },
     });
   }
diff --git a/packages/cdk-contentful-webhook/src/lambdas/contentful-webhook/index.ts b/packages/cdk-contentful-webhook/src/lambdas/contentful-webhook/index.ts
index 0029eb78d..61894aa79 100644
--- a/packages/cdk-contentful-webhook/src/lambdas/contentful-webhook/index.ts
+++ b/packages/cdk-contentful-webhook/src/lambdas/contentful-webhook/index.ts
@@ -1,3 +1,4 @@
+import { SecretKey } from '@cloudcomponents/lambda-utils';
 import type { CloudFormationCustomResourceEventCommon } from 'aws-lambda';
 import * as contentful from 'contentful-management';
 
@@ -11,8 +12,10 @@ import {
   camelizeKeys,
 } from 'custom-resource-helper';
 
+const secretKey = new SecretKey();
+
 export interface WebhookProps {
-  accessToken: string;
+  accessTokenString: string;
   spaceId: string;
   name: string;
   url: string;
@@ -28,10 +31,12 @@ const getSpace = async (accessToken: string, spaceId: string) => {
 };
 
 const handleCreate: OnCreateHandler = async (event): Promise<ResourceHandlerReturn> => {
-  const { accessToken, spaceId, ...props } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { accessTokenString, spaceId, ...props } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
+  const accessToken = await secretKey.getValue(accessTokenString);
+
   const space = await getSpace(accessToken, spaceId);
 
   const res = await space.createWebhook({
@@ -47,10 +52,12 @@ const handleCreate: OnCreateHandler = async (event): Promise<ResourceHandlerRetu
 };
 
 const handleUpdate: OnUpdateHandler = async (event): Promise<ResourceHandlerReturn> => {
-  const { accessToken, spaceId, ...props } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { accessTokenString, spaceId, ...props } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
+  const accessToken = await secretKey.getValue(accessTokenString);
+
   const webhookId = event.PhysicalResourceId;
 
   const space = await getSpace(accessToken, spaceId);
@@ -72,10 +79,12 @@ const handleUpdate: OnUpdateHandler = async (event): Promise<ResourceHandlerRetu
 };
 
 const handleDelete: OnDeleteHandler = async (event): Promise<void> => {
-  const { accessToken, spaceId } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { accessTokenString, spaceId } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
+  const accessToken = await secretKey.getValue(accessTokenString);
+
   const webhookId = event.PhysicalResourceId;
 
   const space = await getSpace(accessToken, spaceId);
diff --git a/packages/cdk-github-webhook/API.md b/packages/cdk-github-webhook/API.md
index 53c6fe565..d33ca4237 100644
--- a/packages/cdk-github-webhook/API.md
+++ b/packages/cdk-github-webhook/API.md
@@ -35,7 +35,7 @@ new GithubWebhook(scope: Construct, id: string, props: GithubWebhookProps)
 * **id** (<code>string</code>)  *No description*
 * **props** (<code>[GithubWebhookProps](#cloudcomponents-cdk-github-webhook-githubwebhookprops)</code>)  *No description*
   * **events** (<code>Array<string></code>)  Determines what events the hook is triggered for. 
-  * **githubApiToken** (<code>string</code>)  The OAuth access token. 
+  * **githubApiToken** (<code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>)  The OAuth access token. 
   * **githubRepoUrl** (<code>string</code>)  The Github repo url. 
   * **payloadUrl** (<code>string</code>)  The URL to which the payloads will be delivered. 
   * **logLevel** (<code>string</code>)  *No description* __*Optional*__
@@ -53,7 +53,7 @@ new GithubWebhook(scope: Construct, id: string, props: GithubWebhookProps)
 Name | Type | Description 
 -----|------|-------------
 **events** | <code>Array<string></code> | Determines what events the hook is triggered for.
-**githubApiToken** | <code>string</code> | The OAuth access token.
+**githubApiToken** | <code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code> | The OAuth access token.
 **githubRepoUrl** | <code>string</code> | The Github repo url.
 **payloadUrl** | <code>string</code> | The URL to which the payloads will be delivered.
 **logLevel**? | <code>string</code> | __*Optional*__
diff --git a/packages/cdk-github-webhook/README.md b/packages/cdk-github-webhook/README.md
index cb10972a6..10eb4438c 100644
--- a/packages/cdk-github-webhook/README.md
+++ b/packages/cdk-github-webhook/README.md
@@ -26,9 +26,10 @@ pip install cloudcomponents.cdk-github-webhook
 ## How to use
 
 ```typescript
-import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { RestApi } from '@aws-cdk/aws-apigateway';
+import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { GithubWebhook } from '@cloudcomponents/cdk-github-webhook';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export class GithubWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
@@ -37,7 +38,7 @@ export class GithubWebhookStack extends Stack {
     const api = new RestApi(this, 'github-webhook');
     api.root.addMethod('POST');
 
-    const githubApiToken = process.env.API_TOKEN as string;
+    const githubApiToken = SecretKey.fromPlainText(process.env.API_TOKEN as string);
 
     // @example https://github.com/cloudcomponents/cdk-constructs
     const githubRepoUrl = process.env.REPO_URL as string;
diff --git a/packages/cdk-github-webhook/lambda-file-sizes.json b/packages/cdk-github-webhook/lambda-file-sizes.json
index e4fe64180..5331eae01 100644
--- a/packages/cdk-github-webhook/lambda-file-sizes.json
+++ b/packages/cdk-github-webhook/lambda-file-sizes.json
@@ -1,1 +1,1 @@
-[{"timestamp":1615023549795,"files":[{"filename":"github-webhook/index.js","previous":182255,"size":182432,"diff":177}]},{"timestamp":1615022566740,"files":[{"filename":"github-webhook/index.js","previous":181954,"size":182255,"diff":301}]},{"timestamp":1614104217580,"files":[{"filename":"github-webhook/index.js","previous":181904,"size":181954,"diff":50}]},{"timestamp":1612464188131,"files":[{"filename":"github-webhook/index.js","previous":181855,"size":181904,"diff":49}]},{"timestamp":1611769329263,"files":[{"filename":"github-webhook/index.js","previous":181805,"size":181855,"diff":50}]},{"timestamp":1609970949480,"files":[{"filename":"github-webhook/index.js","previous":179020,"size":181805,"diff":2785}]},{"timestamp":1607360063925,"files":[{"filename":"github-webhook/index.js","previous":178533,"size":179020,"diff":487}]},{"timestamp":1606896280100,"files":[{"filename":"github-webhook/index.js","previous":177980,"size":178533,"diff":553}]},{"timestamp":1606329557431,"files":[{"filename":"github-webhook/index.js","previous":177960,"size":177980,"diff":20}]},{"timestamp":1604259061964,"files":[{"filename":"github-webhook/index.js","previous":177961,"size":177960,"diff":-1}]},{"timestamp":1600966304194,"files":[{"filename":"github-webhook/index.js","previous":177682,"size":177961,"diff":279}]},{"timestamp":1599246609676,"files":[{"filename":"github-webhook/index.js","previous":177721,"size":177682,"diff":-39}]},{"timestamp":1596542584192,"files":[{"filename":"github-webhook/index.js","previous":181657,"size":177721,"diff":-3936}]},{"timestamp":1596540416823,"files":[{"filename":"github-webhook/index.js","previous":181110,"size":181657,"diff":547}]},{"timestamp":1596457756702,"files":[{"filename":"github-webhook/index.js","previous":181095,"size":181110,"diff":15}]},{"timestamp":1596455025723,"files":[{"filename":"github-webhook/index.js","previous":473647,"size":181095,"diff":-292552}]},{"timestamp":1596407673941,"files":[{"filename":"github-webhook/index.js","previous":332785,"size":473647,"diff":140862}]}]
+[{"timestamp":1615809019316,"files":[{"filename":"github-webhook/index.js","previous":182432,"size":1008634,"diff":826202}]},{"timestamp":1615023549795,"files":[{"filename":"github-webhook/index.js","previous":182255,"size":182432,"diff":177}]},{"timestamp":1615022566740,"files":[{"filename":"github-webhook/index.js","previous":181954,"size":182255,"diff":301}]},{"timestamp":1614104217580,"files":[{"filename":"github-webhook/index.js","previous":181904,"size":181954,"diff":50}]},{"timestamp":1612464188131,"files":[{"filename":"github-webhook/index.js","previous":181855,"size":181904,"diff":49}]},{"timestamp":1611769329263,"files":[{"filename":"github-webhook/index.js","previous":181805,"size":181855,"diff":50}]},{"timestamp":1609970949480,"files":[{"filename":"github-webhook/index.js","previous":179020,"size":181805,"diff":2785}]},{"timestamp":1607360063925,"files":[{"filename":"github-webhook/index.js","previous":178533,"size":179020,"diff":487}]},{"timestamp":1606896280100,"files":[{"filename":"github-webhook/index.js","previous":177980,"size":178533,"diff":553}]},{"timestamp":1606329557431,"files":[{"filename":"github-webhook/index.js","previous":177960,"size":177980,"diff":20}]},{"timestamp":1604259061964,"files":[{"filename":"github-webhook/index.js","previous":177961,"size":177960,"diff":-1}]},{"timestamp":1600966304194,"files":[{"filename":"github-webhook/index.js","previous":177682,"size":177961,"diff":279}]},{"timestamp":1599246609676,"files":[{"filename":"github-webhook/index.js","previous":177721,"size":177682,"diff":-39}]},{"timestamp":1596542584192,"files":[{"filename":"github-webhook/index.js","previous":181657,"size":177721,"diff":-3936}]},{"timestamp":1596540416823,"files":[{"filename":"github-webhook/index.js","previous":181110,"size":181657,"diff":547}]},{"timestamp":1596457756702,"files":[{"filename":"github-webhook/index.js","previous":181095,"size":181110,"diff":15}]},{"timestamp":1596455025723,"files":[{"filename":"github-webhook/index.js","previous":473647,"size":181095,"diff":-292552}]},{"timestamp":1596407673941,"files":[{"filename":"github-webhook/index.js","previous":332785,"size":473647,"diff":140862}]}]
diff --git a/packages/cdk-github-webhook/package.json b/packages/cdk-github-webhook/package.json
index 72f666bf8..9430c5f0d 100644
--- a/packages/cdk-github-webhook/package.json
+++ b/packages/cdk-github-webhook/package.json
@@ -60,14 +60,17 @@
   "peerDependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0",
     "constructs": "^3.2.0"
   },
   "dependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
-    "@aws-cdk/core": "^1.93.0"
+    "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0"
   },
   "devDependencies": {
     "@aws-cdk/assert": "^1.93.0",
+    "@cloudcomponents/lambda-utils": "^0.1.1",
     "@octokit/rest": "^18.3.5",
     "@types/parse-github-url": "^1.0.0",
     "axios": "^0.21.1",
diff --git a/packages/cdk-github-webhook/src/github-webhook.ts b/packages/cdk-github-webhook/src/github-webhook.ts
index 20119f478..f59c9ab31 100644
--- a/packages/cdk-github-webhook/src/github-webhook.ts
+++ b/packages/cdk-github-webhook/src/github-webhook.ts
@@ -1,12 +1,13 @@
 import * as path from 'path';
 import { SingletonFunction, Runtime, Code } from '@aws-cdk/aws-lambda';
 import { Construct, Duration, CustomResource } from '@aws-cdk/core';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 
 export interface GithubWebhookProps {
   /**
    * The OAuth access token
    */
-  readonly githubApiToken: string;
+  readonly githubApiToken: string | SecretKey;
 
   /**
    * The Github repo url
@@ -31,6 +32,8 @@ export class GithubWebhook extends Construct {
   constructor(scope: Construct, id: string, props: GithubWebhookProps) {
     super(scope, id);
 
+    const githubApiToken = typeof props.githubApiToken === 'string' ? SecretKey.fromPlainText(props.githubApiToken) : props.githubApiToken;
+
     const handler = new SingletonFunction(this, 'CustomResourceHandler', {
       uuid: '83CBF3EB-7B62-44F2-8C67-8441E4C1232E',
       runtime: Runtime.NODEJS_12_X,
@@ -40,17 +43,20 @@ export class GithubWebhook extends Construct {
       timeout: Duration.minutes(15),
     });
 
-    const { githubApiToken, githubRepoUrl, payloadUrl, events, logLevel } = props;
+    if (githubApiToken.grantRead) {
+      githubApiToken.grantRead(handler);
+    }
 
     new CustomResource(this, 'CustomResource', {
       serviceToken: handler.functionArn,
       resourceType: 'Custom::GithubWebhook',
+      pascalCaseProperties: true,
       properties: {
-        GithubApiToken: githubApiToken,
-        GithubRepoUrl: githubRepoUrl,
-        PayloadUrl: payloadUrl,
-        Events: events,
-        LogLevel: logLevel,
+        githubApiTokenString: githubApiToken.serialize(),
+        githubRepoUrl: props.githubRepoUrl,
+        payloadUrl: props.payloadUrl,
+        events: props.events,
+        logLevel: props.logLevel,
       },
     });
   }
diff --git a/packages/cdk-github-webhook/src/lambdas/github-webhook/index.ts b/packages/cdk-github-webhook/src/lambdas/github-webhook/index.ts
index 609d79f97..257238a3d 100644
--- a/packages/cdk-github-webhook/src/lambdas/github-webhook/index.ts
+++ b/packages/cdk-github-webhook/src/lambdas/github-webhook/index.ts
@@ -1,3 +1,4 @@
+import { SecretKey } from '@cloudcomponents/lambda-utils';
 import type { CloudFormationCustomResourceEventCommon } from 'aws-lambda';
 import {
   customResourceHelper,
@@ -11,19 +12,23 @@ import {
 
 import { createWebhook, updateWebhook, deleteWebhook } from './webhook-api';
 
+const secretKey = new SecretKey();
+
 export interface WebhookProps {
-  githubApiToken: string;
+  githubApiTokenString: string;
   githubRepoUrl: string;
   payloadUrl: string;
   events: string[];
 }
 
 const handleCreate: OnCreateHandler = async (event): Promise<ResourceHandlerReturn> => {
-  const { githubApiToken, githubRepoUrl, payloadUrl, events } = camelizeKeys<
+  const { githubApiTokenString, githubRepoUrl, payloadUrl, events } = camelizeKeys<
     WebhookProps,
     CloudFormationCustomResourceEventCommon['ResourceProperties']
   >(event.ResourceProperties);
 
+  const githubApiToken = await secretKey.getValue(githubApiTokenString);
+
   const { data } = await createWebhook(githubApiToken, githubRepoUrl, payloadUrl, events);
 
   const physicalResourceId = data.id.toString();
@@ -37,11 +42,13 @@ const handleCreate: OnCreateHandler = async (event): Promise<ResourceHandlerRetu
 };
 
 const handleUpdate: OnUpdateHandler = async (event): Promise<ResourceHandlerReturn> => {
-  const { githubApiToken, githubRepoUrl, payloadUrl, events } = camelizeKeys<
+  const { githubApiTokenString, githubRepoUrl, payloadUrl, events } = camelizeKeys<
     WebhookProps,
     CloudFormationCustomResourceEventCommon['ResourceProperties']
   >(event.ResourceProperties);
 
+  const githubApiToken = await secretKey.getValue(githubApiTokenString);
+
   const hookId = event.PhysicalResourceId;
 
   const { data } = await updateWebhook(githubApiToken, githubRepoUrl, payloadUrl, events, parseInt(hookId, 10));
@@ -57,10 +64,12 @@ const handleUpdate: OnUpdateHandler = async (event): Promise<ResourceHandlerRetu
 };
 
 const handleDelete: OnDeleteHandler = async (event): Promise<void> => {
-  const { githubApiToken, githubRepoUrl } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { githubApiTokenString, githubRepoUrl } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
+  const githubApiToken = await secretKey.getValue(githubApiTokenString);
+
   const hookId = event.PhysicalResourceId;
 
   await deleteWebhook(githubApiToken, githubRepoUrl, parseInt(hookId, 10));
diff --git a/packages/cdk-pull-request-check/API.md b/packages/cdk-pull-request-check/API.md
index 4ee426b18..c740b6bf4 100644
--- a/packages/cdk-pull-request-check/API.md
+++ b/packages/cdk-pull-request-check/API.md
@@ -36,13 +36,17 @@ new PullRequestCheck(scope: Construct, id: string, props: PullRequestCheckProps)
 * **props** (<code>[PullRequestCheckProps](#cloudcomponents-cdk-pull-request-check-pullrequestcheckprops)</code>)  *No description*
   * **buildSpec** (<code>[BuildSpec](#aws-cdk-aws-codebuild-buildspec)</code>)  Filename or contents of buildspec in JSON format. 
   * **repository** (<code>[IRepository](#aws-cdk-aws-codecommit-irepository)</code>)  The CodeCommit repository. 
+  * **allowAllOutbound** (<code>boolean</code>)  Whether to allow the CodeBuild to send all network traffic. __*Default*__: true
   * **buildImage** (<code>[IBuildImage](#aws-cdk-aws-codebuild-ibuildimage)</code>)  Build environment to use for the build. __*Default*__: BuildEnvironment.LinuxBuildImage.STANDARD_2_0
   * **computeType** (<code>[ComputeType](#aws-cdk-aws-codebuild-computetype)</code>)  The type of compute to use for this build. __*Default*__: taken from {@link #buildImage#defaultComputeType}
   * **postComment** (<code>boolean</code>)  Specifies whether comments should be written in the request. __*Default*__: true
   * **privileged** (<code>boolean</code>)  Indicates how the project builds Docker images. __*Default*__: false
   * **projectName** (<code>string</code>)  The human-visible name of this PullRequest-Project. __*Optional*__
   * **role** (<code>[IRole](#aws-cdk-aws-iam-irole)</code>)  The IAM service Role of the Project. __*Optional*__
+  * **securityGroups** (<code>Array<[ISecurityGroup](#aws-cdk-aws-ec2-isecuritygroup)></code>)  What security group to associate with the codebuild project's network interfaces. __*Default*__: Security group will be automatically created
+  * **subnetSelection** (<code>[SubnetSelection](#aws-cdk-aws-ec2-subnetselection)</code>)  Where to place the network interfaces within the VPC. __*Default*__: All private subnets
   * **updateApprovalState** (<code>boolean</code>)  Indicates whether the approval state [APPROVE, REVOKE] should be updated. __*Default*__: true
+  * **vpc** (<code>[IVpc](#aws-cdk-aws-ec2-ivpc)</code>)  VPC network to place codebuild network interfaces. __*Default*__: No VPC is specified
 
 
 ### Methods
@@ -128,13 +132,17 @@ Name | Type | Description
 -----|------|-------------
 **buildSpec** | <code>[BuildSpec](#aws-cdk-aws-codebuild-buildspec)</code> | Filename or contents of buildspec in JSON format.
 **repository** | <code>[IRepository](#aws-cdk-aws-codecommit-irepository)</code> | The CodeCommit repository.
+**allowAllOutbound**? | <code>boolean</code> | Whether to allow the CodeBuild to send all network traffic.<br/>__*Default*__: true
 **buildImage**? | <code>[IBuildImage](#aws-cdk-aws-codebuild-ibuildimage)</code> | Build environment to use for the build.<br/>__*Default*__: BuildEnvironment.LinuxBuildImage.STANDARD_2_0
 **computeType**? | <code>[ComputeType](#aws-cdk-aws-codebuild-computetype)</code> | The type of compute to use for this build.<br/>__*Default*__: taken from {@link #buildImage#defaultComputeType}
 **postComment**? | <code>boolean</code> | Specifies whether comments should be written in the request.<br/>__*Default*__: true
 **privileged**? | <code>boolean</code> | Indicates how the project builds Docker images.<br/>__*Default*__: false
 **projectName**? | <code>string</code> | The human-visible name of this PullRequest-Project.<br/>__*Optional*__
 **role**? | <code>[IRole](#aws-cdk-aws-iam-irole)</code> | The IAM service Role of the Project.<br/>__*Optional*__
+**securityGroups**? | <code>Array<[ISecurityGroup](#aws-cdk-aws-ec2-isecuritygroup)></code> | What security group to associate with the codebuild project's network interfaces.<br/>__*Default*__: Security group will be automatically created
+**subnetSelection**? | <code>[SubnetSelection](#aws-cdk-aws-ec2-subnetselection)</code> | Where to place the network interfaces within the VPC.<br/>__*Default*__: All private subnets
 **updateApprovalState**? | <code>boolean</code> | Indicates whether the approval state [APPROVE, REVOKE] should be updated.<br/>__*Default*__: true
+**vpc**? | <code>[IVpc](#aws-cdk-aws-ec2-ivpc)</code> | VPC network to place codebuild network interfaces.<br/>__*Default*__: No VPC is specified
 
 
 
diff --git a/packages/cdk-pull-request-check/src/pull-request-check.ts b/packages/cdk-pull-request-check/src/pull-request-check.ts
index 85e7f7c48..3554703bc 100644
--- a/packages/cdk-pull-request-check/src/pull-request-check.ts
+++ b/packages/cdk-pull-request-check/src/pull-request-check.ts
@@ -141,16 +141,16 @@ export class PullRequestCheck extends Construct {
       },
       buildSpec,
       role,
-      vpc: vpc,
-      subnetSelection: subnetSelection,
-      securityGroups: securityGroups,
-      allowAllOutbound: allowAllOutbound,
+      vpc,
+      subnetSelection,
+      securityGroups,
+      allowAllOutbound,
     });
 
     if (updateApprovalState || postComment) {
       const codeBuildResultFunction = new Function(this, 'CodeBuildResultFunction', {
         runtime: Runtime.NODEJS_12_X,
-        code: Code.asset(path.join(__dirname, 'lambdas', 'code-build-result')),
+        code: Code.fromAsset(path.join(__dirname, 'lambdas', 'code-build-result')),
         handler: 'index.handler',
         environment: {
           UPDATE_APPROVAL_STATE: updateApprovalState ? 'TRUE' : 'FALSE',
diff --git a/packages/cdk-secret-key/API.md b/packages/cdk-secret-key/API.md
new file mode 100644
index 000000000..188f9003e
--- /dev/null
+++ b/packages/cdk-secret-key/API.md
@@ -0,0 +1,205 @@
+# API Reference
+
+**Classes**
+
+Name|Description
+----|-----------
+[SecretKey](#cloudcomponents-cdk-secret-key-secretkey)|*No description*
+[SecretKeyStore](#cloudcomponents-cdk-secret-key-secretkeystore)|*No description*
+
+
+**Enums**
+
+Name|Description
+----|-----------
+[KeyType](#cloudcomponents-cdk-secret-key-keytype)|*No description*
+
+
+
+## class SecretKey  <a id="cloudcomponents-cdk-secret-key-secretkey"></a>
+
+
+
+
+### Initializer
+
+
+
+
+```ts
+new SecretKey(secretKeyType: KeyType)
+```
+
+* **secretKeyType** (<code>[KeyType](#cloudcomponents-cdk-secret-key-keytype)</code>)  *No description*
+
+
+
+### Properties
+
+
+Name | Type | Description 
+-----|------|-------------
+**secretKeyType** | <code>[KeyType](#cloudcomponents-cdk-secret-key-keytype)</code> | <span></span>
+
+### Methods
+
+
+#### grantRead(grantee) <a id="cloudcomponents-cdk-secret-key-secretkey-grantread"></a>
+
+
+
+```ts
+grantRead(grantee: IGrantable): Grant
+```
+
+* **grantee** (<code>[IGrantable](#aws-cdk-aws-iam-igrantable)</code>)  *No description*
+
+__Returns__:
+* <code>[Grant](#aws-cdk-aws-iam-grant)</code>
+
+#### serialize() <a id="cloudcomponents-cdk-secret-key-secretkey-serialize"></a>
+
+
+
+```ts
+serialize(): string
+```
+
+
+__Returns__:
+* <code>string</code>
+
+#### *static* fromPlainText(value) <a id="cloudcomponents-cdk-secret-key-secretkey-fromplaintext"></a>
+
+
+
+```ts
+static fromPlainText(value: string): SecretKey
+```
+
+* **value** (<code>string</code>)  *No description*
+
+__Returns__:
+* <code>[SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>
+
+#### *static* fromSSMParameter(secretKeyParameter) <a id="cloudcomponents-cdk-secret-key-secretkey-fromssmparameter"></a>
+
+
+
+```ts
+static fromSSMParameter(secretKeyParameter: IParameter): SecretKey
+```
+
+* **secretKeyParameter** (<code>[IParameter](#aws-cdk-aws-ssm-iparameter)</code>)  *No description*
+
+__Returns__:
+* <code>[SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>
+
+#### *static* fromSecretsManager(secretKeySecret, fieldName?) <a id="cloudcomponents-cdk-secret-key-secretkey-fromsecretsmanager"></a>
+
+
+
+```ts
+static fromSecretsManager(secretKeySecret: ISecret, fieldName?: string): SecretKey
+```
+
+* **secretKeySecret** (<code>[ISecret](#aws-cdk-aws-secretsmanager-isecret)</code>)  *No description*
+* **fieldName** (<code>string</code>)  *No description*
+
+__Returns__:
+* <code>[SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>
+
+
+
+## class SecretKeyStore  <a id="cloudcomponents-cdk-secret-key-secretkeystore"></a>
+
+
+
+
+### Initializer
+
+
+
+
+```ts
+new SecretKeyStore(secretKeyType: KeyType)
+```
+
+* **secretKeyType** (<code>[KeyType](#cloudcomponents-cdk-secret-key-keytype)</code>)  *No description*
+
+
+
+### Properties
+
+
+Name | Type | Description 
+-----|------|-------------
+**secretKeyType** | <code>[KeyType](#cloudcomponents-cdk-secret-key-keytype)</code> | <span></span>
+
+### Methods
+
+
+#### grantWrite(grantee) <a id="cloudcomponents-cdk-secret-key-secretkeystore-grantwrite"></a>
+
+
+
+```ts
+grantWrite(grantee: IGrantable): Grant
+```
+
+* **grantee** (<code>[IGrantable](#aws-cdk-aws-iam-igrantable)</code>)  *No description*
+
+__Returns__:
+* <code>[Grant](#aws-cdk-aws-iam-grant)</code>
+
+#### serialize() <a id="cloudcomponents-cdk-secret-key-secretkeystore-serialize"></a>
+
+
+
+```ts
+serialize(): string
+```
+
+
+__Returns__:
+* <code>string</code>
+
+#### *static* fromSSMParameter(secretKeyParameter) <a id="cloudcomponents-cdk-secret-key-secretkeystore-fromssmparameter"></a>
+
+
+
+```ts
+static fromSSMParameter(secretKeyParameter: IParameter): SecretKeyStore
+```
+
+* **secretKeyParameter** (<code>[IParameter](#aws-cdk-aws-ssm-iparameter)</code>)  *No description*
+
+__Returns__:
+* <code>[SecretKeyStore](#cloudcomponents-cdk-secret-key-secretkeystore)</code>
+
+#### *static* fromSecretsManager(secretKeySecret) <a id="cloudcomponents-cdk-secret-key-secretkeystore-fromsecretsmanager"></a>
+
+
+
+```ts
+static fromSecretsManager(secretKeySecret: ISecret): SecretKeyStore
+```
+
+* **secretKeySecret** (<code>[ISecret](#aws-cdk-aws-secretsmanager-isecret)</code>)  *No description*
+
+__Returns__:
+* <code>[SecretKeyStore](#cloudcomponents-cdk-secret-key-secretkeystore)</code>
+
+
+
+## enum KeyType  <a id="cloudcomponents-cdk-secret-key-keytype"></a>
+
+
+
+Name | Description
+-----|-----
+**SECRETS_MANAGER** |
+**SSM_PARAMETER** |
+**PLAIN_TEXT** |
+
+
diff --git a/packages/cdk-secret-key/LICENSE b/packages/cdk-secret-key/LICENSE
new file mode 100644
index 000000000..50db47fc0
--- /dev/null
+++ b/packages/cdk-secret-key/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 cloudcomponents
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/cdk-secret-key/README.md b/packages/cdk-secret-key/README.md
new file mode 100644
index 000000000..7df8af121
--- /dev/null
+++ b/packages/cdk-secret-key/README.md
@@ -0,0 +1,47 @@
+[![cloudcomponents Logo](https://raw.githubusercontent.com/cloudcomponents/cdk-constructs/master/logo.png)](https://github.com/cloudcomponents/cdk-constructs)
+
+# @cloudcomponents/cdk-secret-key 
+
+[![Build Status](https://github.com/cloudcomponents/cdk-constructs/workflows/Build/badge.svg)](https://github.com/cloudcomponents/cdk-constructs/actions?query=workflow=Build)
+[![cdkdx](https://img.shields.io/badge/buildtool-cdkdx-blue.svg)](https://github.com/hupe1980/cdkdx)
+[![typescript](https://img.shields.io/badge/jsii-typescript-blueviolet.svg)](https://www.npmjs.com/package/@cloudcomponents/cdk-secret-key)
+[![python](https://img.shields.io/badge/jsii-python-blueviolet.svg)](https://pypi.org/project/cloudcomponents.cdk-secret-key/)
+
+> Provide secret keys to lambdas
+
+## Install
+TypeScript/JavaScript:
+
+```bash
+npm i @cloudcomponents/cdk-secret-key
+```
+
+Python:
+
+```bash
+pip install cloudcomponents.cdk-secret-key
+```
+
+## How to use
+
+```typescript
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
+
+const secretKey = SecretKey.fromPlainText(process.env.SECRET_KEY as string);
+const secretKeyString = secretKey.serialize(),
+
+```
+
+See [cloudcomponents/lambda-utils-nodejs](https://github.com/cloudcomponents/lambda-utils-nodejs) for the counterpart in lambda functions
+
+## API Reference
+
+See [API.md](https://github.com/cloudcomponents/cdk-constructs/tree/master/packages/cdk-secret-key/API.md).
+
+## Example
+
+See more complete [examples](https://github.com/cloudcomponents/cdk-constructs/tree/master/examples).
+
+## License
+
+[MIT](https://github.com/cloudcomponents/cdk-constructs/tree/master/packages/cdk-secret-key/LICENSE)
diff --git a/packages/cdk-secret-key/package.json b/packages/cdk-secret-key/package.json
new file mode 100644
index 000000000..08d872133
--- /dev/null
+++ b/packages/cdk-secret-key/package.json
@@ -0,0 +1,75 @@
+{
+  "name": "@cloudcomponents/cdk-secret-key",
+  "version": "1.0.0",
+  "description": "Provide secret keys to lambdas",
+  "license": "MIT",
+  "author": {
+    "name": "hupe1980",
+    "url": "https://github.com/hupe1980"
+  },
+  "awscdkio": {
+    "twitter": "hupe1980"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/cloudcomponents/cdk-constructs.git",
+    "directory": "packages/cdk-secret-key"
+  },
+  "homepage": "https://github.com/cloudcomponents/cdk-constructs",
+  "keywords": [
+    "aws",
+    "cdk",
+    "secrets",
+    "@cloudcomponents"
+  ],
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "files": [
+    "lib",
+    ".jsii"
+  ],
+  "scripts": {
+    "build": "cdkdx build",
+    "watch": "cdkdx build -w",
+    "test": "cdkdx test",
+    "lint": "cdkdx lint",
+    "upgrade:cdk": "cdkdx upgrade-cdk",
+    "package": "cdkdx package",
+    "docgen": "cdkdx docgen",
+    "release:npm": "cdkdx release npm",
+    "release:pypi": "cdkdx release pypi"
+  },
+  "jsii": {
+    "outdir": "dist",
+    "tsc": {
+      "outDir": "lib",
+      "rootDir": "src"
+    },
+    "excludeTypescript": [
+      "src/lambdas",
+      "src/**/__tests__"
+    ],
+    "targets": {
+      "python": {
+        "distName": "cloudcomponents.cdk-secret-key",
+        "module": "cloudcomponents.cdk_secret_key"
+      }
+    }
+  },
+  "peerDependencies": {
+    "@aws-cdk/aws-iam": "^1.93.0",
+    "@aws-cdk/aws-ssm": "^1.93.0",
+    "@aws-cdk/aws-secretsmanager": "^1.93.0",
+    "@aws-cdk/core": "^1.93.0",
+    "constructs": "^3.2.0"
+  },
+  "dependencies": {
+    "@aws-cdk/aws-iam": "^1.93.0",
+    "@aws-cdk/aws-ssm": "^1.93.0",
+    "@aws-cdk/aws-secretsmanager": "^1.93.0",
+    "@aws-cdk/core": "^1.93.0"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}
diff --git a/packages/cdk-secret-key/src/index.ts b/packages/cdk-secret-key/src/index.ts
new file mode 100644
index 000000000..29ef29457
--- /dev/null
+++ b/packages/cdk-secret-key/src/index.ts
@@ -0,0 +1,3 @@
+export * from './key-type';
+export * from './secret-key-store';
+export * from './secret-key';
diff --git a/packages/cdk-secret-key/src/key-type.ts b/packages/cdk-secret-key/src/key-type.ts
new file mode 100644
index 000000000..2f6b196a5
--- /dev/null
+++ b/packages/cdk-secret-key/src/key-type.ts
@@ -0,0 +1,5 @@
+export enum KeyType {
+  SECRETS_MANAGER = 'SECRETS_MANAGER',
+  SSM_PARAMETER = 'SSM_PARAMETER',
+  PLAIN_TEXT = 'PLAIN_TEXT',
+}
diff --git a/packages/cdk-secret-key/src/secret-key-store.ts b/packages/cdk-secret-key/src/secret-key-store.ts
new file mode 100644
index 000000000..df55dc24d
--- /dev/null
+++ b/packages/cdk-secret-key/src/secret-key-store.ts
@@ -0,0 +1,55 @@
+import { Grant, IGrantable } from '@aws-cdk/aws-iam';
+import { ISecret } from '@aws-cdk/aws-secretsmanager';
+import { IParameter } from '@aws-cdk/aws-ssm';
+
+import { KeyType } from './key-type';
+
+export abstract class SecretKeyStore {
+  public static fromSSMParameter(secretKeyParameter: IParameter): SecretKeyStore {
+    return new SSMParameterSecretKeyStore(secretKeyParameter);
+  }
+
+  public static fromSecretsManager(secretKeySecret: ISecret): SecretKeyStore {
+    return new SecretsManagerSecretKeyStore(secretKeySecret);
+  }
+
+  constructor(public readonly secretKeyType: KeyType) {}
+
+  public abstract grantWrite?(grantee: IGrantable): Grant;
+
+  public abstract serialize(): string;
+}
+
+class SecretsManagerSecretKeyStore extends SecretKeyStore {
+  constructor(public readonly secretKeySecret: ISecret) {
+    super(KeyType.SECRETS_MANAGER);
+  }
+
+  public grantWrite(grantee: IGrantable): Grant {
+    return this.secretKeySecret.grantWrite(grantee);
+  }
+
+  public serialize(): string {
+    return JSON.stringify({
+      secretKeyType: this.secretKeyType,
+      secretArn: this.secretKeySecret.secretArn,
+    });
+  }
+}
+
+class SSMParameterSecretKeyStore extends SecretKeyStore {
+  constructor(public readonly secretKeyParameter: IParameter) {
+    super(KeyType.SSM_PARAMETER);
+  }
+
+  public grantWrite(grantee: IGrantable): Grant {
+    return this.secretKeyParameter.grantWrite(grantee);
+  }
+
+  public serialize(): string {
+    return JSON.stringify({
+      secretKeyType: this.secretKeyType,
+      parameterName: this.secretKeyParameter.parameterName,
+    });
+  }
+}
diff --git a/packages/cdk-secret-key/src/secret-key.ts b/packages/cdk-secret-key/src/secret-key.ts
new file mode 100644
index 000000000..e0c1a7104
--- /dev/null
+++ b/packages/cdk-secret-key/src/secret-key.ts
@@ -0,0 +1,75 @@
+import { Grant, IGrantable } from '@aws-cdk/aws-iam';
+import { ISecret } from '@aws-cdk/aws-secretsmanager';
+import { IParameter } from '@aws-cdk/aws-ssm';
+
+import { KeyType } from './key-type';
+
+export abstract class SecretKey {
+  public static fromPlainText(value: string): SecretKey {
+    return new PlainTextSecretKey(value);
+  }
+
+  public static fromSSMParameter(secretKeyParameter: IParameter): SecretKey {
+    return new SSMParameterSecretKey(secretKeyParameter);
+  }
+
+  public static fromSecretsManager(secretKeySecret: ISecret, fieldName?: string): SecretKey {
+    return new SecretsManagerSecretKey(secretKeySecret, fieldName);
+  }
+
+  constructor(public readonly secretKeyType: KeyType) {}
+
+  public abstract grantRead?(grantee: IGrantable): Grant;
+
+  public abstract serialize(): string;
+}
+
+class PlainTextSecretKey extends SecretKey {
+  public grantRead: undefined;
+
+  constructor(public readonly value: string) {
+    super(KeyType.PLAIN_TEXT);
+  }
+
+  public serialize(): string {
+    return JSON.stringify({
+      secretKeyType: this.secretKeyType,
+      value: this.value,
+    });
+  }
+}
+
+class SecretsManagerSecretKey extends SecretKey {
+  constructor(public readonly secretKeySecret: ISecret, public readonly fieldName?: string) {
+    super(KeyType.SECRETS_MANAGER);
+  }
+
+  public grantRead(grantee: IGrantable): Grant {
+    return this.secretKeySecret.grantRead(grantee);
+  }
+
+  public serialize(): string {
+    return JSON.stringify({
+      secretKeyType: this.secretKeyType,
+      secretId: this.secretKeySecret.secretArn,
+      fieldName: this.fieldName,
+    });
+  }
+}
+
+class SSMParameterSecretKey extends SecretKey {
+  constructor(public readonly secretKeyParameter: IParameter) {
+    super(KeyType.SSM_PARAMETER);
+  }
+
+  public grantRead(grantee: IGrantable): Grant {
+    return this.secretKeyParameter.grantRead(grantee);
+  }
+
+  public serialize(): string {
+    return JSON.stringify({
+      secretKeyType: this.secretKeyType,
+      parameterName: this.secretKeyParameter.parameterName,
+    });
+  }
+}
diff --git a/packages/cdk-stripe-webhook/API.md b/packages/cdk-stripe-webhook/API.md
index 0cb1cc437..0c28fe7d5 100644
--- a/packages/cdk-stripe-webhook/API.md
+++ b/packages/cdk-stripe-webhook/API.md
@@ -35,7 +35,7 @@ new StripeWebhook(scope: Construct, id: string, props: StripeWebhookProps)
 * **id** (<code>string</code>)  *No description*
 * **props** (<code>[StripeWebhookProps](#cloudcomponents-cdk-stripe-webhook-stripewebhookprops)</code>)  *No description*
   * **events** (<code>Array<string></code>)  *No description* 
-  * **secretKey** (<code>string</code>)  *No description* 
+  * **secretKey** (<code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code>)  *No description* 
   * **url** (<code>string</code>)  *No description* 
   * **description** (<code>string</code>)  *No description* __*Optional*__
   * **logLevel** (<code>string</code>)  *No description* __*Optional*__
@@ -61,7 +61,7 @@ Name | Type | Description
 Name | Type | Description 
 -----|------|-------------
 **events** | <code>Array<string></code> | <span></span>
-**secretKey** | <code>string</code> | <span></span>
+**secretKey** | <code>string &#124; [SecretKey](#cloudcomponents-cdk-secret-key-secretkey)</code> | <span></span>
 **url** | <code>string</code> | <span></span>
 **description**? | <code>string</code> | __*Optional*__
 **logLevel**? | <code>string</code> | __*Optional*__
diff --git a/packages/cdk-stripe-webhook/README.md b/packages/cdk-stripe-webhook/README.md
index 68ef0201c..842e06251 100644
--- a/packages/cdk-stripe-webhook/README.md
+++ b/packages/cdk-stripe-webhook/README.md
@@ -25,10 +25,10 @@ pip install cloudcomponents.cdk-stripe-webhook
 ## How to use
 
 ```typescript
-import { Construct, Stack, StackProps } from '@aws-cdk/core';
 import { RestApi } from '@aws-cdk/aws-apigateway';
+import { Construct, Stack, StackProps } from '@aws-cdk/core';
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 import { StripeWebhook } from '@cloudcomponents/cdk-stripe-webhook';
-
 export class StripeWebhookStack extends Stack {
   constructor(scope: Construct, id: string, props?: StackProps) {
     super(scope, id, props);
@@ -36,7 +36,7 @@ export class StripeWebhookStack extends Stack {
     const api = new RestApi(this, 'Endpoint');
     api.root.addMethod('POST');
 
-    const secretKey = process.env.SECRET_KEY as string;
+    const secretKey = SecretKey.fromPlainText(process.env.SECRET_KEY as string);
 
     const events = ['charge.failed', 'charge.succeeded'];
 
@@ -48,6 +48,7 @@ export class StripeWebhookStack extends Stack {
     });
   }
 }
+
 ```
 
 ## API Reference
diff --git a/packages/cdk-stripe-webhook/lambda-file-sizes.json b/packages/cdk-stripe-webhook/lambda-file-sizes.json
index 8e28251a1..2047754d6 100644
--- a/packages/cdk-stripe-webhook/lambda-file-sizes.json
+++ b/packages/cdk-stripe-webhook/lambda-file-sizes.json
@@ -1,1 +1,1 @@
-[{"timestamp":1615535054925,"files":[{"filename":"stripe-webhook/index.js","previous":178288,"size":178311,"diff":23}]},{"timestamp":1612894907890,"files":[{"filename":"stripe-webhook/index.js","previous":178247,"size":178288,"diff":41}]},{"timestamp":1611251026819,"files":[{"filename":"stripe-webhook/index.js","previous":178239,"size":178247,"diff":8}]},{"timestamp":1610572412633,"files":[{"filename":"stripe-webhook/index.js","previous":178125,"size":178239,"diff":114}]},{"timestamp":1609970972468,"files":[{"filename":"stripe-webhook/index.js","previous":175300,"size":178125,"diff":2825}]},{"timestamp":1607360080295,"files":[{"filename":"stripe-webhook/index.js","previous":175302,"size":175300,"diff":-2}]},{"timestamp":1606332128770,"files":[{"filename":"stripe-webhook/index.js","previous":175297,"size":175302,"diff":5}]},{"timestamp":1606331402732,"files":[{"filename":"stripe-webhook/index.js","previous":173633,"size":175297,"diff":1664}]},{"timestamp":1600966323131,"files":[{"filename":"stripe-webhook/index.js","previous":173622,"size":173633,"diff":11}]},{"timestamp":1596542600035,"files":[{"filename":"stripe-webhook/index.js","previous":177655,"size":173622,"diff":-4033}]},{"timestamp":1596540606102,"files":[{"filename":"stripe-webhook/index.js","previous":177121,"size":177655,"diff":534}]},{"timestamp":1596458220846,"files":[{"filename":"stripe-webhook/index.js","previous":177110,"size":177121,"diff":11}]},{"timestamp":1596457299467,"files":[{"filename":"stripe-webhook/index.js","previous":463445,"size":177110,"diff":-286335}]},{"timestamp":1596407687567,"files":[{"filename":"stripe-webhook/index.js","previous":164597,"size":463445,"diff":298848}]}]
+[{"timestamp":1615805520640,"files":[{"filename":"stripe-webhook/index.js","previous":178329,"size":1004493,"diff":826164}]},{"timestamp":1615673334493,"files":[{"filename":"stripe-webhook/index.js","previous":178311,"size":178329,"diff":18}]},{"timestamp":1615535054925,"files":[{"filename":"stripe-webhook/index.js","previous":178288,"size":178311,"diff":23}]},{"timestamp":1612894907890,"files":[{"filename":"stripe-webhook/index.js","previous":178247,"size":178288,"diff":41}]},{"timestamp":1611251026819,"files":[{"filename":"stripe-webhook/index.js","previous":178239,"size":178247,"diff":8}]},{"timestamp":1610572412633,"files":[{"filename":"stripe-webhook/index.js","previous":178125,"size":178239,"diff":114}]},{"timestamp":1609970972468,"files":[{"filename":"stripe-webhook/index.js","previous":175300,"size":178125,"diff":2825}]},{"timestamp":1607360080295,"files":[{"filename":"stripe-webhook/index.js","previous":175302,"size":175300,"diff":-2}]},{"timestamp":1606332128770,"files":[{"filename":"stripe-webhook/index.js","previous":175297,"size":175302,"diff":5}]},{"timestamp":1606331402732,"files":[{"filename":"stripe-webhook/index.js","previous":173633,"size":175297,"diff":1664}]},{"timestamp":1600966323131,"files":[{"filename":"stripe-webhook/index.js","previous":173622,"size":173633,"diff":11}]},{"timestamp":1596542600035,"files":[{"filename":"stripe-webhook/index.js","previous":177655,"size":173622,"diff":-4033}]},{"timestamp":1596540606102,"files":[{"filename":"stripe-webhook/index.js","previous":177121,"size":177655,"diff":534}]},{"timestamp":1596458220846,"files":[{"filename":"stripe-webhook/index.js","previous":177110,"size":177121,"diff":11}]},{"timestamp":1596457299467,"files":[{"filename":"stripe-webhook/index.js","previous":463445,"size":177110,"diff":-286335}]},{"timestamp":1596407687567,"files":[{"filename":"stripe-webhook/index.js","previous":164597,"size":463445,"diff":298848}]}]
diff --git a/packages/cdk-stripe-webhook/package.json b/packages/cdk-stripe-webhook/package.json
index 84dcd1d4d..096213e6e 100644
--- a/packages/cdk-stripe-webhook/package.json
+++ b/packages/cdk-stripe-webhook/package.json
@@ -60,14 +60,17 @@
   "peerDependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
     "@aws-cdk/core": "^1.93.0",
-    "constructs": "^3.2.0"
+    "constructs": "^3.2.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0"
   },
   "dependencies": {
     "@aws-cdk/aws-lambda": "^1.93.0",
-    "@aws-cdk/core": "^1.93.0"
+    "@aws-cdk/core": "^1.93.0",
+    "@cloudcomponents/cdk-secret-key": "^1.0.0"
   },
   "devDependencies": {
     "@aws-cdk/assert": "^1.93.0",
+    "@cloudcomponents/lambda-utils": "^0.1.1",
     "@types/stripe": "^8.0.417",
     "custom-resource-helper": "^1.0.15",
     "jest-cdk-snapshot": "^1.4.1",
diff --git a/packages/cdk-stripe-webhook/src/lambdas/stripe-webhook/index.ts b/packages/cdk-stripe-webhook/src/lambdas/stripe-webhook/index.ts
index 2de192c35..d44cea35d 100644
--- a/packages/cdk-stripe-webhook/src/lambdas/stripe-webhook/index.ts
+++ b/packages/cdk-stripe-webhook/src/lambdas/stripe-webhook/index.ts
@@ -1,3 +1,4 @@
+import { SecretKey } from '@cloudcomponents/lambda-utils';
 import type { CloudFormationCustomResourceEventCommon } from 'aws-lambda';
 import {
   camelizeKeys,
@@ -10,19 +11,22 @@ import {
 } from 'custom-resource-helper';
 import Stripe from 'stripe';
 
+const secretKey = new SecretKey();
 export interface WebhookProps {
-  secretKey: string;
+  secretKeyString: string;
   url: string;
   description?: string;
   events: Stripe.WebhookEndpointCreateParams.EnabledEvent[];
 }
 
 const handleCreate: OnCreateHandler = async (event, _): Promise<ResourceHandlerReturn> => {
-  const { secretKey, url, events, description } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { secretKeyString, url, events, description } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
-  const stripe = new Stripe(secretKey, { apiVersion: '2020-08-27' });
+  const value = await secretKey.getValue(secretKeyString);
+
+  const stripe = new Stripe(value, { apiVersion: '2020-08-27' });
 
   const data = await stripe.webhookEndpoints.create({
     url,
@@ -41,13 +45,15 @@ const handleCreate: OnCreateHandler = async (event, _): Promise<ResourceHandlerR
 };
 
 const handleUpdate: OnUpdateHandler = async (event, _): Promise<ResourceHandlerReturn> => {
-  const { secretKey, url, events, description } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
+  const { secretKeyString, url, events, description } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(
     event.ResourceProperties,
   );
 
+  const value = await secretKey.getValue(secretKeyString);
+
   const webhookId = event.PhysicalResourceId;
 
-  const stripe = new Stripe(secretKey, { apiVersion: '2020-08-27' });
+  const stripe = new Stripe(value, { apiVersion: '2020-08-27' });
 
   const data = await stripe.webhookEndpoints.update(webhookId, {
     url,
@@ -66,11 +72,13 @@ const handleUpdate: OnUpdateHandler = async (event, _): Promise<ResourceHandlerR
 };
 
 const handleDelete: OnDeleteHandler = async (event, _): Promise<void> => {
-  const { secretKey } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(event.ResourceProperties);
+  const { secretKeyString } = camelizeKeys<WebhookProps, CloudFormationCustomResourceEventCommon['ResourceProperties']>(event.ResourceProperties);
+
+  const value = await secretKey.getValue(secretKeyString);
 
   const webhookId = event.PhysicalResourceId;
 
-  const stripe = new Stripe(secretKey, { apiVersion: '2020-08-27' });
+  const stripe = new Stripe(value, { apiVersion: '2020-08-27' });
 
   await stripe.webhookEndpoints.del(webhookId);
 };
diff --git a/packages/cdk-stripe-webhook/src/stripe-webhook.ts b/packages/cdk-stripe-webhook/src/stripe-webhook.ts
index 1a924463b..b0282020f 100644
--- a/packages/cdk-stripe-webhook/src/stripe-webhook.ts
+++ b/packages/cdk-stripe-webhook/src/stripe-webhook.ts
@@ -1,9 +1,9 @@
 import * as path from 'path';
 import { SingletonFunction, Runtime, Code } from '@aws-cdk/aws-lambda';
 import { Construct, Duration, CustomResource } from '@aws-cdk/core';
-
+import { SecretKey } from '@cloudcomponents/cdk-secret-key';
 export interface StripeWebhookProps {
-  readonly secretKey: string;
+  readonly secretKey: SecretKey | string;
   readonly url: string;
   readonly description?: string;
   readonly events: string[];
@@ -16,6 +16,8 @@ export class StripeWebhook extends Construct {
   constructor(scope: Construct, id: string, props: StripeWebhookProps) {
     super(scope, id);
 
+    const secretKey = typeof props.secretKey === 'string' ? SecretKey.fromPlainText(props.secretKey) : props.secretKey;
+
     const handler = new SingletonFunction(this, 'CustomResourceHandler', {
       uuid: 'e9db3870-d793-4cd2-96a9-efe2e318ebbc',
       runtime: Runtime.NODEJS_12_X,
@@ -25,12 +27,20 @@ export class StripeWebhook extends Construct {
       timeout: Duration.minutes(15),
     });
 
+    if (secretKey.grantRead) {
+      secretKey.grantRead(handler);
+    }
+
     const cr = new CustomResource(this, 'CustomResource', {
       serviceToken: handler.functionArn,
       resourceType: 'Custom::StripeWebhook',
       pascalCaseProperties: true,
       properties: {
-        ...props,
+        url: props.url,
+        description: props.description,
+        events: props.events,
+        logLevel: props.logLevel,
+        secretKeyString: secretKey.serialize(),
       },
     });
 
diff --git a/yarn.lock b/yarn.lock
index 1a945e6d0..ec41cc10b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -662,7 +662,7 @@
     "@aws-cdk/core" "1.93.0"
     constructs "^3.2.0"
 
-"@aws-cdk/aws-secretsmanager@1.93.0":
+"@aws-cdk/aws-secretsmanager@1.93.0", "@aws-cdk/aws-secretsmanager@^1.93.0":
   version "1.93.0"
   resolved "https://registry.yarnpkg.com/@aws-cdk/aws-secretsmanager/-/aws-secretsmanager-1.93.0.tgz#e45d0c0d00838cd7343cf505fd47871d9701e9bb"
   integrity sha512-Vyl2k66J0Ag256W8YBcdS7QM9cr6/aBZuEq5kyFT9GMwhpQ5RpDT+OUg31Pu3mLizlU70YlYueegnUQYEjxTbQ==
@@ -1127,6 +1127,13 @@
   resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
   integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
 
+"@cloudcomponents/lambda-utils@^0.1.1":
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/@cloudcomponents/lambda-utils/-/lambda-utils-0.1.1.tgz#244aa2641c98ae773cc43c1f0c23b37bb6ae5c07"
+  integrity sha512-TTnT1yRGeL28EBFRhDXBMiUKn/mK95ZXKY+cOduG/MYU5U8hjC3/H+t0efkUPQJTnAyqR2jzvY8tsUkqFQmf+Q==
+  dependencies:
+    aws-parameter-cache "^1.2.0"
+
 "@cnakazawa/watch@^1.0.3":
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -3561,6 +3568,11 @@ aws-local-testing-library@^0.0.7:
     lodash.merge "^4.6.2"
     uuid "^8.3.0"
 
+aws-parameter-cache@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/aws-parameter-cache/-/aws-parameter-cache-1.2.0.tgz#b202fcaace4e066a9b6f9a00e7eb29daab900643"
+  integrity sha512-GoMfOSEYJNXyUqkK2YBwyR6cKUEv8Gs6LrTx5pkZhLKCnU7finPgLHhS76SppPyrBJ9CuzRBi8FH4mvVf0eZ9w==
+
 aws-sdk@^2.848.0:
   version "2.849.0"
   resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.849.0.tgz#7fc9863e04f9e97c1f81f204fca84dfb2e4175dd"


Test patch:
diff --git a/packages/cdk-contentful-webhook/src/__tests__/__snapshots__/contentful-webhook.test.ts.snap b/packages/cdk-contentful-webhook/src/__tests__/__snapshots__/contentful-webhook.test.ts.snap
index 744dc737c..7c91b2be5 100644
--- a/packages/cdk-contentful-webhook/src/__tests__/__snapshots__/contentful-webhook.test.ts.snap
+++ b/packages/cdk-contentful-webhook/src/__tests__/__snapshots__/contentful-webhook.test.ts.snap
@@ -7,7 +7,7 @@ Object {
     "ContentfulWebhookCustomResourceFC4E1F73": Object {
       "DeletionPolicy": "Delete",
       "Properties": Object {
-        "AccessToken": "<access_token>",
+        "AccessTokenString": "{\\"secretKeyType\\":\\"PLAIN_TEXT\\",\\"value\\":\\"<access_token>\\"}",
         "Name": "My webhook",
         "ServiceToken": Object {
           "Fn::GetAtt": Array [
diff --git a/packages/cdk-github-webhook/src/__tests__/__snapshots__/github-webhook.test.ts.snap b/packages/cdk-github-webhook/src/__tests__/__snapshots__/github-webhook.test.ts.snap
index b1164d55e..a3da534d9 100644
--- a/packages/cdk-github-webhook/src/__tests__/__snapshots__/github-webhook.test.ts.snap
+++ b/packages/cdk-github-webhook/src/__tests__/__snapshots__/github-webhook.test.ts.snap
@@ -59,7 +59,7 @@ Object {
         "Events": Array [
           "test",
         ],
-        "GithubApiToken": "test12",
+        "GithubApiTokenString": "{\\"secretKeyType\\":\\"PLAIN_TEXT\\",\\"value\\":\\"test12\\"}",
         "GithubRepoUrl": "test",
         "PayloadUrl": "test",
         "ServiceToken": Object {
diff --git a/packages/cdk-secret-key/src/__tests__/secret-key.test.ts b/packages/cdk-secret-key/src/__tests__/secret-key.test.ts
new file mode 100644
index 000000000..5c2b577f7
--- /dev/null
+++ b/packages/cdk-secret-key/src/__tests__/secret-key.test.ts
@@ -0,0 +1,57 @@
+import { Secret } from '@aws-cdk/aws-secretsmanager';
+import { StringParameter } from '@aws-cdk/aws-ssm';
+import { Stack } from '@aws-cdk/core';
+
+import { KeyType } from '../key-type';
+import { SecretKey } from '../secret-key';
+
+test('plain text', (): void => {
+  const secretKey = SecretKey.fromPlainText('foo');
+
+  expect(secretKey.serialize()).toEqual(
+    JSON.stringify({
+      secretKeyType: KeyType.PLAIN_TEXT,
+      value: 'foo',
+    }),
+  );
+});
+
+test('ssm parameter', (): void => {
+  const stack = new Stack();
+  const secretKeyParameter = StringParameter.fromStringParameterName(stack, 'TestParameter', 'secret-key');
+  const secretKey = SecretKey.fromSSMParameter(secretKeyParameter);
+
+  const parsedSecretKey = JSON.parse(secretKey.serialize());
+
+  expect(parsedSecretKey).toEqual({
+    secretKeyType: KeyType.SSM_PARAMETER,
+    parameterName: secretKeyParameter.parameterName,
+  });
+});
+
+test('secrets manager', (): void => {
+  const stack = new Stack();
+  const secretKeySecret = Secret.fromSecretNameV2(stack, 'TestSecret', 'secret-key');
+  const secretKey = SecretKey.fromSecretsManager(secretKeySecret);
+
+  const parsedSecretKey = JSON.parse(secretKey.serialize());
+
+  expect(parsedSecretKey).toEqual({
+    secretKeyType: KeyType.SECRETS_MANAGER,
+    secretId: secretKeySecret.secretArn,
+  });
+});
+
+test('secrets manager with fieldName', (): void => {
+  const stack = new Stack();
+  const secretKeySecret = Secret.fromSecretNameV2(stack, 'TestSecret', 'secret-key');
+  const secretKey = SecretKey.fromSecretsManager(secretKeySecret, 'api');
+
+  const parsedSecretKey = JSON.parse(secretKey.serialize());
+
+  expect(parsedSecretKey).toEqual({
+    secretKeyType: KeyType.SECRETS_MANAGER,
+    secretId: secretKeySecret.secretArn,
+    fieldName: 'api',
+  });
+});
diff --git a/packages/cdk-stripe-webhook/src/__tests__/__snapshots__/stripe-webhook.test.ts.snap b/packages/cdk-stripe-webhook/src/__tests__/__snapshots__/stripe-webhook.test.ts.snap
index 222512d7b..22418396a 100644
--- a/packages/cdk-stripe-webhook/src/__tests__/__snapshots__/stripe-webhook.test.ts.snap
+++ b/packages/cdk-stripe-webhook/src/__tests__/__snapshots__/stripe-webhook.test.ts.snap
@@ -60,7 +60,7 @@ Object {
           "charge.failed",
           "charge.succeeded",
         ],
-        "SecretKey": "sk_test_1213fdsdfsgfsdgdfgfdg",
+        "SecretKeyString": "{\\"secretKeyType\\":\\"PLAIN_TEXT\\",\\"value\\":\\"sk_test_1213fdsdfsgfsdgdfgfdg\\"}",
         "ServiceToken": Object {
           "Fn::GetAtt": Array [
             "CustomStripeWebhooke9db3870d7934cd296a9efe2e318ebbc3F433A9D",