@trautonen/cdk-dns-validated-certificate 0.1.39 → 0.1.41
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.
- package/.jsii +4 -4
- package/README.md +288 -47
- package/lib/dns-validated-certificate.js +1 -1
- package/package.json +3 -3
package/.jsii
CHANGED
|
@@ -3465,7 +3465,7 @@
|
|
|
3465
3465
|
"stability": "stable"
|
|
3466
3466
|
},
|
|
3467
3467
|
"homepage": "https://github.com/trautonen/cdk-dns-validated-certificate.git",
|
|
3468
|
-
"jsiiVersion": "5.
|
|
3468
|
+
"jsiiVersion": "5.9.32 (build ac92fbd)",
|
|
3469
3469
|
"keywords": [
|
|
3470
3470
|
"aws",
|
|
3471
3471
|
"cdk",
|
|
@@ -3485,7 +3485,7 @@
|
|
|
3485
3485
|
},
|
|
3486
3486
|
"name": "@trautonen/cdk-dns-validated-certificate",
|
|
3487
3487
|
"readme": {
|
|
3488
|
-
"markdown": "# AWS CDK DNS Validated Certificate\n\nCDK does not have a built in construct to manage cross-region or cross-account DNS validated certificates. There's an\nattempt to work around the issue with a cross region references option for stacks, but it has a lot of issues and still\ndoes not solve the cross-account use case.\n\nThis construct solves these problems by managing the certificate as a custom resource and with direct API calls to ACM\nand Route53. In the future it will be possible to support not only Route53, but other DNS services too.\n\n## Usage for cross-region validation\n\n```typescript\n// hosted zone managed by the CDK application\nconst hostedZone: route53.IHostedZone = ...\n// no separate validation role is needed\nconst certificate = new DnsValidatedCertificate(this, 'CrossRegionCertificate', {\n hostedZone: hostedZone,\n domainName: 'example.com', // must be compatible with the hosted zone\n certificateRegion: 'us-east-1' // used by for example CloudFront\n})\n```\n\n## Usage for cross-account validation\n\n```typescript\n// external hosted zone\nconst hostedZone: route53.IHostedZone = route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {\n hostedZoneId: 'Z532DGDEDFS123456789',\n zoneName: 'example.com',\n})\n// validation role on the same account as the hosted zone\nconst roleArn = 'arn:aws:iam::123456789:role/ChangeDnsRecordsRole'\nconst externalId = 'domain-assume'\nconst validationRole: iam.IRole = iam.Role.fromRoleArn(this, 'ValidationRole', roleArn)\nconst certificate = new DnsValidatedCertificate(this, 'CrossAccountCertificate', {\n hostedZone: hostedZone,\n domainName: 'example.com',\n validationRole: validationRole,\n validationExternalId: externalId,\n})\n```\n\n## Usage for cross-account alternative names validation\n\n```typescript\n// example.com is validated on same account against managed hosted zone\n// and secondary.com is validated against external hosted zone on other account\nconst hostedZoneForMain: route53.IHostedZone = ...\nconst hostedZoneForAlternative: route53.IHostedZone =\n route53.HostedZone.fromHostedZoneAttributes(this, 'SecondaryHostedZone', {\n hostedZoneId: 'Z532DGDEDFS123456789',\n zoneName: 'secondary.com'\n})\nconst certificate = new DnsValidatedCertificate(this, 'CrossAccountCertificate', {\n domainName: 'example.com',\n alternativeDomainNames: ['secondary.com'],\n validationHostedZones: [{\n hostedZone: hostedZoneForMain\n },{\n hostedZone: hostedZoneForAlternative,\n validationRole: iam.Role.fromRoleArn(\n this, 'SecondaryValidationRole', 'arn:aws:iam::123456789:role/ChangeDnsRecordsRole'\n ),\n validationExternalId: 'domain-assume'\n }]\n})\n```\n"
|
|
3488
|
+
"markdown": "# @trautonen/cdk-dns-validated-certificate\n\n[](https://www.npmjs.com/package/@trautonen/cdk-dns-validated-certificate)\n[](https://www.npmjs.com/package/@trautonen/cdk-dns-validated-certificate)\n[](https://github.com/trautonen/cdk-dns-validated-certificate/blob/main/LICENSE)\n[](https://github.com/trautonen/cdk-dns-validated-certificate/actions/workflows/release.yml)\n\nAn AWS CDK construct for creating DNS-validated ACM certificates with **cross-region** and **cross-account** support.\n\nThe built-in CDK `Certificate` construct does not support cross-region or cross-account DNS validation. The cross-region references workaround has known issues and still does not cover cross-account use cases. This construct solves both problems by managing the full certificate lifecycle — request, DNS validation, and cleanup — through a Lambda-backed custom resource with direct API calls to ACM and Route 53.\n\n## Features\n\n- **Cross-region certificates** — provision a certificate in `us-east-1` for CloudFront while your stack is in any other region\n- **Cross-account validation** — validate against a Route 53 hosted zone in a different AWS account using IAM role assumption\n- **Multiple hosted zones** — validate a primary domain and alternative names against different hosted zones, each with its own credentials\n- **Automatic DNS record management** — creates and cleans up CNAME validation records automatically\n- **Certificate Transparency logging** — configurable CT logging\n- **Tagging support** — tag your certificates via CDK's standard tagging mechanism\n- **Configurable removal policy** — retain certificates on stack deletion if needed\n\n## Installation\n\n```bash\n# npm\nnpm install @trautonen/cdk-dns-validated-certificate\n\n# yarn\nyarn add @trautonen/cdk-dns-validated-certificate\n\n# pnpm\npnpm add @trautonen/cdk-dns-validated-certificate\n\n# bun\nbun add @trautonen/cdk-dns-validated-certificate\n```\n\n### Peer Dependencies\n\nThis construct requires the following peer dependencies:\n\n| Package | Version |\n|---|---|\n| `aws-cdk-lib` | `>= 2.83.1` |\n| `constructs` | `>= 10.5.1` |\n\n## Quick Start\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n validationHostedZones: [{\n hostedZone,\n }],\n});\n```\n\n## Usage\n\n### Cross-Region Certificate\n\nA common scenario is provisioning a certificate in `us-east-1` for CloudFront while the CDK stack deploys to another region. Use the `certificateRegion` property to specify where the certificate should be created.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\nimport * as cloudfront from 'aws-cdk-lib/aws-cloudfront';\nimport * as origins from 'aws-cdk-lib/aws-cloudfront-origins';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\n\nconst myBucket = new s3.Bucket(this, 'WebsiteBucket');\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\n// Create the certificate in us-east-1 regardless of the stack's region\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n certificateRegion: 'us-east-1',\n validationHostedZones: [{\n hostedZone,\n }],\n});\n\n// Use with a CloudFront distribution\nconst distribution = new cloudfront.Distribution(this, 'Distribution', {\n domainNames: ['example.com'],\n certificate,\n defaultBehavior: {\n origin: new origins.S3Origin(myBucket),\n },\n});\n```\n\n### Cross-Account Validation\n\nWhen the Route 53 hosted zone is in a different AWS account, provide an IAM role that the construct can assume to create DNS validation records in the target account. Optionally, use an external ID for additional security.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\nimport * as iam from 'aws-cdk-lib/aws-iam';\n\n// Reference the hosted zone in the other account\nconst hostedZone = route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {\n hostedZoneId: 'Z0123456789ABCDEFGHIJ',\n zoneName: 'example.com',\n});\n\n// IAM role in the DNS account that permits Route 53 changes\nconst validationRole = iam.Role.fromRoleArn(\n this, 'ValidationRole',\n 'arn:aws:iam::111111111111:role/DnsValidationRole',\n);\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n validationHostedZones: [{\n hostedZone,\n validationRole,\n validationExternalId: 'my-external-id', // optional\n }],\n});\n```\n\n> **Note:** The role in the DNS account must trust the account running the CDK stack and have permissions to call `route53:ChangeResourceRecordSets` and `route53:GetChange`.\n\n### Multiple Hosted Zones with Alternative Names\n\nValidate a primary domain and subject alternative names (SANs) against different hosted zones, each with independent credentials. This is useful when your primary domain and alternative domains are managed in separate AWS accounts.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\nimport * as iam from 'aws-cdk-lib/aws-iam';\n\n// Primary domain — hosted zone in the current account\nconst primaryZone = route53.HostedZone.fromLookup(this, 'PrimaryZone', {\n domainName: 'example.com',\n});\n\n// Alternative domain — hosted zone in a different account\nconst secondaryZone = route53.HostedZone.fromHostedZoneAttributes(this, 'SecondaryZone', {\n hostedZoneId: 'Z0123456789ABCDEFGHIJ',\n zoneName: 'example.org',\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n alternativeDomainNames: ['example.org'],\n certificateRegion: 'us-east-1',\n validationHostedZones: [{\n hostedZone: primaryZone,\n // No role needed — same account\n }, {\n hostedZone: secondaryZone,\n validationRole: iam.Role.fromRoleArn(\n this, 'SecondaryValidationRole',\n 'arn:aws:iam::222222222222:role/DnsValidationRole',\n ),\n validationExternalId: 'secondary-external-id',\n }],\n});\n```\n\n### Wildcard Certificate\n\nRequest a wildcard certificate that covers both the apex and all subdomains.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'WildcardCertificate', {\n domainName: 'example.com',\n alternativeDomainNames: ['*.example.com'],\n validationHostedZones: [{\n hostedZone,\n }],\n});\n```\n\n### Configuring Removal Policy\n\nBy default, certificates are destroyed when the stack is deleted. Set a removal policy to retain the certificate instead.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as cdk from 'aws-cdk-lib';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n validationHostedZones: [{ hostedZone }],\n removalPolicy: cdk.RemovalPolicy.RETAIN,\n});\n```\n\n### Disabling DNS Record Cleanup\n\nBy default, validation CNAME records are removed when the certificate is deleted. To keep them in DNS (useful for faster re-provisioning), set `cleanupValidationRecords` to `false`.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n validationHostedZones: [{ hostedZone }],\n cleanupValidationRecords: false,\n});\n```\n\n### Using a Custom Lambda Execution Role\n\nProvide your own IAM role for the Lambda function that manages the certificate lifecycle. This is useful when you need fine-grained control over permissions or want to use a shared role.\n\n```typescript\nimport { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';\nimport * as iam from 'aws-cdk-lib/aws-iam';\nimport * as route53 from 'aws-cdk-lib/aws-route53';\n\nconst hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {\n domainName: 'example.com',\n});\n\nconst lambdaRole = new iam.Role(this, 'CertificateLambdaRole', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n managedPolicies: [\n iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),\n ],\n});\n\nconst certificate = new DnsValidatedCertificate(this, 'Certificate', {\n domainName: 'example.com',\n validationHostedZones: [{ hostedZone }],\n customResourceRole: lambdaRole,\n});\n```\n\n## API Reference\n\n### `DnsValidatedCertificate`\n\n| Property | Type | Description |\n|---|---|---|\n| `certificateArn` | `string` | The ARN of the certificate |\n| `certificateRegion` | `string` | The region the certificate is deployed to |\n| `tags` | `TagManager` | Tag manager for the certificate |\n\n### `DnsValidatedCertificateProps`\n\n| Property | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `domainName` | `string` | Yes | — | Fully qualified domain name. May contain a wildcard (`*.example.com`). |\n| `validationHostedZones` | `ValidationHostedZone[]` | Yes | — | Route 53 hosted zones to use for DNS validation. |\n| `alternativeDomainNames` | `string[]` | No | — | Subject Alternative Names (SANs) for the certificate. |\n| `certificateRegion` | `string` | No | Stack region | Region for the certificate (e.g. `us-east-1` for CloudFront). |\n| `customResourceRole` | `IRole` | No | Auto-created | IAM role for the Lambda custom resource. |\n| `cleanupValidationRecords` | `boolean` | No | `true` | Remove DNS validation records on certificate deletion. |\n| `transparencyLoggingEnabled` | `boolean` | No | `true` | Enable Certificate Transparency logging. |\n| `removalPolicy` | `RemovalPolicy` | No | `DESTROY` | What to do with the certificate when the stack is deleted. |\n\n### `ValidationHostedZone`\n\n| Property | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `hostedZone` | `IHostedZone` | Yes | — | The Route 53 hosted zone for DNS validation. |\n| `validationRole` | `IRole` | No | — | IAM role to assume for cross-account DNS changes. |\n| `validationExternalId` | `string` | No | — | External ID for the role assumption. |\n\nFor the full API reference, see [API.md](API.md).\n\n## How It Works\n\nThe construct deploys a Lambda function (Node.js 22.x, ARM64) as a CloudFormation custom resource that:\n\n1. **Requests** a DNS-validated certificate from ACM\n2. **Creates** CNAME validation records in the specified Route 53 hosted zones (assuming cross-account roles when needed)\n3. **Waits** for ACM to validate the certificate\n4. **Applies** tags to the certificate\n5. **Cleans up** validation records and deletes the certificate on stack removal\n\nThe Lambda function handles the full lifecycle including updates (detecting when a new certificate is needed vs. a tag-only update) and graceful deletion (waiting for the certificate to stop being in-use before deleting).\n\n## License\n\n[Apache-2.0](LICENSE)\n"
|
|
3489
3489
|
},
|
|
3490
3490
|
"repository": {
|
|
3491
3491
|
"type": "git",
|
|
@@ -3921,6 +3921,6 @@
|
|
|
3921
3921
|
"symbolId": "src/dns-validated-certificate:ValidationHostedZone"
|
|
3922
3922
|
}
|
|
3923
3923
|
},
|
|
3924
|
-
"version": "0.1.
|
|
3925
|
-
"fingerprint": "
|
|
3924
|
+
"version": "0.1.41",
|
|
3925
|
+
"fingerprint": "8UKvOSI61xK0XIkClXpyOghMN/QKKHrwwCNIKmQAtRk="
|
|
3926
3926
|
}
|
package/README.md
CHANGED
|
@@ -1,67 +1,308 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @trautonen/cdk-dns-validated-certificate
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@trautonen/cdk-dns-validated-certificate)
|
|
4
|
+
[](https://www.npmjs.com/package/@trautonen/cdk-dns-validated-certificate)
|
|
5
|
+
[](https://github.com/trautonen/cdk-dns-validated-certificate/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/trautonen/cdk-dns-validated-certificate/actions/workflows/release.yml)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
and Route53. In the future it will be possible to support not only Route53, but other DNS services too.
|
|
8
|
+
An AWS CDK construct for creating DNS-validated ACM certificates with **cross-region** and **cross-account** support.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
The built-in CDK `Certificate` construct does not support cross-region or cross-account DNS validation. The cross-region references workaround has known issues and still does not cover cross-account use cases. This construct solves both problems by managing the full certificate lifecycle — request, DNS validation, and cleanup — through a Lambda-backed custom resource with direct API calls to ACM and Route 53.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Cross-region certificates** — provision a certificate in `us-east-1` for CloudFront while your stack is in any other region
|
|
15
|
+
- **Cross-account validation** — validate against a Route 53 hosted zone in a different AWS account using IAM role assumption
|
|
16
|
+
- **Multiple hosted zones** — validate a primary domain and alternative names against different hosted zones, each with its own credentials
|
|
17
|
+
- **Automatic DNS record management** — creates and cleans up CNAME validation records automatically
|
|
18
|
+
- **Certificate Transparency logging** — configurable CT logging
|
|
19
|
+
- **Tagging support** — tag your certificates via CDK's standard tagging mechanism
|
|
20
|
+
- **Configurable removal policy** — retain certificates on stack deletion if needed
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# npm
|
|
26
|
+
npm install @trautonen/cdk-dns-validated-certificate
|
|
27
|
+
|
|
28
|
+
# yarn
|
|
29
|
+
yarn add @trautonen/cdk-dns-validated-certificate
|
|
30
|
+
|
|
31
|
+
# pnpm
|
|
32
|
+
pnpm add @trautonen/cdk-dns-validated-certificate
|
|
33
|
+
|
|
34
|
+
# bun
|
|
35
|
+
bun add @trautonen/cdk-dns-validated-certificate
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Peer Dependencies
|
|
39
|
+
|
|
40
|
+
This construct requires the following peer dependencies:
|
|
41
|
+
|
|
42
|
+
| Package | Version |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `aws-cdk-lib` | `>= 2.83.1` |
|
|
45
|
+
| `constructs` | `>= 10.5.1` |
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
11
48
|
|
|
12
49
|
```typescript
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
50
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
51
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
52
|
+
|
|
53
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
54
|
+
domainName: 'example.com',
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
58
|
+
domainName: 'example.com',
|
|
59
|
+
validationHostedZones: [{
|
|
60
|
+
hostedZone,
|
|
61
|
+
}],
|
|
62
|
+
});
|
|
21
63
|
```
|
|
22
64
|
|
|
23
|
-
## Usage
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
### Cross-Region Certificate
|
|
68
|
+
|
|
69
|
+
A common scenario is provisioning a certificate in `us-east-1` for CloudFront while the CDK stack deploys to another region. Use the `certificateRegion` property to specify where the certificate should be created.
|
|
24
70
|
|
|
25
71
|
```typescript
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
72
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
73
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
74
|
+
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
|
|
75
|
+
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
|
|
76
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
77
|
+
|
|
78
|
+
const myBucket = new s3.Bucket(this, 'WebsiteBucket');
|
|
79
|
+
|
|
80
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
81
|
+
domainName: 'example.com',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Create the certificate in us-east-1 regardless of the stack's region
|
|
85
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
86
|
+
domainName: 'example.com',
|
|
87
|
+
certificateRegion: 'us-east-1',
|
|
88
|
+
validationHostedZones: [{
|
|
89
|
+
hostedZone,
|
|
90
|
+
}],
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Use with a CloudFront distribution
|
|
94
|
+
const distribution = new cloudfront.Distribution(this, 'Distribution', {
|
|
95
|
+
domainNames: ['example.com'],
|
|
96
|
+
certificate,
|
|
97
|
+
defaultBehavior: {
|
|
98
|
+
origin: new origins.S3Origin(myBucket),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Cross-Account Validation
|
|
104
|
+
|
|
105
|
+
When the Route 53 hosted zone is in a different AWS account, provide an IAM role that the construct can assume to create DNS validation records in the target account. Optionally, use an external ID for additional security.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
109
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
110
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
111
|
+
|
|
112
|
+
// Reference the hosted zone in the other account
|
|
113
|
+
const hostedZone = route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
|
|
114
|
+
hostedZoneId: 'Z0123456789ABCDEFGHIJ',
|
|
29
115
|
zoneName: 'example.com',
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// IAM role in the DNS account that permits Route 53 changes
|
|
119
|
+
const validationRole = iam.Role.fromRoleArn(
|
|
120
|
+
this, 'ValidationRole',
|
|
121
|
+
'arn:aws:iam::111111111111:role/DnsValidationRole',
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
37
125
|
domainName: 'example.com',
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
126
|
+
validationHostedZones: [{
|
|
127
|
+
hostedZone,
|
|
128
|
+
validationRole,
|
|
129
|
+
validationExternalId: 'my-external-id', // optional
|
|
130
|
+
}],
|
|
131
|
+
});
|
|
41
132
|
```
|
|
42
133
|
|
|
43
|
-
|
|
134
|
+
> **Note:** The role in the DNS account must trust the account running the CDK stack and have permissions to call `route53:ChangeResourceRecordSets` and `route53:GetChange`.
|
|
135
|
+
|
|
136
|
+
### Multiple Hosted Zones with Alternative Names
|
|
137
|
+
|
|
138
|
+
Validate a primary domain and subject alternative names (SANs) against different hosted zones, each with independent credentials. This is useful when your primary domain and alternative domains are managed in separate AWS accounts.
|
|
44
139
|
|
|
45
140
|
```typescript
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
54
|
-
|
|
141
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
142
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
143
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
144
|
+
|
|
145
|
+
// Primary domain — hosted zone in the current account
|
|
146
|
+
const primaryZone = route53.HostedZone.fromLookup(this, 'PrimaryZone', {
|
|
147
|
+
domainName: 'example.com',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Alternative domain — hosted zone in a different account
|
|
151
|
+
const secondaryZone = route53.HostedZone.fromHostedZoneAttributes(this, 'SecondaryZone', {
|
|
152
|
+
hostedZoneId: 'Z0123456789ABCDEFGHIJ',
|
|
153
|
+
zoneName: 'example.org',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
55
157
|
domainName: 'example.com',
|
|
56
|
-
alternativeDomainNames: ['
|
|
158
|
+
alternativeDomainNames: ['example.org'],
|
|
159
|
+
certificateRegion: 'us-east-1',
|
|
57
160
|
validationHostedZones: [{
|
|
58
|
-
hostedZone:
|
|
59
|
-
|
|
60
|
-
|
|
161
|
+
hostedZone: primaryZone,
|
|
162
|
+
// No role needed — same account
|
|
163
|
+
}, {
|
|
164
|
+
hostedZone: secondaryZone,
|
|
61
165
|
validationRole: iam.Role.fromRoleArn(
|
|
62
|
-
this, 'SecondaryValidationRole',
|
|
166
|
+
this, 'SecondaryValidationRole',
|
|
167
|
+
'arn:aws:iam::222222222222:role/DnsValidationRole',
|
|
63
168
|
),
|
|
64
|
-
validationExternalId: '
|
|
65
|
-
}]
|
|
66
|
-
})
|
|
169
|
+
validationExternalId: 'secondary-external-id',
|
|
170
|
+
}],
|
|
171
|
+
});
|
|
67
172
|
```
|
|
173
|
+
|
|
174
|
+
### Wildcard Certificate
|
|
175
|
+
|
|
176
|
+
Request a wildcard certificate that covers both the apex and all subdomains.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
180
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
181
|
+
|
|
182
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
183
|
+
domainName: 'example.com',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const certificate = new DnsValidatedCertificate(this, 'WildcardCertificate', {
|
|
187
|
+
domainName: 'example.com',
|
|
188
|
+
alternativeDomainNames: ['*.example.com'],
|
|
189
|
+
validationHostedZones: [{
|
|
190
|
+
hostedZone,
|
|
191
|
+
}],
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Configuring Removal Policy
|
|
196
|
+
|
|
197
|
+
By default, certificates are destroyed when the stack is deleted. Set a removal policy to retain the certificate instead.
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
201
|
+
import * as cdk from 'aws-cdk-lib';
|
|
202
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
203
|
+
|
|
204
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
205
|
+
domainName: 'example.com',
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
209
|
+
domainName: 'example.com',
|
|
210
|
+
validationHostedZones: [{ hostedZone }],
|
|
211
|
+
removalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Disabling DNS Record Cleanup
|
|
216
|
+
|
|
217
|
+
By default, validation CNAME records are removed when the certificate is deleted. To keep them in DNS (useful for faster re-provisioning), set `cleanupValidationRecords` to `false`.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
221
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
222
|
+
|
|
223
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
224
|
+
domainName: 'example.com',
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
228
|
+
domainName: 'example.com',
|
|
229
|
+
validationHostedZones: [{ hostedZone }],
|
|
230
|
+
cleanupValidationRecords: false,
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Using a Custom Lambda Execution Role
|
|
235
|
+
|
|
236
|
+
Provide your own IAM role for the Lambda function that manages the certificate lifecycle. This is useful when you need fine-grained control over permissions or want to use a shared role.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { DnsValidatedCertificate } from '@trautonen/cdk-dns-validated-certificate';
|
|
240
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
241
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
242
|
+
|
|
243
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
244
|
+
domainName: 'example.com',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const lambdaRole = new iam.Role(this, 'CertificateLambdaRole', {
|
|
248
|
+
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
|
|
249
|
+
managedPolicies: [
|
|
250
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
|
|
251
|
+
],
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
|
|
255
|
+
domainName: 'example.com',
|
|
256
|
+
validationHostedZones: [{ hostedZone }],
|
|
257
|
+
customResourceRole: lambdaRole,
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## API Reference
|
|
262
|
+
|
|
263
|
+
### `DnsValidatedCertificate`
|
|
264
|
+
|
|
265
|
+
| Property | Type | Description |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `certificateArn` | `string` | The ARN of the certificate |
|
|
268
|
+
| `certificateRegion` | `string` | The region the certificate is deployed to |
|
|
269
|
+
| `tags` | `TagManager` | Tag manager for the certificate |
|
|
270
|
+
|
|
271
|
+
### `DnsValidatedCertificateProps`
|
|
272
|
+
|
|
273
|
+
| Property | Type | Required | Default | Description |
|
|
274
|
+
|---|---|---|---|---|
|
|
275
|
+
| `domainName` | `string` | Yes | — | Fully qualified domain name. May contain a wildcard (`*.example.com`). |
|
|
276
|
+
| `validationHostedZones` | `ValidationHostedZone[]` | Yes | — | Route 53 hosted zones to use for DNS validation. |
|
|
277
|
+
| `alternativeDomainNames` | `string[]` | No | — | Subject Alternative Names (SANs) for the certificate. |
|
|
278
|
+
| `certificateRegion` | `string` | No | Stack region | Region for the certificate (e.g. `us-east-1` for CloudFront). |
|
|
279
|
+
| `customResourceRole` | `IRole` | No | Auto-created | IAM role for the Lambda custom resource. |
|
|
280
|
+
| `cleanupValidationRecords` | `boolean` | No | `true` | Remove DNS validation records on certificate deletion. |
|
|
281
|
+
| `transparencyLoggingEnabled` | `boolean` | No | `true` | Enable Certificate Transparency logging. |
|
|
282
|
+
| `removalPolicy` | `RemovalPolicy` | No | `DESTROY` | What to do with the certificate when the stack is deleted. |
|
|
283
|
+
|
|
284
|
+
### `ValidationHostedZone`
|
|
285
|
+
|
|
286
|
+
| Property | Type | Required | Default | Description |
|
|
287
|
+
|---|---|---|---|---|
|
|
288
|
+
| `hostedZone` | `IHostedZone` | Yes | — | The Route 53 hosted zone for DNS validation. |
|
|
289
|
+
| `validationRole` | `IRole` | No | — | IAM role to assume for cross-account DNS changes. |
|
|
290
|
+
| `validationExternalId` | `string` | No | — | External ID for the role assumption. |
|
|
291
|
+
|
|
292
|
+
For the full API reference, see [API.md](API.md).
|
|
293
|
+
|
|
294
|
+
## How It Works
|
|
295
|
+
|
|
296
|
+
The construct deploys a Lambda function (Node.js 22.x, ARM64) as a CloudFormation custom resource that:
|
|
297
|
+
|
|
298
|
+
1. **Requests** a DNS-validated certificate from ACM
|
|
299
|
+
2. **Creates** CNAME validation records in the specified Route 53 hosted zones (assuming cross-account roles when needed)
|
|
300
|
+
3. **Waits** for ACM to validate the certificate
|
|
301
|
+
4. **Applies** tags to the certificate
|
|
302
|
+
5. **Cleans up** validation records and deletes the certificate on stack removal
|
|
303
|
+
|
|
304
|
+
The Lambda function handles the full lifecycle including updates (detecting when a new certificate is needed vs. a tag-only update) and graceful deletion (waiting for the certificate to stop being in-use before deleting).
|
|
305
|
+
|
|
306
|
+
## License
|
|
307
|
+
|
|
308
|
+
[Apache-2.0](LICENSE)
|
|
@@ -243,5 +243,5 @@ class DnsValidatedCertificate extends cdk.Resource {
|
|
|
243
243
|
}
|
|
244
244
|
exports.DnsValidatedCertificate = DnsValidatedCertificate;
|
|
245
245
|
_a = JSII_RTTI_SYMBOL_1;
|
|
246
|
-
DnsValidatedCertificate[_a] = { fqn: "@trautonen/cdk-dns-validated-certificate.DnsValidatedCertificate", version: "0.1.
|
|
246
|
+
DnsValidatedCertificate[_a] = { fqn: "@trautonen/cdk-dns-validated-certificate.DnsValidatedCertificate", version: "0.1.41" };
|
|
247
247
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zLXZhbGlkYXRlZC1jZXJ0aWZpY2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kbnMtdmFsaWRhdGVkLWNlcnRpZmljYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQWtDO0FBRWxDLHlEQUF3RDtBQUN4RCwyQ0FBMEM7QUFDMUMsaURBQWdEO0FBRWhELGlFQUFnRTtBQUVoRSxxRkFBK0U7QUFFL0UsbUNBQWdHO0FBaUhoRyxNQUFNLDhCQUE4QixHQUFHLGlDQUFpQyxDQUFBO0FBQ3hFLE1BQU0sMEJBQTBCLEdBQUcsc0NBQXNDLENBQUE7QUFFekU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUVHO0FBQ0gsTUFBYSx1QkFBd0IsU0FBUSxHQUFHLENBQUMsUUFBUTtJQWF2RDs7Ozs7O09BTUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQW1DO1FBQzNFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFFaEIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUM3RCxNQUFNLHNCQUFzQixHQUFHLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQ3pGLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUNoRCxDQUFBO1FBQ0QsTUFBTSxVQUFVLEdBQUcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUE7UUFFbEUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQTtRQUNyRSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FB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LE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUNoRSxNQUFNLG1CQUFtQixHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQTtZQUMzRixJQUFJLG9CQUFvQixJQUFJLG1CQUFtQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hILE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxVQUFVLGlEQUFpRCxDQUFDLENBQUE7WUFDcEYsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7O0FBcE5ILDBEQXFOQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYidcbmltcG9ydCAqIGFzIGNlcnRpZmljYXRlbWFuYWdlciBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyJ1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCdcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJ1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnXG5pbXBvcnQgKiBhcyByb3V0ZTUzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1yb3V0ZTUzJ1xuaW1wb3J0ICogYXMgY3VzdG9tX3Jlc291cmNlcyBmcm9tICdhd3MtY2RrLWxpYi9jdXN0b20tcmVzb3VyY2VzJ1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cydcbmltcG9ydCB7IENlcnRpZmljYXRlUmVxdWVzdG9yRnVuY3Rpb24gfSBmcm9tICcuL2NlcnRpZmljYXRlLXJlcXVlc3Rvci1mdW5jdGlvbidcbmltcG9ydCB7IFByb3BlcnRpZXMsIFZhbGlkYXRpb25Ib3N0ZWRab25lUHJvcGVydGllcyB9IGZyb20gJy4vY2VydGlmaWNhdGUtcmVxdWVzdG9yLmxhbWJkYSdcbmltcG9ydCB7IGJvb2xlYW5Ub1N0cmluZywgY2xlYW5Eb21haW5OYW1lLCBjbGVhbkhvc3RlZFpvbmVJZCwgbWF0Y2hOYW1lc1RvWm9uZXMgfSBmcm9tICcuL3V0aWxzJ1xuXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25Ib3N0ZWRab25lIHtcbiAgLyoqXG4gICAqIEhvc3RlZCB6b25lIHRvIHVzZSBmb3IgRE5TIHZhbGlkYXRpb24uIFRoZSB6b25lIG5hbWUgaXMgbWF0Y2hlZCB0byBkb21haW4gbmFtZSB0byB1c2UgdGhlIHJpZ2h0XG4gICAqIGhvc3RlZCB6b25lIGZvciB2YWxpZGF0aW9uLlxuICAgKlxuICAgKiBJZiB0aGUgaG9zdGVkIHpvbmUgaXMgbm90IG1hbmFnZWQgYnkgdGhlIENESyBhcHBsaWNhdGlvbiwgaXQgbmVlZHMgdG8gYmUgcHJvdmlkZWQgdmlhXG4gICAqIGBgSG9zdGVkWm9uZS5mcm9tSG9zdGVkWm9uZUF0dHJpYnV0ZXMoKWBgLlxuICAgKi9cbiAgcmVhZG9ubHkgaG9zdGVkWm9uZTogcm91dGU1My5JSG9zdGVkWm9uZVxuXG4gIC8qKlxuICAgKiBUaGUgcm9sZSB0aGF0IGlzIGFzc3VtZWQgZm9yIEROUyByZWNvcmQgY2hhbmdlcyBmb3IgY2VydGlmaWNhdGUgdmFsaWRhdGlvbi5cbiAgICpcbiAgICogVGhpcyByb2xlIHNob3VsZCBleGlzdCBpbiB0aGUgc2FtZSBhY2NvdW50IGFzIHRoZSBob3N0ZWQgem9uZSBhbmQgaW5jbHVkZSBwZXJtaXNzaW9ucyB0byBjaGFuZ2UgdGhlIEROUyByZWNvcmRzXG4gICAqIGZvciB0aGUgZ2l2ZW4gYGBob3N0ZWRab25lYGAuIFRoZSBgYGN1c3RvbVJlc291cmNlUm9sZWBgIG9yIHRoZSBkZWZhdWx0IGV4ZWN1dGlvbiByb2xlIGlzIGdpdmVuIHBlcm1pc3Npb24gdG9cbiAgICogYXNzdW1lIHRoaXMgcm9sZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzZXBhcmF0ZSByb2xlIGZvciBETlMgcmVjb3JkIGNoYW5nZXMuIFRoZSBnaXZlbiBjdXN0b21SZXNvdXJjZVJvbGUgb3IgdGhlIGRlZmF1bHQgcm9sZSBpcyB1c2VkXG4gICAqIGZvciBETlMgcmVjb3JkIGNoYW5nZXMuXG4gICAqL1xuICByZWFkb25seSB2YWxpZGF0aW9uUm9sZT86IGlhbS5JUm9sZVxuXG4gIC8qKlxuICAgKiBFeHRlcm5hbCBpZCBmb3IgYGB2YWxpZGF0aW9uUm9sZWBgIHJvbGUgYXNzdW1lIHZlcmlmaWNhdGlvbi5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgYmUgdXNlZCBvbmx5IHdoZW4gYGB2YWxpZGF0aW9uUm9sZWBgIGlzIGdpdmVuIGFuZCB0aGUgcm9sZSBleHBlY3RzIGFuIGV4dGVybmFsIGlkIHByb3ZpZGVkIG9uIGFzc3VtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBleHRlcm5hbCBpZCBwcm92aWRlZCBkdXJpbmcgYXNzdW1lLlxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRhdGlvbkV4dGVybmFsSWQ/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEbnNWYWxpZGF0ZWRDZXJ0aWZpY2F0ZVByb3BzIHtcbiAgLyoqXG4gICAqIEZ1bGx5LXF1YWxpZmllZCBkb21haW4gbmFtZSB0byByZXF1ZXN0IGEgY2VydGlmaWNhdGUgZm9yLlxuICAgKlxuICAgKiBNYXkgY29udGFpbiB3aWxkY2FyZHMsIHN1Y2ggYXMgYGAqLmRvbWFpbi5jb21gYC5cbiAgICovXG4gIHJlYWRvbmx5IGRvbWFpbk5hbWU6IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBGdWxseS1xdWFsaWZpZWQgYWx0ZXJuYXRpdmUgZG9tYWluIG5hbWVzIHRvIHJlcXVlc3QgYSBjZXJ0aWZpY2F0ZSBmb3IuXG4gICAqXG4gICAqIE1heSBjb250YWluIHdpbGRjYXJkcywgc3VjaCBhcyBgYCoub3RoZXJkb21haW4uY29tYGAuXG4gICAqL1xuICByZWFkb25seSBhbHRlcm5hdGl2ZURvbWFpbk5hbWVzPzogc3RyaW5nW11cblxuICAvKipcbiAgICogTGlzdCBvZiBob3N0ZWQgem9uZXMgdG8gdXNlIGZvciB2YWxpZGF0aW9uLiBIb3N0ZWQgem9uZXMgYXJlIG1hcHBlZCB0byBkb21haW4gbmFtZXMgYnkgdGhlIHpvbmUgbmFtZS5cbiAgICovXG4gIHJlYWRvbmx5IHZhbGlkYXRpb25Ib3N0ZWRab25lczogVmFsaWRhdGlvbkhvc3RlZFpvbmVbXVxuXG4gIC8qKlxuICAgKiBBV1MgcmVnaW9uIHdoZXJlIHRoZSBjZXJ0aWZpY2F0ZSBpcyBkZXBsb3llZC5cbiAgICpcbiAgICogWW91IHNob3VsZCB1c2UgdGhlIGRlZmF1bHQgYGBDZXJ0aWZpY2F0ZWBgIGNvbnN0cnVjdCBpbnN0ZWFkIGlmIHRoZSByZWdpb24gaXMgc2FtZSBhcyB0aGUgc3RhY2sncyBhbmQgdGhlIGhvc3RlZFxuICAgKiB6b25lIGlzIGluIHRoZSBzYW1lIGFjY291bnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2FtZSByZWdpb24gYXMgdGhlIHN0YWNrLlxuICAgKi9cbiAgcmVhZG9ubHkgY2VydGlmaWNhdGVSZWdpb24/OiBzdHJpbmdcblxuICAvKipcbiAgICogVGhlIHJvbGUgdGhhdCBpcyB1c2VkIGZvciB0aGUgY3VzdG9tIHJlc291cmNlIExhbWJkYSBleGVjdXRpb24uXG4gICAqXG4gICAqIFRoZSByb2xlIGlzIGdpdmVuIHBlcm1pc3Npb25zIHRvIHJlcXVlc3QgY2VydGlmaWNhdGVzIGZyb20gQUNNLiBJZiB0aGVyZSBhcmUgYW55IGBgdmFsaWRhdGlvblJvbGVgYHMgcHJvdmlkZWQsXG4gICAqIHRoaXMgcm9sZSBpcyBhbHNvIGdpdmVuIHBlcm1pc3Npb24gdG8gYXNzdW1lIHRoZSBgYHZhbGlkYXRpb25Sb2xlYGAuIE90aGVyd2lzZSBpdCBpcyBhc3N1bWVkIHRoYXQgdGhlIGhvc3RlZCB6b25lXG4gICAqIGlzIGluIHNhbWUgYWNjb3VudCBhbmQgdGhlIGV4ZWN1dGlvbiByb2xlIGlzIGdpdmVuIHBlcm1pc3Npb25zIHRvIGNoYW5nZSBETlMgcmVjb3JkcyBmb3IgdGhlIGdpdmVuIGBgZG9tYWluTmFtZWBgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIExhbWJkYSBjcmVhdGVzIGEgZGVmYXVsdCBleGVjdXRpb24gcm9sZS5cbiAgICovXG4gIHJlYWRvbmx5IGN1c3RvbVJlc291cmNlUm9sZT86IGlhbS5JUm9sZVxuXG4gIC8qKlxuICAgKiBFbmFibGUgb3IgZGlzYWJsZSBjbGVhbmluZyBvZiB2YWxpZGF0aW9uIEROUyByZWNvcmRzIGZyb20gdGhlIGhvc3RlZCB6b25lLlxuICAgKlxuICAgKiBJZiB0aGVyZSdzIG11bHRpcGxlIGNlcnRpZmljYXRlcyBjcmVhdGVkIGZvciBzYW1lIGRvbWFpbiwgaXQgaXMgcG9zc2libGUgdG8gZW5jb3V0ZXIgYSByYWNlIGNvbmRpdGlvbiB3aGVyZSBzb21lXG4gICAqIGNlcnRpZmljYXRlIGlzIHJlbW92ZWQgYW5kIGFub3RoZXIgY2VydGlmaWNhdGUgd291bGQgbmVlZCB0aGUgc2FtZSB2YWxpZGF0aW9uIHJlY29yZC4gUHJlZmVyIHNpbmdsZSBjZXJ0aWZpY2F0ZVxuICAgKiBmb3IgYSBkb21haW4gb3Igc2V0IHRoaXMgdG8gZmFsc2UgYW5kIGNsZWFudXAgcmVjb3JkcyBtYW51YWxseSB3aGVuIG5vdCBuZWVkZWQgYW55bW9yZS4gSWYgeW91IGNoYW5nZSB0aGlzXG4gICAqIHByb3BlcnR5IGFmdGVyIGNyZWF0aW9uLCBhIG5ldyBjZXJ0aWZpY2F0ZSB3aWxsIGJlIHJlcXVlc3RlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2xlYW51cFZhbGlkYXRpb25SZWNvcmRzPzogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBFbmFibGUgb3IgZGlzYWJsZSB0cmFuc3BhcmVuY3kgbG9nZ2luZyBmb3IgdGhpcyBjZXJ0aWZpY2F0ZS5cbiAgICpcbiAgICogT25jZSBhIGNlcnRpZmljYXRlIGhhcyBiZWVuIGxvZ2dlZCwgaXQgY2Fubm90IGJlIHJlbW92ZWQgZnJvbSB0aGUgbG9nLiBPcHRpbmcgb3V0IGF0IHRoYXQgcG9pbnQgd2lsbCBoYXZlIG5vXG4gICAqIGVmZmVjdC4gSWYgeW91IGNoYW5nZSB0aGlzIHByb3BlcnR5IGFmdGVyIGNyZWF0aW9uLCBhIG5ldyBjZXJ0aWZpY2F0ZSB3aWxsIGJlIHJlcXVlc3RlZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYWNtL2xhdGVzdC91c2VyZ3VpZGUvYWNtLWJlc3RwcmFjdGljZXMuaHRtbCNiZXN0LXByYWN0aWNlcy10cmFuc3BhcmVuY3lcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgdHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQ/OiBib29sZWFuXG5cbiAgLyoqXG4gICAqIEFwcGx5IHRoZSBnaXZlbiByZW1vdmFsIHBvbGljeSB0byB0aGlzIHJlc291cmNlLlxuICAgKlxuICAgKiBUaGUgcmVtb3ZhbCBwb2xpY3kgY29udHJvbHMgd2hhdCBoYXBwZW5zIHRvIHRoaXMgcmVzb3VyY2Ugd2hlbiBpdCBzdG9wcyBiZWluZyBtYW5hZ2VkIGJ5IENsb3VkRm9ybWF0aW9uLCBlaXRoZXJcbiAgICogYmVjYXVzZSB5b3UndmUgcmVtb3ZlZCBpdCBmcm9tIHRoZSBDREsgYXBwbGljYXRpb24gb3IgYmVjYXVzZSB5b3UndmUgbWFkZSBhIGNoYW5nZSB0aGF0IHJlcXVpcmVzIHRoZSByZXNvdXJjZSB0b1xuICAgKiBiZSByZXBsYWNlZC4gVGhlIHJlc291cmNlIGNhbiBiZSBkZWxldGVkIChgYFJlbW92YWxQb2xpY3kuREVTVFJPWWBgKSwgb3IgbGVmdCBpbiB5b3VyIEFXUyBhY2NvdW50IGZvciBkYXRhXG4gICAqIHJlY292ZXJ5IGFuZCBjbGVhbnVwIGxhdGVyIChgYFJlbW92YWxQb2xpY3kuUkVUQUlOYGApLiBJZiB5b3UgY2hhbmdlIHRoaXMgcHJvcGVydHkgYWZ0ZXIgY3JlYXRpb24sIGEgbmV3XG4gICAqIGNlcnRpZmljYXRlIHdpbGwgYmUgcmVxdWVzdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBSZW1vdmFsUG9saWN5LkRFU1RST1lcbiAgICovXG4gIHJlYWRvbmx5IHJlbW92YWxQb2xpY3k/OiBjZGsuUmVtb3ZhbFBvbGljeVxufVxuXG5jb25zdCBETlNfVkFMSURBVEVEX0NFUlRJRklDQVRFX1RZUEUgPSAnQ3VzdG9tOjpEbnNWYWxpZGF0ZWRDZXJ0aWZpY2F0ZSdcbmNvbnN0IENFUlRUSUZJQ0FURV9SRVNPVVJDRV9UWVBFID0gJ0FXUzo6Q2VydGlmaWNhdGVNYW5hZ2VyOjpDZXJ0aWZpY2F0ZSdcblxuLyoqXG4gKiBBIGNlcnRpZmljYXRlIG1hbmFnZWQgYnkgQVdTIENlcnRpZmljYXRlIE1hbmFnZXIuIFdpbGwgYmUgYXV0b21hdGljYWxseSB2YWxpZGF0ZWQgdXNpbmcgRE5TIHZhbGlkYXRpb24gYWdhaW5zdCB0aGVcbiAqIHNwZWNpZmllZCBSb3V0ZSA1MyBob3N0ZWQgem9uZS4gVGhpcyBjb25zdHJ1Y3Qgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgY3Jvc3MtcmVnaW9uIG9yIGNyb3NzLWFjY291bnQgY2VydGlmaWNhdGVcbiAqIHZhbGlkYXRpb25zLiBUaGUgZGVmYXVsdCBgYENlcnRpZmljYXRlYGAgY29uc3RydWN0IGlzIGJldHRlciBpbiBjYXNlcyB3aGVyZSBldmVyeXRoaW5nIGlzIG1hbmFnZWQgYnkgdGhlIENES1xuICogYXBwbGljYXRpb24uXG4gKlxuICogUGxlYXNlIG5vdGUgdGhhdCB0aGlzIGNvbnN0cnVjdCBkb2VzIG5vdCBzdXBwb3J0IGFsdGVybmF0aXZlIG5hbWVzIHlldCBhcyBpdCB3b3VsZCByZXF1aXJlIGRvbWFpbiB0byByb2xlIG1hcHBpbmcuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vICMjIyBDcm9zcy1yZWdpb24gY2VydGlmaWNhdGUgdmFsaWRhdGlvblxuICogLy8gaG9zdGVkIHpvbmUgbWFuYWdlZCBieSB0aGUgQ0RLIGFwcGxpY2F0aW9uXG4gKiBjb25zdCBob3N0ZWRab25lOiByb3V0ZTUzLklIb3N0ZWRab25lID0gLi4uXG4gKiAvLyBubyBzZXBhcmF0ZSB2YWxpZGF0aW9uIHJvbGUgaXMgbmVlZGVkXG4gKiBjb25zdCBjZXJ0aWZpY2F0ZSA9IG5ldyBEbnNWYWxpZGF0ZWRDZXJ0aWZpY2F0ZSh0aGlzLCAnQ3Jvc3NSZWdpb25DZXJ0aWZpY2F0ZScsIHtcbiAqICAgZG9tYWluTmFtZTogJ2V4YW1wbGUuY29tJywgICAgIC8vIG11c3QgYmUgY29tcGF0aWJsZSB3aXRoIHRoZSBob3N0ZWQgem9uZVxuICogICB2YWxpZGF0aW9uSG9zdGVkWm9uZXM6IFt7ICAgICAgLy8gaG9zdGVkIHpvbmUgdXNlZCB3aXRoIHRoZSBleGVjdXRpb24gcm9sZSdzIHBlcm1pc3Npb25zXG4gKiAgICAgaG9zdGVkWm9uZTogaG9zdGVkWm9uZVxuICogICB9XSxcbiAqICAgY2VydGlmaWNhdGVSZWdpb246ICd1cy1lYXN0LTEnIC8vIHVzZWQgYnkgZm9yIGV4YW1wbGUgQ2xvdWRGcm9udFxuICogfSlcbiAqIC8vICMjIyBDcm9zcy1hY2NvdW50IGNlcnRpZmljYXRlIHZhbGlkYXRpb25cbiAqIC8vIGV4dGVybmFsIGhvc3RlZCB6b25lXG4gKiBjb25zdCBob3N0ZWRab25lOiByb3V0ZTUzLklIb3N0ZWRab25lID1cbiAqICAgcm91dGU1My5Ib3N0ZWRab25lLmZyb21Ib3N0ZWRab25lQXR0cmlidXRlcyh0aGlzLCAnSG9zdGVkWm9uZScsIHtcbiAqICAgICBob3N0ZWRab25lSWQ6ICdaNTMyREdERURGUzEyMzQ1Njc4OScsXG4gKiAgICAgem9uZU5hbWU6ICdleGFtcGxlLmNvbSdcbiAqICAgfSlcbiAqIC8vIHZhbGlkYXRpb24gcm9sZSBpbiB0aGUgc2FtZSBhY2NvdW50IGFzIHRoZSBob3N0ZWQgem9uZVxuICogY29uc3Qgcm9sZUFybiA9ICdhcm46YXdzOmlhbTo6MTIzNDU2Nzg5OnJvbGUvQ2hhbmdlRG5zUmVjb3Jkc1JvbGUnXG4gKiBjb25zdCBleHRlcm5hbElkID0gJ2RvbWFpbi1hc3N1bWUnXG4gKiBjb25zdCB2YWxpZGF0aW9uUm9sZTogaWFtLklSb2xlID1cbiAqICAgaWFtLlJvbGUuZnJvbVJvbGVBcm4odGhpcywgJ1ZhbGlkYXRpb25Sb2xlJywgcm9sZUFybilcbiAqIGNvbnN0IGNlcnRpZmljYXRlID0gbmV3IERuc1ZhbGlkYXRlZENlcnRpZmljYXRlKHRoaXMsICdDcm9zc0FjY291bnRDZXJ0aWZpY2F0ZScsIHtcbiAqICAgZG9tYWluTmFtZTogJ2V4YW1wbGUuY29tJyxcbiAqICAgdmFsaWRhdGlvbkhvc3RlZFpvbmVzOiBbe1xuICogICAgIGhvc3RlZFpvbmU6IGhvc3RlZFpvbmUsXG4gKiAgICAgdmFsaWRhdGlvblJvbGU6IHZhbGlkYXRpb25Sb2xlLFxuICogICAgIHZhbGlkYXRpb25FeHRlcm5hbElkOiBleHRlcm5hbElkXG4gKiAgIH1dXG4gKiB9KVxuICogLy8gIyMjIENyb3NzLWFjY291bnQgYWx0ZXJuYXRpdmUgbmFtZSB2YWxpZGF0aW9uXG4gKiAvLyBleGFtcGxlLmNvbSBpcyB2YWxpZGF0ZWQgb24gc2FtZSBhY2NvdW50IGFnYWluc3QgbWFuYWdlZCBob3N0ZWQgem9uZVxuICogLy8gYW5kIHNlY29uZGFyeS5jb20gaXMgdmFsaWRhdGVkIGFnYWluc3QgZXh0ZXJuYWwgaG9zdGVkIHpvbmUgb24gb3RoZXIgYWNjb3VudFxuICogY29uc3QgaG9zdGVkWm9uZUZvck1haW46IHJvdXRlNTMuSUhvc3RlZFpvbmUgPSAuLi5cbiAqIGNvbnN0IGhvc3RlZFpvbmVGb3JBbHRlcm5hdGl2ZTogcm91dGU1My5JSG9zdGVkWm9uZSA9XG4gKiAgIHJvdXRlNTMuSG9zdGVkWm9uZS5mcm9tSG9zdGVkWm9uZUF0dHJpYnV0ZXModGhpcywgJ1NlY29uZGFyeUhvc3RlZFpvbmUnLCB7XG4gKiAgICAgaG9zdGVkWm9uZUlkOiAnWjUzMkRHREVERlMxMjM0NTY3ODknLFxuICogICAgIHpvbmVOYW1lOiAnc2Vjb25kYXJ5LmNvbSdcbiAqICAgfSlcbiAqIGNvbnN0IGNlcnRpZmljYXRlID0gbmV3IERuc1ZhbGlkYXRlZENlcnRpZmljYXRlKHRoaXMsICdDcm9zc0FjY291bnRDZXJ0aWZpY2F0ZScsIHtcbiAqICAgZG9tYWluTmFtZTogJ2V4YW1wbGUuY29tJyxcbiAqICAgYWx0ZXJuYXRpdmVEb21haW5OYW1lczogWydzZWNvbmRhcnkuY29tJ10sXG4gKiAgIHZhbGlkYXRpb25Ib3N0ZWRab25lczogW3tcbiAqICAgICBob3N0ZWRab25lOiBob3N0ZWRab25lRm9yTWFpblxuICogICB9LHtcbiAqICAgICBob3N0ZWRab25lOiBob3N0ZWRab25lRm9yQWx0ZXJuYXRpdmUsXG4gKiAgICAgdmFsaWRhdGlvblJvbGU6IGlhbS5Sb2xlLmZyb21Sb2xlQXJuKFxuICogICAgICAgdGhpcywgJ1NlY29uZGFyeVZhbGlkYXRpb25Sb2xlJywgJ2Fybjphd3M6aWFtOjoxMjM0NTY3ODk6cm9sZS9DaGFuZ2VEbnNSZWNvcmRzUm9sZSdcbiAqICAgICApLFxuICogICAgIHZhbGlkYXRpb25FeHRlcm5hbElkOiAnZG9tYWluLWFzc3VtZSdcbiAqICAgfV1cbiAqIH0pXG4gKlxuICogQHJlc291cmNlIEN1c3RvbTo6RG5zVmFsaWRhdGVkQ2VydGlmaWNhdGVcbiAqIEByZXNvdXJjZSBBV1M6OkNlcnRpZmljYXRlTWFuYWdlcjo6Q2VydGlmaWNhdGVcbiAqL1xuZXhwb3J0IGNsYXNzIERuc1ZhbGlkYXRlZENlcnRpZmljYXRlIGV4dGVuZHMgY2RrLlJlc291cmNlIGltcGxlbWVudHMgY2VydGlmaWNhdGVtYW5hZ2VyLklDZXJ0aWZpY2F0ZSwgY2RrLklUYWdnYWJsZSB7XG4gIC8qKiBUaGUgY2VydGlmaWNhdGUncyBBUk4gKi9cbiAgcHVibGljIHJlYWRvbmx5IGNlcnRpZmljYXRlQXJuOiBzdHJpbmdcblxuICAvKiogVGhlIHJlZ2lvbiB3aGVyZSB0aGUgY2VydGlmaWNhdGUgaXMgZGVwbG95ZWQgdG8gKi9cbiAgcHVibGljIHJlYWRvbmx5IGNlcnRpZmljYXRlUmVnaW9uOiBzdHJpbmdcblxuICAvKiogVGhlIHRhZyBtYW5hZ2VyIHRvIHNldCwgcmVtb3ZlIGFuZCBmb3JtYXQgdGFncyBmb3IgdGhlIGNlcnRpZmljYXRlICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFnczogY2RrLlRhZ01hbmFnZXJcblxuICAvKiogVGhlIHJlbW92YWwgcG9saWN5IGZvciB0aGUgY2VydGlmaWNhdGUgKi9cbiAgcHJpdmF0ZSByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIERuc1ZhbGlkYXRlZENlcnRpZmljYXRlIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIGNvbnN0cnVjdCBob3N0aW5nIHRoaXMgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCBjb25zdHJ1Y3QncyBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIGZvciB0aGUgY29uc3RydWN0XG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZClcblxuICAgIGNvbnN0IGRvbWFpbk5hbWUgPSB0aGlzLm5vcm1hbGl6ZURvbWFpbk5hbWUocHJvcHMuZG9tYWluTmFtZSlcbiAgICBjb25zdCBhbHRlcm5hdGl2ZURvbWFpbk5hbWVzID0gcHJvcHMuYWx0ZXJuYXRpdmVEb21haW5OYW1lcz8ubWFwKChhbHRlcm5hdGl2ZURvbWFpbk5hbWUpID0+XG4gICAgICB0aGlzLm5vcm1hbGl6ZURvbWFpbk5hbWUoYWx0ZXJuYXRpdmVEb21haW5OYW1lKVxuICAgIClcbiAgICBjb25zdCBhbGxEb21haW5zID0gW2RvbWFpbk5hbWUsIC4uLihhbHRlcm5hdGl2ZURvbWFpbk5hbWVzID8/IFtdKV1cblxuICAgIHRoaXMuY2VydGlmaWNhdGVSZWdpb24gPSBwcm9wcy5jZXJ0aWZpY2F0ZVJlZ2lvbiA/PyB0aGlzLnN0YWNrLnJlZ2lvblxuICAgIHRoaXMudGFncyA9IG5ldyBjZGsuVGFnTWFuYWdlcihjZGsuVGFnVHlwZS5NQVAsIENFUlRUSUZJQ0FURV9SRVNPVVJDRV9UWVBFKVxuICAgIHRoaXMucmVtb3ZhbFBvbGljeSA9IHByb3BzLnJlbW92YWxQb2xpY3kgPz8gY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWVxuXG4gICAgY29uc3QgcmVxdWVzdG9yRnVuY3Rpb24gPSBuZXcgQ2VydGlmaWNhdGVSZXF1ZXN0b3JGdW5jdGlvbih0aGlzLCAnUmVxdWVzdG9yRnVuY3Rpb24nLCB7XG4gICAgICBhcmNoaXRlY3R1cmU6IGxhbWJkYS5BcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLm1pbnV0ZXMoMTQpLFxuICAgICAgcm9sZTogcHJvcHMuY3VzdG9tUmVzb3VyY2VSb2xlLFxuICAgIH0pXG5cbiAgICByZXF1ZXN0b3JGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICdhY206UmVxdWVzdENlcnRpZmljYXRlJyxcbiAgICAgICAgICAnYWNtOkRlc2NyaWJlQ2VydGlmaWNhdGUnLFxuICAgICAgICAgICdhY206RGVsZXRlQ2VydGlmaWNhdGUnLFxuICAgICAgICAgICdhY206QWRkVGFnc1RvQ2VydGlmaWNhdGUnLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSlcbiAgICApXG5cbiAgICBjb25zdCBkb21haW5zVG9ab25lcyA9IG1hdGNoTmFtZXNUb1pvbmVzKFxuICAgICAgcHJvcHMudmFsaWRhdGlvbkhvc3RlZFpvbmVzLm1hcCgoem9uZSkgPT4gem9uZS5ob3N0ZWRab25lLnpvbmVOYW1lKSxcbiAgICAgIGFsbERvbWFpbnMsXG4gICAgICAoZG9tYWluKSA9PiBkb21haW5cbiAgICApXG4gICAgY29uc3QgaG9zdGVkWm9uZXNXaXRoUm9sZSA9IHByb3BzLnZhbGlkYXRpb25Ib3N0ZWRab25lcy5maWx0ZXIoKHpvbmUpID0+IHpvbmUudmFsaWRhdGlvblJvbGUgIT09IHVuZGVmaW5lZClcbiAgICBjb25zdCBob3N0ZWRab25lc1dpdGhvdXRSb2xlID0gcHJvcHMudmFsaWRhdGlvbkhvc3RlZFpvbmVzLmZpbHRlcigoem9uZSkgPT4gem9uZS52YWxpZGF0aW9uUm9sZSA9PT0gdW5kZWZpbmVkKVxuXG4gICAgaG9zdGVkWm9uZXNXaXRoUm9sZS5mb3JFYWNoKCh6b25lKSA9PiB7XG4gICAgICByZXF1ZXN0b3JGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgICAgYWN0aW9uczogWydzdHM6QXNzdW1lUm9sZSddLFxuICAgICAgICAgIHJlc291cmNlczogW3pvbmUudmFsaWRhdGlvblJvbGUhLnJvbGVBcm5dLFxuICAgICAgICB9KVxuICAgICAgKVxuICAgIH0pXG5cbiAgICBob3N0ZWRab25lc1dpdGhvdXRSb2xlLmZvckVhY2goKHpvbmUpID0+IHtcbiAgICAgIHJlcXVlc3RvckZ1bmN0aW9uLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsncm91dGU1MzpHZXRDaGFuZ2UnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgY29uc3QgZG9tYWluTmFtZXMgPSBkb21haW5zVG9ab25lc1t6b25lLmhvc3RlZFpvbmUuem9uZU5hbWVdXG4gICAgICBpZiAoZG9tYWluTmFtZXMgJiYgZG9tYWluTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXF1ZXN0b3JGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogWydyb3V0ZTUzOkNoYW5nZVJlc291cmNlUmVjb3JkU2V0cyddLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbYGFybjphd3M6cm91dGU1Mzo6Omhvc3RlZHpvbmUvJHt0aGlzLm5vcm1hbGl6ZUhvc3RlZFpvbmVJZCh6b25lLmhvc3RlZFpvbmUuaG9zdGVkWm9uZUlkKX1gXSxcbiAgICAgICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICAgICAgJ0ZvckFsbFZhbHVlczpTdHJpbmdFcXVhbHMnOiB7XG4gICAgICAgICAgICAgICAgJ3JvdXRlNTM6Q2hhbmdlUmVzb3VyY2VSZWNvcmRTZXRzUmVjb3JkVHlwZXMnOiBbJ0NOQU1FJ10sXG4gICAgICAgICAgICAgICAgJ3JvdXRlNTM6Q2hhbmdlUmVzb3VyY2VSZWNvcmRTZXRzQWN0aW9ucyc6IFsnVVBTRVJUJywgJ0RFTEVURSddLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAnRm9yQWxsVmFsdWVzOlN0cmluZ0xpa2UnOiB7XG4gICAgICAgICAgICAgICAgJ3JvdXRlNTM6Q2hhbmdlUmVzb3VyY2VSZWNvcmRTZXRzTm9ybWFsaXplZFJlY29yZE5hbWVzJzogZG9tYWluTmFtZXMubWFwKChuYW1lLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lsZGNhcmREb21haW5OYW1lKGBEb21haW5XaWxkY2FyZCR7em9uZS5ob3N0ZWRab25lLm5vZGUuaWR9JHtpbmRleH1gLCBuYW1lKVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICB9XG4gICAgfSlcblxuICAgIGNvbnN0IHJlcXVlc3RvclByb3ZpZGVyID0gbmV3IGN1c3RvbV9yZXNvdXJjZXMuUHJvdmlkZXIodGhpcywgJ1JlcXVlc3RvclByb3ZpZGVyJywge1xuICAgICAgb25FdmVudEhhbmRsZXI6IHJlcXVlc3RvckZ1bmN0aW9uLFxuICAgIH0pXG5cbiAgICBjb25zdCB2YWxpZGF0aW9uSG9zdGVkWm9uZXMgPSBwcm9wcy52YWxpZGF0aW9uSG9zdGVkWm9uZXMubWFwPFtzdHJpbmcsIFZhbGlkYXRpb25Ib3N0ZWRab25lUHJvcGVydGllc10+KCh6b25lKSA9PiB7XG4gICAgICBjb25zdCBwcm9wZXJ0aWVzOiBWYWxpZGF0aW9uSG9zdGVkWm9uZVByb3BlcnRpZXMgPSB7XG4gICAgICAgIERvbWFpbk5hbWU6IHRoaXMubm9ybWFsaXplRG9tYWluTmFtZSh6b25lLmhvc3RlZFpvbmUuem9uZU5hbWUpLFxuICAgICAgICBIb3N0ZWRab25lSWQ6IHRoaXMubm9ybWFsaXplSG9zdGVkWm9uZUlkKHpvbmUuaG9zdGVkWm9uZS5ob3N0ZWRab25lSWQpLFxuICAgICAgICBWYWxpZGF0aW9uUm9sZUFybjogem9uZS52YWxpZGF0aW9uUm9sZT8ucm9sZUFybixcbiAgICAgICAgVmFsaWRhdGlvbkV4dGVybmFsSWQ6IHpvbmUudmFsaWRhdGlvbkV4dGVybmFsSWQsXG4gICAgICB9XG4gICAgICByZXR1cm4gW3Byb3BlcnRpZXMuRG9tYWluTmFtZSwgcHJvcGVydGllc11cbiAgICB9KVxuXG4gICAgY29uc3QgcHJvcGVydGllczogUHJvcGVydGllcyA9IHtcbiAgICAgIERvbWFpbk5hbWU6IGRvbWFpbk5hbWUsXG4gICAgICBBbHRlcm5hdGl2ZURvbWFpbk5hbWVzOiBhbHRlcm5hdGl2ZURvbWFpbk5hbWVzLFxuICAgICAgVmFsaWRhdGlvbkhvc3RlZFpvbmVzOiBPYmplY3QuZnJvbUVudHJpZXModmFsaWRhdGlvbkhvc3RlZFpvbmVzKSxcbiAgICAgIENlcnRpZmljYXRlUmVnaW9uOiB0aGlzLmNlcnRpZmljYXRlUmVnaW9uLFxuICAgICAgQ2xlYW51cFZhbGlkYXRpb25SZWNvcmRzOiBib29sZWFuVG9TdHJpbmcocHJvcHMuY2xlYW51cFZhbGlkYXRpb25SZWNvcmRzID8/IHRydWUpLFxuICAgICAgVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQ6IGJvb2xlYW5Ub1N0cmluZyhwcm9wcy50cmFuc3BhcmVuY3lMb2dnaW5nRW5hYmxlZCA/PyB0cnVlKSxcbiAgICAgIFRhZ3M6IGNkay5MYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMudGFncy5yZW5kZXJUYWdzKCkgfSkgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgICAgUmVtb3ZhbFBvbGljeTogY2RrLkxhenkuc3RyaW5nKHsgcHJvZHVjZTogKCkgPT4gdGhpcy5yZW1vdmFsUG9saWN5IH0pLFxuICAgIH1cblxuICAgIGNvbnN0IGNlcnRpZmljYXRlID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnUmVxdWVzdG9yUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHJlcXVlc3RvclByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHJlc291cmNlVHlwZTogRE5TX1ZBTElEQVRFRF9DRVJUSUZJQ0FURV9UWVBFLFxuICAgICAgcHJvcGVydGllcyxcbiAgICB9KVxuXG4gICAgLy8gRW5zdXJlIENsb3VkRm9ybWF0aW9uIGRlbGV0ZXMgdGhlIGN1c3RvbSByZXNvdXJjZSBiZWZvcmUgdGhlIExhbWJkYVxuICAgIC8vIGZ1bmN0aW9uIGFuZCBpdHMgSUFNIHBvbGljaWVzLiBDbG91ZEZvcm1hdGlvbiBtYXkgZGVsZXRlIHRoZW0gaW5cbiAgICAvLyBwYXJhbGxlbCBkdXJpbmcgc3RhY2sgZGVsZXRpb24sIGNhdXNpbmcgdGhlIERFTEVURSBoYW5kbGVyIHRvIGZhaWxcbiAgICAvLyBiZWNhdXNlIHRoZSBMYW1iZGEncyBBQ00gcGVybWlzc2lvbnMgaGF2ZSBhbHJlYWR5IGJlZW4gcmVtb3ZlZC5cbiAgICBjZXJ0aWZpY2F0ZS5ub2RlLmFkZERlcGVuZGVuY3kocmVxdWVzdG9yRnVuY3Rpb24pXG4gICAgaWYgKHJlcXVlc3RvckZ1bmN0aW9uLnJvbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2VydGlmaWNhdGUubm9kZS5hZGREZXBlbmRlbmN5KHJlcXVlc3RvckZ1bmN0aW9uLnJvbGUpXG4gICAgICBjb25zdCBwb2xpY3kgPSByZXF1ZXN0b3JGdW5jdGlvbi5yb2xlLm5vZGUudHJ5RmluZENoaWxkKCdEZWZhdWx0UG9saWN5JylcbiAgICAgIGlmIChwb2xpY3kgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjZXJ0aWZpY2F0ZS5ub2RlLmFkZERlcGVuZGVuY3kocG9saWN5KVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY2VydGlmaWNhdGVBcm4gPSBjZXJ0aWZpY2F0ZS5nZXRBdHRTdHJpbmcoJ0FybicpXG5cbiAgICB0aGlzLm5vZGUuYWRkVmFsaWRhdGlvbih7XG4gICAgICB2YWxpZGF0ZTogKCkgPT5cbiAgICAgICAgdGhpcy52YWxpZGF0ZURvbWFpbnNUb0hvc3RlZFpvbmVzKFxuICAgICAgICAgIGFsbERvbWFpbnMsXG4gICAgICAgICAgdmFsaWRhdGlvbkhvc3RlZFpvbmVzLm1hcCgoW3pvbmVOYW1lLCBfXSkgPT4gem9uZU5hbWUpXG4gICAgICAgICksXG4gICAgfSlcbiAgfVxuXG4gIG1ldHJpY0RheXNUb0V4cGlyeShwcm9wcz86IGNkay5hd3NfY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zIHwgdW5kZWZpbmVkKTogY2RrLmF3c19jbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBwZXJpb2Q6IGNkay5EdXJhdGlvbi5kYXlzKDEpLFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7IENlcnRpZmljYXRlQXJuOiB0aGlzLmNlcnRpZmljYXRlQXJuIH0sXG4gICAgICBtZXRyaWNOYW1lOiAnRGF5c1RvRXhwaXJ5JyxcbiAgICAgIG5hbWVzcGFjZTogJ0FXUy9DZXJ0aWZpY2F0ZU1hbmFnZXInLFxuICAgICAgcmVnaW9uOiB0aGlzLmNlcnRpZmljYXRlUmVnaW9uLFxuICAgICAgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRzLk1JTklNVU0sXG4gICAgfSlcbiAgfVxuXG4gIGFwcGx5UmVtb3ZhbFBvbGljeShwb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5KTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmFsUG9saWN5ID0gcG9saWN5XG4gIH1cblxuICAvLyBjZXJ0aWZpY2F0ZVJlZiBpcyBhIHJlcXVpcmVkIHByb3BlcnR5IG9mIHR5cGUgY2VydGlmaWNhdGVtYW5hZ2VyLklDZXJ0aWZpY2F0ZVJlZiBvbiBjZXJ0aWZpY2F0ZW1hbmFnZXIuSUNlcnRpZmljYXRlIHNpbmNlIGF3cy1jZGstbGliIDIuMzUuMFxuICAvLyBXZSB1c2UgdHlwZSBhbnkgaGVyZSB0byBrZWVwIGNvbXBhdGFiaWxpdHkgd2l0aCBvbGRlciBDREsgdmVyc2lvbnNcbiAgLyoqIEEgcmVmZXJlbmNlIHRvIGEgQ2VydGlmaWNhdGUgcmVzb3VyY2UuICovXG4gIHB1YmxpYyBnZXQgY2VydGlmaWNhdGVSZWYoKTogYW55IHtcbiAgICByZXR1cm4ge1xuICAgICAgY2VydGlmaWNhdGVJZDogdGhpcy5jZXJ0aWZpY2F0ZUFybixcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG5vcm1hbGl6ZURvbWFpbk5hbWUoZG9tYWluTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoY2RrLlRva2VuLmlzVW5yZXNvbHZlZChkb21haW5OYW1lKSkge1xuICAgICAgcmV0dXJuIGRvbWFpbk5hbWVcbiAgICB9XG4gICAgcmV0dXJuIGNsZWFuRG9tYWluTmFtZShkb21haW5OYW1lKVxuICB9XG5cbiAgcHJpdmF0ZSBub3JtYWxpemVIb3N0ZWRab25lSWQoaG9zdGVkWm9uZUlkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChjZGsuVG9rZW4uaXNVbnJlc29sdmVkKGhvc3RlZFpvbmVJZCkpIHtcbiAgICAgIHJldHVybiBob3N0ZWRab25lSWRcbiAgICB9XG4gICAgcmV0dXJuIGNsZWFuSG9zdGVkWm9uZUlkKGhvc3RlZFpvbmVJZClcbiAgfVxuXG4gIHByaXZhdGUgd2lsZGNhcmREb21haW5OYW1lKGlkOiBzdHJpbmcsIGRvbWFpbk5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHMgPSBjZGsuRm4uc3BsaXQoJy4nLCBkb21haW5OYW1lKVxuICAgIGNvbnN0IGZpcnN0ID0gY2RrLkZuLnNlbGVjdCgwLCBwYXJ0cylcbiAgICBjb25zdCBpc1dpbGRjYXJkID0gbmV3IGNkay5DZm5Db25kaXRpb24odGhpcywgYElzJHtpZH1gLCB7XG4gICAgICBleHByZXNzaW9uOiBjZGsuRm4uY29uZGl0aW9uRXF1YWxzKGZpcnN0LCAnKicpLFxuICAgIH0pXG4gICAgcmV0dXJuIGNkay5Gbi5jb25kaXRpb25JZihpc1dpbGRjYXJkLmxvZ2ljYWxJZCwgZG9tYWluTmFtZSwgYCouJHtkb21haW5OYW1lfWApLnRvU3RyaW5nKClcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVEb21haW5zVG9Ib3N0ZWRab25lcyhkb21haW5OYW1lczogc3RyaW5nW10sIHpvbmVOYW1lczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdXG4gICAgZm9yIChjb25zdCBkb21haW5OYW1lIG9mIGRvbWFpbk5hbWVzKSB7XG4gICAgICBjb25zdCByZXNvbHZhYmxlRG9tYWluTmFtZSA9ICFjZGsuVG9rZW4uaXNVbnJlc29sdmVkKGRvbWFpbk5hbWUpXG4gICAgICBjb25zdCByZXNvbHZhYmxlWm9uZU5hbWVzID0gIXpvbmVOYW1lcy5zb21lKCh6b25lTmFtZSkgPT4gY2RrLlRva2VuLmlzVW5yZXNvbHZlZCh6b25lTmFtZSkpXG4gICAgICBpZiAocmVzb2x2YWJsZURvbWFpbk5hbWUgJiYgcmVzb2x2YWJsZVpvbmVOYW1lcyAmJiAhem9uZU5hbWVzLnNvbWUoKHpvbmVOYW1lKSA9PiBkb21haW5OYW1lLmVuZHNXaXRoKHpvbmVOYW1lKSkpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goYERvbWFpbiAke2RvbWFpbk5hbWV9IGlzIG5vdCBwcm92aWRlZCB3aXRoIGF1dGhvcml0YXRpdmUgaG9zdGVkIHpvbmVgKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzXG4gIH1cbn1cbiJdfQ==
|
package/package.json
CHANGED
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"eslint-plugin-prettier": "^4.2.5",
|
|
60
60
|
"jest": "^29.7.0",
|
|
61
61
|
"jest-junit": "^16",
|
|
62
|
-
"jsii": "~5.
|
|
62
|
+
"jsii": "~5.9.0",
|
|
63
63
|
"jsii-diff": "^1.126.0",
|
|
64
64
|
"jsii-docgen": "^10.5.0",
|
|
65
65
|
"jsii-pacmak": "^1.126.0",
|
|
66
|
-
"jsii-rosetta": "~5.
|
|
66
|
+
"jsii-rosetta": "~5.9.0",
|
|
67
67
|
"prettier": "^2.8.8",
|
|
68
68
|
"projen": "^0.99.16",
|
|
69
69
|
"ts-jest": "^29.4.6",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"publishConfig": {
|
|
88
88
|
"access": "public"
|
|
89
89
|
},
|
|
90
|
-
"version": "0.1.
|
|
90
|
+
"version": "0.1.41",
|
|
91
91
|
"jest": {
|
|
92
92
|
"coverageProvider": "v8",
|
|
93
93
|
"testMatch": [
|