@cdklabs/cdk-appmod-catalog-blueprints 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.jsii +8644 -0
  2. package/LICENSE +202 -0
  3. package/README.md +212 -0
  4. package/lib/document-processing/agentic-document-processing.d.ts +16 -0
  5. package/lib/document-processing/agentic-document-processing.js +90 -0
  6. package/lib/document-processing/base-document-processing.d.ts +189 -0
  7. package/lib/document-processing/base-document-processing.js +509 -0
  8. package/lib/document-processing/bedrock-document-processing.d.ts +167 -0
  9. package/lib/document-processing/bedrock-document-processing.js +297 -0
  10. package/lib/document-processing/index.d.ts +3 -0
  11. package/lib/document-processing/index.js +20 -0
  12. package/lib/document-processing/resources/default-bedrock-invoke/index.py +63 -0
  13. package/lib/document-processing/resources/default-bedrock-invoke/requirements.txt +4 -0
  14. package/lib/document-processing/resources/default-doc-retrieval-lambda/index.mjs +92 -0
  15. package/lib/document-processing/resources/default-doc-retrieval-lambda/package.json +10 -0
  16. package/lib/document-processing/resources/default-error-handler/index.js +46 -0
  17. package/lib/document-processing/resources/default-error-handler/package.json +4 -0
  18. package/lib/document-processing/resources/default-image-processor/classifier.mjs +665 -0
  19. package/lib/document-processing/resources/default-image-processor/extractors.mjs +465 -0
  20. package/lib/document-processing/resources/default-image-processor/index.mjs +143 -0
  21. package/lib/document-processing/resources/default-image-processor/package-lock.json +12 -0
  22. package/lib/document-processing/resources/default-image-processor/package.json +4 -0
  23. package/lib/document-processing/resources/default-image-validator/index.mjs +76 -0
  24. package/lib/document-processing/resources/default-image-validator/package-lock.json +154 -0
  25. package/lib/document-processing/resources/default-image-validator/package.json +7 -0
  26. package/lib/document-processing/resources/default-pdf-processor/index.js +46 -0
  27. package/lib/document-processing/resources/default-pdf-validator/index.js +36 -0
  28. package/lib/document-processing/resources/default-sqs-consumer/index.py +111 -0
  29. package/lib/document-processing/resources/default-sqs-consumer/requirements.txt +4 -0
  30. package/lib/document-processing/resources/default-sqs-consumer/sample_payload.json +20 -0
  31. package/lib/document-processing/resources/default-sqs-consumer/sample_payload_multi.json +24 -0
  32. package/lib/document-processing/resources/default-strands-agent/index.py +111 -0
  33. package/lib/document-processing/resources/default-strands-agent/requirements.txt +6 -0
  34. package/lib/document-processing/tests/agentic-document-processing-nag.test.d.ts +1 -0
  35. package/lib/document-processing/tests/agentic-document-processing-nag.test.js +107 -0
  36. package/lib/document-processing/tests/agentic-document-processing.test.d.ts +1 -0
  37. package/lib/document-processing/tests/agentic-document-processing.test.js +125 -0
  38. package/lib/document-processing/tests/bedrock-document-processing-nag.test.d.ts +1 -0
  39. package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +101 -0
  40. package/lib/document-processing/tests/bedrock-document-processing.test.d.ts +1 -0
  41. package/lib/document-processing/tests/bedrock-document-processing.test.js +79 -0
  42. package/lib/framework/custom-resource/default-runtimes.d.ts +21 -0
  43. package/lib/framework/custom-resource/default-runtimes.js +34 -0
  44. package/lib/framework/custom-resource/index.d.ts +1 -0
  45. package/lib/framework/custom-resource/index.js +18 -0
  46. package/lib/framework/foundation/access-log.d.ts +69 -0
  47. package/lib/framework/foundation/access-log.js +121 -0
  48. package/lib/framework/foundation/eventbridge-broker.d.ts +18 -0
  49. package/lib/framework/foundation/eventbridge-broker.js +42 -0
  50. package/lib/framework/foundation/index.d.ts +3 -0
  51. package/lib/framework/foundation/index.js +20 -0
  52. package/lib/framework/foundation/network.d.ts +19 -0
  53. package/lib/framework/foundation/network.js +83 -0
  54. package/lib/framework/index.d.ts +2 -0
  55. package/lib/framework/index.js +19 -0
  56. package/lib/framework/quickstart/base-quickstart.d.ts +30 -0
  57. package/lib/framework/quickstart/base-quickstart.js +30 -0
  58. package/lib/index.d.ts +4 -0
  59. package/lib/index.js +21 -0
  60. package/lib/tsconfig.tsbuildinfo +1 -0
  61. package/lib/utilities/cdk-nag-config.d.ts +42 -0
  62. package/lib/utilities/cdk-nag-config.js +194 -0
  63. package/lib/utilities/data-loader-lambda/index.py +282 -0
  64. package/lib/utilities/data-loader-lambda/requirements.txt +3 -0
  65. package/lib/utilities/data-loader.d.ts +173 -0
  66. package/lib/utilities/data-loader.js +447 -0
  67. package/lib/utilities/index.d.ts +3 -0
  68. package/lib/utilities/index.js +20 -0
  69. package/lib/utilities/lambda-iam-utils.d.ts +145 -0
  70. package/lib/utilities/lambda-iam-utils.js +235 -0
  71. package/lib/utilities/lambda_layers/data-masking/layer-construct.d.ts +42 -0
  72. package/lib/utilities/lambda_layers/data-masking/layer-construct.js +53 -0
  73. package/lib/utilities/lambda_layers/data-masking/layer-construct.ts +88 -0
  74. package/lib/utilities/observability/bedrock-observability.d.ts +18 -0
  75. package/lib/utilities/observability/bedrock-observability.js +131 -0
  76. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.d.ts +6 -0
  77. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +22 -0
  78. package/lib/utilities/observability/index.d.ts +6 -0
  79. package/lib/utilities/observability/index.js +25 -0
  80. package/lib/utilities/observability/lambda-observability-property-injector.d.ts +8 -0
  81. package/lib/utilities/observability/lambda-observability-property-injector.js +43 -0
  82. package/lib/utilities/observability/log-group-data-protection-props.d.ts +19 -0
  83. package/lib/utilities/observability/log-group-data-protection-props.js +5 -0
  84. package/lib/utilities/observability/observability.d.ts +83 -0
  85. package/lib/utilities/observability/observability.js +278 -0
  86. package/lib/utilities/observability/observable.d.ts +32 -0
  87. package/lib/utilities/observability/observable.js +3 -0
  88. package/lib/utilities/observability/powertools-config.d.ts +3 -0
  89. package/lib/utilities/observability/powertools-config.js +25 -0
  90. package/lib/utilities/observability/resources/bedrock-manage-logging-configuration/index.py +27 -0
  91. package/lib/utilities/observability/state-machine-observability-property-injector.d.ts +8 -0
  92. package/lib/utilities/observability/state-machine-observability-property-injector.js +49 -0
  93. package/lib/utilities/tests/data-loader-nag.test.d.ts +1 -0
  94. package/lib/utilities/tests/data-loader-nag.test.js +432 -0
  95. package/lib/utilities/tests/data-loader.test.d.ts +1 -0
  96. package/lib/utilities/tests/data-loader.test.js +284 -0
  97. package/lib/webapp/frontend-construct.d.ts +136 -0
  98. package/lib/webapp/frontend-construct.js +253 -0
  99. package/lib/webapp/index.d.ts +1 -0
  100. package/lib/webapp/index.js +18 -0
  101. package/lib/webapp/tests/frontend-construct-nag.test.d.ts +1 -0
  102. package/lib/webapp/tests/frontend-construct-nag.test.js +266 -0
  103. package/lib/webapp/tests/frontend-construct.test.d.ts +1 -0
  104. package/lib/webapp/tests/frontend-construct.test.js +385 -0
  105. package/package.json +183 -0
@@ -0,0 +1,145 @@
1
+ import * as iam from 'aws-cdk-lib/aws-iam';
2
+ import { Construct } from 'constructs';
3
+ /**
4
+ * Stack information
5
+ */
6
+ export interface LambdaIamUtilsStackInfo {
7
+ readonly region: string;
8
+ readonly account: string;
9
+ }
10
+ /**
11
+ * Configuration options for Lambda CloudWatch Logs permissions
12
+ */
13
+ export interface LambdaLogsPermissionsProps {
14
+ /**
15
+ * The construct scope (used to generate unique names)
16
+ */
17
+ readonly scope: Construct;
18
+ /**
19
+ * The base name of the Lambda function
20
+ */
21
+ readonly functionName: string;
22
+ /**
23
+ * Custom log group name pattern
24
+ * @default '/aws/lambda/{uniqueFunctionName}'
25
+ */
26
+ readonly logGroupName?: string;
27
+ /**
28
+ * AWS region for the log group ARN
29
+ */
30
+ readonly region: string;
31
+ /**
32
+ * AWS account ID for the log group ARN
33
+ */
34
+ readonly account: string;
35
+ }
36
+ /**
37
+ * Result of creating Lambda logs permissions
38
+ */
39
+ export interface LambdaLogsPermissionsResult {
40
+ /**
41
+ * The policy statements for CloudWatch Logs
42
+ */
43
+ readonly policyStatements: iam.PolicyStatement[];
44
+ /**
45
+ * The unique function name that was generated
46
+ */
47
+ readonly uniqueFunctionName: string;
48
+ }
49
+ /**
50
+ * Utility class for creating secure Lambda IAM policy statements with minimal permissions
51
+ */
52
+ export declare class LambdaIamUtils {
53
+ /**
54
+ * Creates CloudWatch Logs policy statements for Lambda execution
55
+ *
56
+ * @param props Configuration properties
57
+ * @returns Object containing policy statements and the unique function name
58
+ */
59
+ static createLogsPermissions(props: LambdaLogsPermissionsProps): LambdaLogsPermissionsResult;
60
+ static generateLambdaVPCPermissions(): iam.PolicyStatement;
61
+ /**
62
+ * Generates a unique function name using CDK's built-in functionality
63
+ *
64
+ * @param scope The construct scope
65
+ * @param baseName The base name for the function
66
+ * @returns Unique function name
67
+ */
68
+ static generateUniqueFunctionName(scope: Construct, baseName: string): string;
69
+ /**
70
+ * Creates VPC permissions for Lambda functions running in VPC
71
+ *
72
+ * @returns Array of IAM PolicyStatements for VPC access
73
+ */
74
+ static createVpcPermissions(): iam.PolicyStatement[];
75
+ /**
76
+ * Creates X-Ray tracing permissions for Lambda functions
77
+ *
78
+ * @returns Array of IAM PolicyStatements for X-Ray tracing
79
+ */
80
+ static createXRayPermissions(): iam.PolicyStatement[];
81
+ /**
82
+ * Helper method to get region and account from a construct
83
+ *
84
+ * @param scope The construct scope
85
+ * @returns LambdaIamUtilsStackInfo
86
+ */
87
+ static getStackInfo(scope: Construct): LambdaIamUtilsStackInfo;
88
+ /**
89
+ * Creates a policy statement for DynamoDB table access
90
+ *
91
+ * @param tableArn The ARN of the DynamoDB table
92
+ * @param actions The DynamoDB actions to allow
93
+ * @returns PolicyStatement for DynamoDB access
94
+ */
95
+ static createDynamoDbPolicyStatement(tableArn: string, actions?: string[]): iam.PolicyStatement;
96
+ /**
97
+ * Creates a policy statement for S3 bucket access
98
+ *
99
+ * @param bucketArn The ARN of the S3 bucket
100
+ * @param actions The S3 actions to allow
101
+ * @param includeObjects Whether to include object-level permissions
102
+ * @returns PolicyStatement for S3 access
103
+ */
104
+ static createS3PolicyStatement(bucketArn: string, actions?: string[], includeObjects?: boolean): iam.PolicyStatement;
105
+ /**
106
+ * Creates a policy statement for SQS queue access
107
+ *
108
+ * @param queueArn The ARN of the SQS queue
109
+ * @param actions The SQS actions to allow
110
+ * @returns PolicyStatement for SQS access
111
+ */
112
+ static createSqsPolicyStatement(queueArn: string, actions?: string[]): iam.PolicyStatement;
113
+ /**
114
+ * Creates a policy statement for SNS topic access
115
+ *
116
+ * @param topicArn The ARN of the SNS topic
117
+ * @param actions The SNS actions to allow
118
+ * @returns PolicyStatement for SNS access
119
+ */
120
+ static createSnsPolicyStatement(topicArn: string, actions?: string[]): iam.PolicyStatement;
121
+ /**
122
+ * Creates a policy statement for Step Functions execution
123
+ *
124
+ * @param stateMachineArn The ARN of the Step Functions state machine
125
+ * @param actions The Step Functions actions to allow
126
+ * @returns PolicyStatement for Step Functions access
127
+ */
128
+ static createStepFunctionsPolicyStatement(stateMachineArn: string, actions?: string[]): iam.PolicyStatement;
129
+ /**
130
+ * Creates a policy statement for Secrets Manager access
131
+ *
132
+ * @param secretArn The ARN of the secret
133
+ * @param actions The Secrets Manager actions to allow
134
+ * @returns PolicyStatement for Secrets Manager access
135
+ */
136
+ static createSecretsManagerPolicyStatement(secretArn: string, actions?: string[]): iam.PolicyStatement;
137
+ /**
138
+ * Creates a policy statement for KMS key access
139
+ *
140
+ * @param keyArn The ARN of the KMS key
141
+ * @param actions The KMS actions to allow
142
+ * @returns PolicyStatement for KMS access
143
+ */
144
+ static createKmsPolicyStatement(keyArn: string, actions?: string[]): iam.PolicyStatement;
145
+ }
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.LambdaIamUtils = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
7
+ // SPDX-License-Identifier: Apache-2.0
8
+ const cdk = require("aws-cdk-lib");
9
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
10
+ const iam = require("aws-cdk-lib/aws-iam");
11
+ /**
12
+ * Utility class for creating secure Lambda IAM policy statements with minimal permissions
13
+ */
14
+ class LambdaIamUtils {
15
+ /**
16
+ * Creates CloudWatch Logs policy statements for Lambda execution
17
+ *
18
+ * @param props Configuration properties
19
+ * @returns Object containing policy statements and the unique function name
20
+ */
21
+ static createLogsPermissions(props) {
22
+ // Generate unique function name using construct node path
23
+ const uniqueFunctionName = LambdaIamUtils.generateUniqueFunctionName(props.scope, props.functionName);
24
+ const logGroupName = props.logGroupName || `/aws/lambda/${uniqueFunctionName}`;
25
+ const policyStatements = [
26
+ // Permission to create log group
27
+ new iam.PolicyStatement({
28
+ effect: iam.Effect.ALLOW,
29
+ actions: ['logs:CreateLogGroup'],
30
+ resources: [
31
+ `arn:aws:logs:${props.region}:${props.account}:log-group:${logGroupName}:*`,
32
+ ],
33
+ }),
34
+ // Permission to create log streams and put log events
35
+ new iam.PolicyStatement({
36
+ effect: iam.Effect.ALLOW,
37
+ actions: [
38
+ 'logs:CreateLogStream',
39
+ 'logs:PutLogEvents',
40
+ ],
41
+ resources: [
42
+ `arn:aws:logs:${props.region}:${props.account}:log-group:${logGroupName}:*`,
43
+ ],
44
+ }),
45
+ ];
46
+ return {
47
+ policyStatements,
48
+ uniqueFunctionName,
49
+ };
50
+ }
51
+ static generateLambdaVPCPermissions() {
52
+ return new iam.PolicyStatement({
53
+ effect: iam.Effect.ALLOW,
54
+ actions: [
55
+ 'ec2:CreateNetworkInterface',
56
+ 'ec2:DescribeNetworkInterfaces',
57
+ 'ec2:DescribeSubnets',
58
+ 'ec2:DeleteNetworkInterface',
59
+ 'ec2:AssignPrivateIpAddresses',
60
+ 'ec2:UnassignPrivateIpAddresses',
61
+ 'ec2:DescribeSecurityGroups',
62
+ 'ec2:DescribeVpcs',
63
+ 'ec2:GetSecurityGroupsForVpc',
64
+ ],
65
+ resources: ['*'],
66
+ });
67
+ }
68
+ /**
69
+ * Generates a unique function name using CDK's built-in functionality
70
+ *
71
+ * @param scope The construct scope
72
+ * @param baseName The base name for the function
73
+ * @returns Unique function name
74
+ */
75
+ static generateUniqueFunctionName(scope, baseName) {
76
+ return `${baseName}-${aws_cdk_lib_1.Names.uniqueResourceName(scope, { maxLength: 64 - (baseName.length + 1) }).toLowerCase()}`;
77
+ }
78
+ /**
79
+ * Creates VPC permissions for Lambda functions running in VPC
80
+ *
81
+ * @returns Array of IAM PolicyStatements for VPC access
82
+ */
83
+ static createVpcPermissions() {
84
+ return [
85
+ new iam.PolicyStatement({
86
+ effect: iam.Effect.ALLOW,
87
+ actions: [
88
+ 'ec2:CreateNetworkInterface',
89
+ 'ec2:DescribeNetworkInterfaces',
90
+ 'ec2:DeleteNetworkInterface',
91
+ 'ec2:AttachNetworkInterface',
92
+ 'ec2:DetachNetworkInterface',
93
+ ],
94
+ resources: ['*'], // VPC permissions require wildcard resources
95
+ }),
96
+ ];
97
+ }
98
+ /**
99
+ * Creates X-Ray tracing permissions for Lambda functions
100
+ *
101
+ * @returns Array of IAM PolicyStatements for X-Ray tracing
102
+ */
103
+ static createXRayPermissions() {
104
+ return [
105
+ new iam.PolicyStatement({
106
+ effect: iam.Effect.ALLOW,
107
+ actions: [
108
+ 'xray:PutTraceSegments',
109
+ 'xray:PutTelemetryRecords',
110
+ ],
111
+ resources: ['*'], // X-Ray permissions require wildcard resources
112
+ }),
113
+ ];
114
+ }
115
+ /**
116
+ * Helper method to get region and account from a construct
117
+ *
118
+ * @param scope The construct scope
119
+ * @returns LambdaIamUtilsStackInfo
120
+ */
121
+ static getStackInfo(scope) {
122
+ const stack = cdk.Stack.of(scope);
123
+ return {
124
+ region: stack.region,
125
+ account: stack.account,
126
+ };
127
+ }
128
+ /**
129
+ * Creates a policy statement for DynamoDB table access
130
+ *
131
+ * @param tableArn The ARN of the DynamoDB table
132
+ * @param actions The DynamoDB actions to allow
133
+ * @returns PolicyStatement for DynamoDB access
134
+ */
135
+ static createDynamoDbPolicyStatement(tableArn, actions = ['dynamodb:GetItem', 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', 'dynamodb:Query', 'dynamodb:Scan']) {
136
+ return new iam.PolicyStatement({
137
+ effect: iam.Effect.ALLOW,
138
+ actions,
139
+ resources: [tableArn, `${tableArn}/index/*`], // Include GSI access
140
+ });
141
+ }
142
+ /**
143
+ * Creates a policy statement for S3 bucket access
144
+ *
145
+ * @param bucketArn The ARN of the S3 bucket
146
+ * @param actions The S3 actions to allow
147
+ * @param includeObjects Whether to include object-level permissions
148
+ * @returns PolicyStatement for S3 access
149
+ */
150
+ static createS3PolicyStatement(bucketArn, actions = ['s3:GetObject', 's3:PutObject'], includeObjects = true) {
151
+ const resources = [bucketArn];
152
+ if (includeObjects) {
153
+ resources.push(`${bucketArn}/*`);
154
+ }
155
+ return new iam.PolicyStatement({
156
+ effect: iam.Effect.ALLOW,
157
+ actions,
158
+ resources,
159
+ });
160
+ }
161
+ /**
162
+ * Creates a policy statement for SQS queue access
163
+ *
164
+ * @param queueArn The ARN of the SQS queue
165
+ * @param actions The SQS actions to allow
166
+ * @returns PolicyStatement for SQS access
167
+ */
168
+ static createSqsPolicyStatement(queueArn, actions = ['sqs:ReceiveMessage', 'sqs:DeleteMessage', 'sqs:GetQueueAttributes']) {
169
+ return new iam.PolicyStatement({
170
+ effect: iam.Effect.ALLOW,
171
+ actions,
172
+ resources: [queueArn],
173
+ });
174
+ }
175
+ /**
176
+ * Creates a policy statement for SNS topic access
177
+ *
178
+ * @param topicArn The ARN of the SNS topic
179
+ * @param actions The SNS actions to allow
180
+ * @returns PolicyStatement for SNS access
181
+ */
182
+ static createSnsPolicyStatement(topicArn, actions = ['sns:Publish']) {
183
+ return new iam.PolicyStatement({
184
+ effect: iam.Effect.ALLOW,
185
+ actions,
186
+ resources: [topicArn],
187
+ });
188
+ }
189
+ /**
190
+ * Creates a policy statement for Step Functions execution
191
+ *
192
+ * @param stateMachineArn The ARN of the Step Functions state machine
193
+ * @param actions The Step Functions actions to allow
194
+ * @returns PolicyStatement for Step Functions access
195
+ */
196
+ static createStepFunctionsPolicyStatement(stateMachineArn, actions = ['states:StartExecution']) {
197
+ return new iam.PolicyStatement({
198
+ effect: iam.Effect.ALLOW,
199
+ actions,
200
+ resources: [stateMachineArn],
201
+ });
202
+ }
203
+ /**
204
+ * Creates a policy statement for Secrets Manager access
205
+ *
206
+ * @param secretArn The ARN of the secret
207
+ * @param actions The Secrets Manager actions to allow
208
+ * @returns PolicyStatement for Secrets Manager access
209
+ */
210
+ static createSecretsManagerPolicyStatement(secretArn, actions = ['secretsmanager:GetSecretValue']) {
211
+ return new iam.PolicyStatement({
212
+ effect: iam.Effect.ALLOW,
213
+ actions,
214
+ resources: [secretArn],
215
+ });
216
+ }
217
+ /**
218
+ * Creates a policy statement for KMS key access
219
+ *
220
+ * @param keyArn The ARN of the KMS key
221
+ * @param actions The KMS actions to allow
222
+ * @returns PolicyStatement for KMS access
223
+ */
224
+ static createKmsPolicyStatement(keyArn, actions = ['kms:Decrypt', 'kms:GenerateDataKey']) {
225
+ return new iam.PolicyStatement({
226
+ effect: iam.Effect.ALLOW,
227
+ actions,
228
+ resources: [keyArn],
229
+ });
230
+ }
231
+ }
232
+ exports.LambdaIamUtils = LambdaIamUtils;
233
+ _a = JSII_RTTI_SYMBOL_1;
234
+ LambdaIamUtils[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.LambdaIamUtils", version: "1.0.0" };
235
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWlhbS11dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3VzZS1jYXNlcy91dGlsaXRpZXMvbGFtYmRhLWlhbS11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFDdEMsbUNBQW1DO0FBQ25DLDZDQUFvQztBQUNwQywyQ0FBMkM7QUF5RDNDOztHQUVHO0FBQ0gsTUFBYSxjQUFjO0lBQ3pCOzs7OztPQUtHO0lBQ0ksTUFBTSxDQUFDLHFCQUFxQixDQUFDLEtBQWlDO1FBQ25FLDBEQUEwRDtRQUMxRCxNQUFNLGtCQUFrQixHQUFHLGNBQWMsQ0FBQywwQkFBMEIsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0RyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsWUFBWSxJQUFJLGVBQWUsa0JBQWtCLEVBQUUsQ0FBQztRQUUvRSxNQUFNLGdCQUFnQixHQUFHO1lBQ3ZCLGlDQUFpQztZQUNqQyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7Z0JBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7Z0JBQ3hCLE9BQU8sRUFBRSxDQUFDLHFCQUFxQixDQUFDO2dCQUNoQyxTQUFTLEVBQUU7b0JBQ1QsZ0JBQWdCLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sY0FBYyxZQUFZLElBQUk7aUJBQzVFO2FBQ0YsQ0FBQztZQUNGLHNEQUFzRDtZQUN0RCxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7Z0JBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7Z0JBQ3hCLE9BQU8sRUFBRTtvQkFDUCxzQkFBc0I7b0JBQ3RCLG1CQUFtQjtpQkFDcEI7Z0JBQ0QsU0FBUyxFQUFFO29CQUNULGdCQUFnQixLQUFLLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLGNBQWMsWUFB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QUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLG1DQUFtQyxDQUMvQyxTQUFpQixFQUNqQixVQUFvQixDQUFDLCtCQUErQixDQUFDO1FBRXJELE9BQU8sSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO1lBQzdCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7WUFDeEIsT0FBTztZQUNQLFNBQVMsRUFBRSxDQUFDLFNBQVMsQ0FBQztTQUN2QixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLHdCQUF3QixDQUNwQyxNQUFjLEVBQ2QsVUFBb0IsQ0FBQyxhQUFhLEVBQUUscUJBQXFCLENBQUM7UUFFMUQsT0FBTyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDN0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSztZQUN4QixPQUFPO1lBQ1AsU0FBUyxFQUFFLENBQUMsTUFBTSxDQUFDO1NBQ3BCLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBN1BILHdDQThQQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBOYW1lcyB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFN0YWNrIGluZm9ybWF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFtYmRhSWFtVXRpbHNTdGFja0luZm8ge1xuICByZWFkb25seSByZWdpb246IHN0cmluZztcbiAgcmVhZG9ubHkgYWNjb3VudDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgTGFtYmRhIENsb3VkV2F0Y2ggTG9ncyBwZXJtaXNzaW9uc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUxvZ3NQZXJtaXNzaW9uc1Byb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBjb25zdHJ1Y3Qgc2NvcGUgKHVzZWQgdG8gZ2VuZXJhdGUgdW5pcXVlIG5hbWVzKVxuICAgKi9cbiAgcmVhZG9ubHkgc2NvcGU6IENvbnN0cnVjdDtcblxuICAvKipcbiAgICogVGhlIGJhc2UgbmFtZSBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQ3VzdG9tIGxvZyBncm91cCBuYW1lIHBhdHRlcm5cbiAgICogQGRlZmF1bHQgJy9hd3MvbGFtYmRhL3t1bmlxdWVGdW5jdGlvbk5hbWV9J1xuICAgKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXBOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBV1MgcmVnaW9uIGZvciB0aGUgbG9nIGdyb3VwIEFSTlxuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFXUyBhY2NvdW50IElEIGZvciB0aGUgbG9nIGdyb3VwIEFSTlxuICAgKi9cbiAgcmVhZG9ubHkgYWNjb3VudDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBjcmVhdGluZyBMYW1iZGEgbG9ncyBwZXJtaXNzaW9uc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUxvZ3NQZXJtaXNzaW9uc1Jlc3VsdCB7XG4gIC8qKlxuICAgKiBUaGUgcG9saWN5IHN0YXRlbWVudHMgZm9yIENsb3VkV2F0Y2ggTG9nc1xuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5U3RhdGVtZW50czogaWFtLlBvbGljeVN0YXRlbWVudFtdO1xuXG4gIC8qKlxuICAgKiBUaGUgdW5pcXVlIGZ1bmN0aW9uIG5hbWUgdGhhdCB3YXMgZ2VuZXJhdGVkXG4gICAqL1xuICByZWFkb25seSB1bmlxdWVGdW5jdGlvbk5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBVdGlsaXR5IGNsYXNzIGZvciBjcmVhdGluZyBzZWN1cmUgTGFtYmRhIElBTSBwb2xpY3kgc3RhdGVtZW50cyB3aXRoIG1pbmltYWwgcGVybWlzc2lvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIExhbWJkYUlhbVV0aWxzIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgQ2xvdWRXYXRjaCBMb2dzIHBvbGljeSBzdGF0ZW1lbnRzIGZvciBMYW1iZGEgZXhlY3V0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBDb25maWd1cmF0aW9uIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgT2JqZWN0IGNvbnRhaW5pbmcgcG9saWN5IHN0YXRlbWVudHMgYW5kIHRoZSB1bmlxdWUgZnVuY3Rpb24gbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjcmVhdGVMb2dzUGVybWlzc2lvbnMocHJvcHM6IExhbWJkYUxvZ3NQZXJtaXNzaW9uc1Byb3BzKTogTGFtYmRhTG9nc1Blcm1pc3Npb25zUmVzdWx0IHtcbiAgICAvLyBHZW5lcmF0ZSB1bmlxdWUgZnVuY3Rpb24gbmFtZSB1c2luZyBjb25zdHJ1Y3Qgbm9kZSBwYXRoXG4gICAgY29uc3QgdW5pcXVlRnVuY3Rpb25OYW1lID0gTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVVbmlxdWVGdW5jdGlvbk5hbWUocHJvcHMuc2NvcGUsIHByb3BzLmZ1bmN0aW9uTmFtZSk7XG4gICAgY29uc3QgbG9nR3JvdXBOYW1lID0gcHJvcHMubG9nR3JvdXBOYW1lIHx8IGAvYXdzL2xhbWJkYS8ke3VuaXF1ZUZ1bmN0aW9uTmFtZX1gO1xuXG4gICAgY29uc3QgcG9saWN5U3RhdGVtZW50cyA9IFtcbiAgICAgIC8vIFBlcm1pc3Npb24gdG8gY3JlYXRlIGxvZyBncm91cFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFsnbG9nczpDcmVhdGVMb2dHcm91cCddLFxuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICBgYXJuOmF3czpsb2dzOiR7cHJvcHMucmVnaW9ufToke3Byb3BzLmFjY291bnR9OmxvZy1ncm91cDoke2xvZ0dyb3VwTmFtZX06KmAsXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICAgIC8vIFBlcm1pc3Npb24gdG8gY3JlYXRlIGxvZyBzdHJlYW1zIGFuZCBwdXQgbG9nIGV2ZW50c1xuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAnbG9nczpDcmVhdGVMb2dTdHJlYW0nLFxuICAgICAgICAgICdsb2dzOlB1dExvZ0V2ZW50cycsXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgIGBhcm46YXdzOmxvZ3M6JHtwcm9wcy5yZWdpb259OiR7cHJvcHMuYWNjb3VudH06bG9nLWdyb3VwOiR7bG9nR3JvdXBOYW1lfToqYCxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgIF07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcG9saWN5U3RhdGVtZW50cyxcbiAgICAgIHVuaXF1ZUZ1bmN0aW9uTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZW5lcmF0ZUxhbWJkYVZQQ1Blcm1pc3Npb25zKCk6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQge1xuICAgIHJldHVybiBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgICdlYzI6Q3JlYXRlTmV0d29ya0ludGVyZmFjZScsXG4gICAgICAgICdlYzI6RGVzY3JpYmVOZXR3b3JrSW50ZXJmYWNlcycsXG4gICAgICAgICdlYzI6RGVzY3JpYmVTdWJuZXRzJyxcbiAgICAgICAgJ2VjMjpEZWxldGVOZXR3b3JrSW50ZXJmYWNlJyxcbiAgICAgICAgJ2VjMjpBc3NpZ25Qcml2YXRlSXBBZGRyZXNzZXMnLFxuICAgICAgICAnZWMyOlVuYXNzaWduUHJpdmF0ZUlwQWRkcmVzc2VzJyxcbiAgICAgICAgJ2VjMjpEZXNjcmliZVNlY3VyaXR5R3JvdXBzJyxcbiAgICAgICAgJ2VjMjpEZXNjcmliZVZwY3MnLFxuICAgICAgICAnZWMyOkdldFNlY3VyaXR5R3JvdXBzRm9yVnBjJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBmdW5jdGlvbiBuYW1lIHVzaW5nIENESydzIGJ1aWx0LWluIGZ1bmN0aW9uYWxpdHlcbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBjb25zdHJ1Y3Qgc2NvcGVcbiAgICogQHBhcmFtIGJhc2VOYW1lIFRoZSBiYXNlIG5hbWUgZm9yIHRoZSBmdW5jdGlvblxuICAgKiBAcmV0dXJucyBVbmlxdWUgZnVuY3Rpb24gbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZW5lcmF0ZVVuaXF1ZUZ1bmN0aW9uTmFtZShzY29wZTogQ29uc3RydWN0LCBiYXNlTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7YmFzZU5hbWV9LSR7TmFtZXMudW5pcXVlUmVzb3VyY2VOYW1lKHNjb3BlLCB7IG1heExlbmd0aDogNjQgLSAoYmFzZU5hbWUubGVuZ3RoICsgMSkgfSkudG9Mb3dlckNhc2UoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgVlBDIHBlcm1pc3Npb25zIGZvciBMYW1iZGEgZnVuY3Rpb25zIHJ1bm5pbmcgaW4gVlBDXG4gICAqXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIElBTSBQb2xpY3lTdGF0ZW1lbnRzIGZvciBWUEMgYWNjZXNzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZVZwY1Blcm1pc3Npb25zKCk6IGlhbS5Qb2xpY3lTdGF0ZW1lbnRbXSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ2VjMjpDcmVhdGVOZXR3b3JrSW50ZXJmYWNlJyxcbiAgICAgICAgICAnZWMyOkRlc2NyaWJlTmV0d29ya0ludGVyZmFjZXMnLFxuICAgICAgICAgICdlYzI6RGVsZXRlTmV0d29ya0ludGVyZmFjZScsXG4gICAgICAgICAgJ2VjMjpBdHRhY2hOZXR3b3JrSW50ZXJmYWNlJyxcbiAgICAgICAgICAnZWMyOkRldGFjaE5ldHdvcmtJbnRlcmZhY2UnLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLCAvLyBWUEMgcGVybWlzc2lvbnMgcmVxdWlyZSB3aWxkY2FyZCByZXNvdXJjZXNcbiAgICAgIH0pLFxuICAgIF07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBYLVJheSB0cmFjaW5nIHBlcm1pc3Npb25zIGZvciBMYW1iZGEgZnVuY3Rpb25zXG4gICAqXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIElBTSBQb2xpY3lTdGF0ZW1lbnRzIGZvciBYLVJheSB0cmFjaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZVhSYXlQZXJtaXNzaW9ucygpOiBpYW0uUG9saWN5U3RhdGVtZW50W10ge1xuICAgIHJldHVybiBbXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICd4cmF5OlB1dFRyYWNlU2VnbWVudHMnLFxuICAgICAgICAgICd4cmF5OlB1dFRlbGVtZXRyeVJlY29yZHMnLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLCAvLyBYLVJheSBwZXJtaXNzaW9ucyByZXF1aXJlIHdpbGRjYXJkIHJlc291cmNlc1xuICAgICAgfSksXG4gICAgXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIGdldCByZWdpb24gYW5kIGFjY291bnQgZnJvbSBhIGNvbnN0cnVjdFxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIGNvbnN0cnVjdCBzY29wZVxuICAgKiBAcmV0dXJucyBMYW1iZGFJYW1VdGlsc1N0YWNrSW5mb1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRTdGFja0luZm8oc2NvcGU6IENvbnN0cnVjdCk6IExhbWJkYUlhbVV0aWxzU3RhY2tJbmZvIHtcbiAgICBjb25zdCBzdGFjayA9IGNkay5TdGFjay5vZihzY29wZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlZ2lvbjogc3RhY2sucmVnaW9uLFxuICAgICAgYWNjb3VudDogc3RhY2suYWNjb3VudCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBwb2xpY3kgc3RhdGVtZW50IGZvciBEeW5hbW9EQiB0YWJsZSBhY2Nlc3NcbiAgICpcbiAgICogQHBhcmFtIHRhYmxlQXJuIFRoZSBBUk4gb2YgdGhlIER5bmFtb0RCIHRhYmxlXG4gICAqIEBwYXJhbSBhY3Rpb25zIFRoZSBEeW5hbW9EQiBhY3Rpb25zIHRvIGFsbG93XG4gICAqIEByZXR1cm5zIFBvbGljeVN0YXRlbWVudCBmb3IgRHluYW1vREIgYWNjZXNzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZUR5bmFtb0RiUG9saWN5U3RhdGVtZW50KFxuICAgIHRhYmxlQXJuOiBzdHJpbmcsXG4gICAgYWN0aW9uczogc3RyaW5nW10gPSBbJ2R5bmFtb2RiOkdldEl0ZW0nLCAnZHluYW1vZGI6UHV0SXRlbScsICdkeW5hbW9kYjpVcGRhdGVJdGVtJywgJ2R5bmFtb2RiOkRlbGV0ZUl0ZW0nLCAnZHluYW1vZGI6UXVlcnknLCAnZHluYW1vZGI6U2NhbiddLFxuICApOiBpYW0uUG9saWN5U3RhdGVtZW50IHtcbiAgICByZXR1cm4gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9ucyxcbiAgICAgIHJlc291cmNlczogW3RhYmxlQXJuLCBgJHt0YWJsZUFybn0vaW5kZXgvKmBdLCAvLyBJbmNsdWRlIEdTSSBhY2Nlc3NcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcG9saWN5IHN0YXRlbWVudCBmb3IgUzMgYnVja2V0IGFjY2Vzc1xuICAgKlxuICAgKiBAcGFyYW0gYnVja2V0QXJuIFRoZSBBUk4gb2YgdGhlIFMzIGJ1Y2tldFxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgUzMgYWN0aW9ucyB0byBhbGxvd1xuICAgKiBAcGFyYW0gaW5jbHVkZU9iamVjdHMgV2hldGhlciB0byBpbmNsdWRlIG9iamVjdC1sZXZlbCBwZXJtaXNzaW9uc1xuICAgKiBAcmV0dXJucyBQb2xpY3lTdGF0ZW1lbnQgZm9yIFMzIGFjY2Vzc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjcmVhdGVTM1BvbGljeVN0YXRlbWVudChcbiAgICBidWNrZXRBcm46IHN0cmluZyxcbiAgICBhY3Rpb25zOiBzdHJpbmdbXSA9IFsnczM6R2V0T2JqZWN0JywgJ3MzOlB1dE9iamVjdCddLFxuICAgIGluY2x1ZGVPYmplY3RzOiBib29sZWFuID0gdHJ1ZSxcbiAgKTogaWFtLlBvbGljeVN0YXRlbWVudCB7XG4gICAgY29uc3QgcmVzb3VyY2VzID0gW2J1Y2tldEFybl07XG4gICAgaWYgKGluY2x1ZGVPYmplY3RzKSB7XG4gICAgICByZXNvdXJjZXMucHVzaChgJHtidWNrZXRBcm59LypgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9ucyxcbiAgICAgIHJlc291cmNlcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcG9saWN5IHN0YXRlbWVudCBmb3IgU1FTIHF1ZXVlIGFjY2Vzc1xuICAgKlxuICAgKiBAcGFyYW0gcXVldWVBcm4gVGhlIEFSTiBvZiB0aGUgU1FTIHF1ZXVlXG4gICAqIEBwYXJhbSBhY3Rpb25zIFRoZSBTUVMgYWN0aW9ucyB0byBhbGxvd1xuICAgKiBAcmV0dXJucyBQb2xpY3lTdGF0ZW1lbnQgZm9yIFNRUyBhY2Nlc3NcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlU3FzUG9saWN5U3RhdGVtZW50KFxuICAgIHF1ZXVlQXJuOiBzdHJpbmcsXG4gICAgYWN0aW9uczogc3RyaW5nW10gPSBbJ3NxczpSZWNlaXZlTWVzc2FnZScsICdzcXM6RGVsZXRlTWVzc2FnZScsICdzcXM6R2V0UXVldWVBdHRyaWJ1dGVzJ10sXG4gICk6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQge1xuICAgIHJldHVybiBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VzOiBbcXVldWVBcm5dLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBwb2xpY3kgc3RhdGVtZW50IGZvciBTTlMgdG9waWMgYWNjZXNzXG4gICAqXG4gICAqIEBwYXJhbSB0b3BpY0FybiBUaGUgQVJOIG9mIHRoZSBTTlMgdG9waWNcbiAgICogQHBhcmFtIGFjdGlvbnMgVGhlIFNOUyBhY3Rpb25zIHRvIGFsbG93XG4gICAqIEByZXR1cm5zIFBvbGljeVN0YXRlbWVudCBmb3IgU05TIGFjY2Vzc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjcmVhdGVTbnNQb2xpY3lTdGF0ZW1lbnQoXG4gICAgdG9waWNBcm46IHN0cmluZyxcbiAgICBhY3Rpb25zOiBzdHJpbmdbXSA9IFsnc25zOlB1Ymxpc2gnXSxcbiAgKTogaWFtLlBvbGljeVN0YXRlbWVudCB7XG4gICAgcmV0dXJuIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgIGFjdGlvbnMsXG4gICAgICByZXNvdXJjZXM6IFt0b3BpY0Fybl0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHBvbGljeSBzdGF0ZW1lbnQgZm9yIFN0ZXAgRnVuY3Rpb25zIGV4ZWN1dGlvblxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVNYWNoaW5lQXJuIFRoZSBBUk4gb2YgdGhlIFN0ZXAgRnVuY3Rpb25zIHN0YXRlIG1hY2hpbmVcbiAgICogQHBhcmFtIGFjdGlvbnMgVGhlIFN0ZXAgRnVuY3Rpb25zIGFjdGlvbnMgdG8gYWxsb3dcbiAgICogQHJldHVybnMgUG9saWN5U3RhdGVtZW50IGZvciBTdGVwIEZ1bmN0aW9ucyBhY2Nlc3NcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlU3RlcEZ1bmN0aW9uc1BvbGljeVN0YXRlbWVudChcbiAgICBzdGF0ZU1hY2hpbmVBcm46IHN0cmluZyxcbiAgICBhY3Rpb25zOiBzdHJpbmdbXSA9IFsnc3RhdGVzOlN0YXJ0RXhlY3V0aW9uJ10sXG4gICk6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQge1xuICAgIHJldHVybiBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VzOiBbc3RhdGVNYWNoaW5lQXJuXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcG9saWN5IHN0YXRlbWVudCBmb3IgU2VjcmV0cyBNYW5hZ2VyIGFjY2Vzc1xuICAgKlxuICAgKiBAcGFyYW0gc2VjcmV0QXJuIFRoZSBBUk4gb2YgdGhlIHNlY3JldFxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgU2VjcmV0cyBNYW5hZ2VyIGFjdGlvbnMgdG8gYWxsb3dcbiAgICogQHJldHVybnMgUG9saWN5U3RhdGVtZW50IGZvciBTZWNyZXRzIE1hbmFnZXIgYWNjZXNzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZVNlY3JldHNNYW5hZ2VyUG9saWN5U3RhdGVtZW50KFxuICAgIHNlY3JldEFybjogc3RyaW5nLFxuICAgIGFjdGlvbnM6IHN0cmluZ1tdID0gWydzZWNyZXRzbWFuYWdlcjpHZXRTZWNyZXRWYWx1ZSddLFxuICApOiBpYW0uUG9saWN5U3RhdGVtZW50IHtcbiAgICByZXR1cm4gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9ucyxcbiAgICAgIHJlc291cmNlczogW3NlY3JldEFybl0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHBvbGljeSBzdGF0ZW1lbnQgZm9yIEtNUyBrZXkgYWNjZXNzXG4gICAqXG4gICAqIEBwYXJhbSBrZXlBcm4gVGhlIEFSTiBvZiB0aGUgS01TIGtleVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgS01TIGFjdGlvbnMgdG8gYWxsb3dcbiAgICogQHJldHVybnMgUG9saWN5U3RhdGVtZW50IGZvciBLTVMgYWNjZXNzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZUttc1BvbGljeVN0YXRlbWVudChcbiAgICBrZXlBcm46IHN0cmluZyxcbiAgICBhY3Rpb25zOiBzdHJpbmdbXSA9IFsna21zOkRlY3J5cHQnLCAna21zOkdlbmVyYXRlRGF0YUtleSddLFxuICApOiBpYW0uUG9saWN5U3RhdGVtZW50IHtcbiAgICByZXR1cm4gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9ucyxcbiAgICAgIHJlc291cmNlczogW2tleUFybl0sXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,42 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import { Construct } from 'constructs';
3
+ /**
4
+ * Properties for the DataMaskingLayerConstruct
5
+ */
6
+ export interface DataMaskingLayerProps {
7
+ /**
8
+ * Description for the Lambda layer
9
+ * @default 'Lambda layer for masking sensitive data in document processing'
10
+ */
11
+ description?: string;
12
+ /**
13
+ * Custom masking patterns to add to the default ones
14
+ * @default {}
15
+ */
16
+ customPatterns?: Record<string, {
17
+ /**
18
+ * Regular expression pattern as string
19
+ */
20
+ regex: string;
21
+ /**
22
+ * Mask to apply (string or function name)
23
+ */
24
+ mask: string;
25
+ }>;
26
+ }
27
+ /**
28
+ * Construct that creates a Lambda layer for data masking
29
+ */
30
+ export declare class DataMaskingLayerConstruct extends Construct {
31
+ /**
32
+ * The Lambda layer containing masking utilities
33
+ */
34
+ readonly layer: lambda.LayerVersion;
35
+ constructor(scope: Construct, id: string, props?: DataMaskingLayerProps);
36
+ /**
37
+ * Adds the masking layer to a Lambda function
38
+ * @param fn Lambda function to add the layer to
39
+ * @param maskingConfig Optional masking configuration to add as environment variable
40
+ */
41
+ addToFunction(fn: lambda.Function, maskingConfig?: Record<string, string[]>): void;
42
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.DataMaskingLayerConstruct = void 0;
6
+ const path = require("path");
7
+ const lambda = require("aws-cdk-lib/aws-lambda");
8
+ const constructs_1 = require("constructs");
9
+ /**
10
+ * Construct that creates a Lambda layer for data masking
11
+ */
12
+ class DataMaskingLayerConstruct extends constructs_1.Construct {
13
+ constructor(scope, id, props = {}) {
14
+ super(scope, id);
15
+ // Create the Lambda layer
16
+ this.layer = new lambda.LayerVersion(this, 'DataMaskingLayer', {
17
+ code: lambda.Code.fromAsset(path.join(__dirname, '../../../utilities/lambda_layers/data-masking')),
18
+ compatibleRuntimes: [
19
+ lambda.Runtime.NODEJS_16_X,
20
+ lambda.Runtime.NODEJS_18_X,
21
+ lambda.Runtime.NODEJS_20_X,
22
+ ],
23
+ description: props.description || 'Lambda layer for masking sensitive data',
24
+ license: 'Apache-2.0',
25
+ });
26
+ // Add metadata about available masking patterns
27
+ const defaultPatterns = [
28
+ 'nric', 'ssn', 'creditCard', 'email', 'phone', 'passport',
29
+ ];
30
+ // Add custom patterns if provided
31
+ const allPatterns = [...defaultPatterns];
32
+ if (props.customPatterns) {
33
+ allPatterns.push(...Object.keys(props.customPatterns));
34
+ }
35
+ // Add metadata to the construct
36
+ this.node.addMetadata('maskingPatterns', allPatterns.join(', '));
37
+ }
38
+ /**
39
+ * Adds the masking layer to a Lambda function
40
+ * @param fn Lambda function to add the layer to
41
+ * @param maskingConfig Optional masking configuration to add as environment variable
42
+ */
43
+ addToFunction(fn, maskingConfig) {
44
+ // Add the layer to the function
45
+ fn.addLayers(this.layer);
46
+ // Add masking configuration if provided
47
+ if (maskingConfig) {
48
+ fn.addEnvironment('MASKING_CONFIG', JSON.stringify(maskingConfig));
49
+ }
50
+ }
51
+ }
52
+ exports.DataMaskingLayerConstruct = DataMaskingLayerConstruct;
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5ZXItY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdXNlLWNhc2VzL3V0aWxpdGllcy9sYW1iZGFfbGF5ZXJzL2RhdGEtbWFza2luZy9sYXllci1jb25zdHJ1Y3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7OztBQUV0Qyw2QkFBNkI7QUFDN0IsaURBQWlEO0FBQ2pELDJDQUF1QztBQTZCdkM7O0dBRUc7QUFDSCxNQUFhLHlCQUEwQixTQUFRLHNCQUFTO0lBTXRELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsUUFBK0IsRUFBRTtRQUN6RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDN0QsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLCtDQUErQyxDQUFDLENBQUM7WUFDbEcsa0JBQWtCLEVBQUU7Z0JBQ2xCLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztnQkFDMUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO2dCQUMxQixNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7YUFDM0I7WUFDRCxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSx5Q0FBeUM7WUFDM0UsT0FBTyxFQUFFLFlBQVk7U0FDdEIsQ0FBQyxDQUFDO1FBRUgsZ0RBQWdEO1FBQ2hELE1BQU0sZUFBZSxHQUFHO1lBQ3RCLE1BQU0sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVTtTQUMxRCxDQUFDO1FBRUYsa0NBQWtDO1FBQ2xDLE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQztRQUN6QyxJQUFJLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN6QixXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBRUQsZ0NBQWdDO1FBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLGFBQWEsQ0FBQyxFQUFtQixFQUFFLGFBQXdDO1FBQ2hGLGdDQUFnQztRQUNoQyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV6Qix3Q0FBd0M7UUFDeEMsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixFQUFFLENBQUMsY0FBYyxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUNyRSxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBbERELDhEQWtEQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSBEYXRhTWFza2luZ0xheWVyQ29uc3RydWN0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YU1hc2tpbmdMYXllclByb3BzIHtcbiAgLyoqXG4gICAqIERlc2NyaXB0aW9uIGZvciB0aGUgTGFtYmRhIGxheWVyXG4gICAqIEBkZWZhdWx0ICdMYW1iZGEgbGF5ZXIgZm9yIG1hc2tpbmcgc2Vuc2l0aXZlIGRhdGEgaW4gZG9jdW1lbnQgcHJvY2Vzc2luZydcbiAgICovXG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gbWFza2luZyBwYXR0ZXJucyB0byBhZGQgdG8gdGhlIGRlZmF1bHQgb25lc1xuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgY3VzdG9tUGF0dGVybnM/OiBSZWNvcmQ8c3RyaW5nLCB7XG4gICAgLyoqXG4gICAgICogUmVndWxhciBleHByZXNzaW9uIHBhdHRlcm4gYXMgc3RyaW5nXG4gICAgICovXG4gICAgcmVnZXg6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE1hc2sgdG8gYXBwbHkgKHN0cmluZyBvciBmdW5jdGlvbiBuYW1lKVxuICAgICAqL1xuICAgIG1hc2s6IHN0cmluZztcbiAgfT47XG59XG5cbi8qKlxuICogQ29uc3RydWN0IHRoYXQgY3JlYXRlcyBhIExhbWJkYSBsYXllciBmb3IgZGF0YSBtYXNraW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhTWFza2luZ0xheWVyQ29uc3RydWN0IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFRoZSBMYW1iZGEgbGF5ZXIgY29udGFpbmluZyBtYXNraW5nIHV0aWxpdGllc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGxheWVyOiBsYW1iZGEuTGF5ZXJWZXJzaW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEYXRhTWFza2luZ0xheWVyUHJvcHMgPSB7fSkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICAvLyBDcmVhdGUgdGhlIExhbWJkYSBsYXllclxuICAgIHRoaXMubGF5ZXIgPSBuZXcgbGFtYmRhLkxheWVyVmVyc2lvbih0aGlzLCAnRGF0YU1hc2tpbmdMYXllcicsIHtcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vLi4vdXRpbGl0aWVzL2xhbWJkYV9sYXllcnMvZGF0YS1tYXNraW5nJykpLFxuICAgICAgY29tcGF0aWJsZVJ1bnRpbWVzOiBbXG4gICAgICAgIGxhbWJkYS5SdW50aW1lLk5PREVKU18xNl9YLFxuICAgICAgICBsYW1iZGEuUnVudGltZS5OT0RFSlNfMThfWCxcbiAgICAgICAgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gICAgICBdLFxuICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uIHx8ICdMYW1iZGEgbGF5ZXIgZm9yIG1hc2tpbmcgc2Vuc2l0aXZlIGRhdGEnLFxuICAgICAgbGljZW5zZTogJ0FwYWNoZS0yLjAnLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIG1ldGFkYXRhIGFib3V0IGF2YWlsYWJsZSBtYXNraW5nIHBhdHRlcm5zXG4gICAgY29uc3QgZGVmYXVsdFBhdHRlcm5zID0gW1xuICAgICAgJ25yaWMnLCAnc3NuJywgJ2NyZWRpdENhcmQnLCAnZW1haWwnLCAncGhvbmUnLCAncGFzc3BvcnQnLFxuICAgIF07XG5cbiAgICAvLyBBZGQgY3VzdG9tIHBhdHRlcm5zIGlmIHByb3ZpZGVkXG4gICAgY29uc3QgYWxsUGF0dGVybnMgPSBbLi4uZGVmYXVsdFBhdHRlcm5zXTtcbiAgICBpZiAocHJvcHMuY3VzdG9tUGF0dGVybnMpIHtcbiAgICAgIGFsbFBhdHRlcm5zLnB1c2goLi4uT2JqZWN0LmtleXMocHJvcHMuY3VzdG9tUGF0dGVybnMpKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0YWRhdGEgdG8gdGhlIGNvbnN0cnVjdFxuICAgIHRoaXMubm9kZS5hZGRNZXRhZGF0YSgnbWFza2luZ1BhdHRlcm5zJywgYWxsUGF0dGVybnMuam9pbignLCAnKSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyB0aGUgbWFza2luZyBsYXllciB0byBhIExhbWJkYSBmdW5jdGlvblxuICAgKiBAcGFyYW0gZm4gTGFtYmRhIGZ1bmN0aW9uIHRvIGFkZCB0aGUgbGF5ZXIgdG9cbiAgICogQHBhcmFtIG1hc2tpbmdDb25maWcgT3B0aW9uYWwgbWFza2luZyBjb25maWd1cmF0aW9uIHRvIGFkZCBhcyBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgKi9cbiAgcHVibGljIGFkZFRvRnVuY3Rpb24oZm46IGxhbWJkYS5GdW5jdGlvbiwgbWFza2luZ0NvbmZpZz86IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPik6IHZvaWQge1xuICAgIC8vIEFkZCB0aGUgbGF5ZXIgdG8gdGhlIGZ1bmN0aW9uXG4gICAgZm4uYWRkTGF5ZXJzKHRoaXMubGF5ZXIpO1xuXG4gICAgLy8gQWRkIG1hc2tpbmcgY29uZmlndXJhdGlvbiBpZiBwcm92aWRlZFxuICAgIGlmIChtYXNraW5nQ29uZmlnKSB7XG4gICAgICBmbi5hZGRFbnZpcm9ubWVudCgnTUFTS0lOR19DT05GSUcnLCBKU09OLnN0cmluZ2lmeShtYXNraW5nQ29uZmlnKSk7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,88 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import * as path from 'path';
5
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
6
+ import { Construct } from 'constructs';
7
+
8
+ /**
9
+ * Properties for the DataMaskingLayerConstruct
10
+ */
11
+ export interface DataMaskingLayerProps {
12
+ /**
13
+ * Description for the Lambda layer
14
+ * @default 'Lambda layer for masking sensitive data in document processing'
15
+ */
16
+ description?: string;
17
+
18
+ /**
19
+ * Custom masking patterns to add to the default ones
20
+ * @default {}
21
+ */
22
+ customPatterns?: Record<string, {
23
+ /**
24
+ * Regular expression pattern as string
25
+ */
26
+ regex: string;
27
+
28
+ /**
29
+ * Mask to apply (string or function name)
30
+ */
31
+ mask: string;
32
+ }>;
33
+ }
34
+
35
+ /**
36
+ * Construct that creates a Lambda layer for data masking
37
+ */
38
+ export class DataMaskingLayerConstruct extends Construct {
39
+ /**
40
+ * The Lambda layer containing masking utilities
41
+ */
42
+ public readonly layer: lambda.LayerVersion;
43
+
44
+ constructor(scope: Construct, id: string, props: DataMaskingLayerProps = {}) {
45
+ super(scope, id);
46
+
47
+ // Create the Lambda layer
48
+ this.layer = new lambda.LayerVersion(this, 'DataMaskingLayer', {
49
+ code: lambda.Code.fromAsset(path.join(__dirname, '../../../utilities/lambda_layers/data-masking')),
50
+ compatibleRuntimes: [
51
+ lambda.Runtime.NODEJS_16_X,
52
+ lambda.Runtime.NODEJS_18_X,
53
+ lambda.Runtime.NODEJS_20_X,
54
+ ],
55
+ description: props.description || 'Lambda layer for masking sensitive data',
56
+ license: 'Apache-2.0',
57
+ });
58
+
59
+ // Add metadata about available masking patterns
60
+ const defaultPatterns = [
61
+ 'nric', 'ssn', 'creditCard', 'email', 'phone', 'passport',
62
+ ];
63
+
64
+ // Add custom patterns if provided
65
+ const allPatterns = [...defaultPatterns];
66
+ if (props.customPatterns) {
67
+ allPatterns.push(...Object.keys(props.customPatterns));
68
+ }
69
+
70
+ // Add metadata to the construct
71
+ this.node.addMetadata('maskingPatterns', allPatterns.join(', '));
72
+ }
73
+
74
+ /**
75
+ * Adds the masking layer to a Lambda function
76
+ * @param fn Lambda function to add the layer to
77
+ * @param maskingConfig Optional masking configuration to add as environment variable
78
+ */
79
+ public addToFunction(fn: lambda.Function, maskingConfig?: Record<string, string[]>): void {
80
+ // Add the layer to the function
81
+ fn.addLayers(this.layer);
82
+
83
+ // Add masking configuration if provided
84
+ if (maskingConfig) {
85
+ fn.addEnvironment('MASKING_CONFIG', JSON.stringify(maskingConfig));
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,18 @@
1
+ import { RemovalPolicy } from 'aws-cdk-lib';
2
+ import { Role } from 'aws-cdk-lib/aws-iam';
3
+ import { Key } from 'aws-cdk-lib/aws-kms';
4
+ import { LogGroup } from 'aws-cdk-lib/aws-logs';
5
+ import { Construct } from 'constructs';
6
+ import { LogGroupDataProtectionProps } from './log-group-data-protection-props';
7
+ export interface BedrockObservabilityProps {
8
+ readonly logGroupDataProtection?: LogGroupDataProtectionProps;
9
+ readonly loggingRole?: Role;
10
+ readonly overrideExistingConfiguration?: boolean;
11
+ readonly removalPolicy?: RemovalPolicy;
12
+ }
13
+ export declare class BedrockObservability extends Construct {
14
+ readonly logGroup: LogGroup;
15
+ readonly loggingRole: Role;
16
+ readonly encryptionKey: Key;
17
+ constructor(scope: Construct, id: string, props?: BedrockObservabilityProps);
18
+ }