@paulo_raca/cdk-skylight 0.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.
- package/.jsii +5012 -0
- package/.jsii.tabl.json +1 -0
- package/API.md +2122 -0
- package/API.md.md +2038 -0
- package/LICENSE +202 -0
- package/README.md +181 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +7 -0
- package/lib/skylight-authentication/ad-authentication.d.ts +132 -0
- package/lib/skylight-authentication/ad-authentication.js +232 -0
- package/lib/skylight-authentication/index.d.ts +1 -0
- package/lib/skylight-authentication/index.js +18 -0
- package/lib/skylight-compute/eks/index.d.ts +2 -0
- package/lib/skylight-compute/eks/index.js +19 -0
- package/lib/skylight-compute/eks/windows-eks-cluster.d.ts +38 -0
- package/lib/skylight-compute/eks/windows-eks-cluster.js +77 -0
- package/lib/skylight-compute/eks/windows-eks-nodes.d.ts +68 -0
- package/lib/skylight-compute/eks/windows-eks-nodes.js +250 -0
- package/lib/skylight-compute/index.d.ts +2 -0
- package/lib/skylight-compute/index.js +19 -0
- package/lib/skylight-compute/windows-node.d.ts +102 -0
- package/lib/skylight-compute/windows-node.js +219 -0
- package/lib/skylight-storage/fsx-windows.d.ts +82 -0
- package/lib/skylight-storage/fsx-windows.js +130 -0
- package/lib/skylight-storage/index.d.ts +1 -0
- package/lib/skylight-storage/index.js +18 -0
- package/package.json +141 -0
- package/rosetta/default.ts-fixture +13 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.WindowsEKSNodes = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
/**
|
|
7
|
+
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
10
|
+
* with the License. A copy of the License is located at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
15
|
+
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
16
|
+
* and limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
19
|
+
const constructs_1 = require("constructs");
|
|
20
|
+
const skylight = require("../../index");
|
|
21
|
+
class WindowsEKSNodes extends constructs_1.Construct {
|
|
22
|
+
constructor(scope, id, props) {
|
|
23
|
+
super(scope, id);
|
|
24
|
+
props.namespace = props.namespace ?? 'cdk-skylight';
|
|
25
|
+
props.instanceType =
|
|
26
|
+
props.instanceType ?? new aws_cdk_lib_1.aws_ec2.InstanceType('m5.large');
|
|
27
|
+
this.vpc = props.vpc;
|
|
28
|
+
const windows_machineImage = new aws_cdk_lib_1.aws_ec2.LookupMachineImage({
|
|
29
|
+
name: '*Windows_Server-2019-English-Full-EKS_Optimized-1.21*',
|
|
30
|
+
windows: true,
|
|
31
|
+
});
|
|
32
|
+
this.nodesSg = new aws_cdk_lib_1.aws_ec2.SecurityGroup(this, id + '-securityGroup', {
|
|
33
|
+
vpc: this.vpc,
|
|
34
|
+
});
|
|
35
|
+
this.windowsWorkersRole = new aws_cdk_lib_1.aws_iam.Role(this, 'windows-eks-workers-instance-role', {
|
|
36
|
+
assumedBy: new aws_cdk_lib_1.aws_iam.ServicePrincipal('ec2.amazonaws.com'),
|
|
37
|
+
roleName: 'windows-eks-workers-instance-role',
|
|
38
|
+
managedPolicies: [
|
|
39
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
|
|
40
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSWorkerNodePolicy'),
|
|
41
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'),
|
|
42
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKS_CNI_Policy'),
|
|
43
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMDirectoryServiceAccess'),
|
|
44
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AWSKeyManagementServicePowerUser'),
|
|
45
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSClusterPolicy'),
|
|
46
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('SecretsManagerReadWrite'),
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
this.asg = new aws_cdk_lib_1.aws_autoscaling.AutoScalingGroup(this, 'WindowsInstancesCapacity', {
|
|
50
|
+
vpc: props.vpc,
|
|
51
|
+
role: this.windowsWorkersRole,
|
|
52
|
+
minCapacity: 2,
|
|
53
|
+
securityGroup: this.nodesSg,
|
|
54
|
+
maxCapacity: 10,
|
|
55
|
+
instanceType: props.instanceType,
|
|
56
|
+
machineImage: windows_machineImage,
|
|
57
|
+
});
|
|
58
|
+
this.asgResource = this.asg.node.children.find((c) => c.cfnResourceType ===
|
|
59
|
+
'AWS::AutoScaling::AutoScalingGroup');
|
|
60
|
+
}
|
|
61
|
+
addUserData(...commands) {
|
|
62
|
+
this.asg.addUserData(...commands);
|
|
63
|
+
}
|
|
64
|
+
addAdDependency(adParametersStore) {
|
|
65
|
+
const secretName = aws_cdk_lib_1.aws_ssm.StringParameter.valueForStringParameter(this, `/${adParametersStore.namespace}/${adParametersStore.secretPointer}`);
|
|
66
|
+
this.addUserData(`
|
|
67
|
+
#domain join with secret from secret manager
|
|
68
|
+
[string]$SecretAD = "${secretName}"
|
|
69
|
+
$SecretObj = Get-SECSecretValue -SecretId $SecretAD
|
|
70
|
+
[PSCustomObject]$Secret = ($SecretObj.SecretString | ConvertFrom-Json)
|
|
71
|
+
$password = $Secret.Password | ConvertTo-SecureString -asPlainText -Force
|
|
72
|
+
$username = $Secret.UserID + "@" + $Secret.Domain
|
|
73
|
+
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
|
|
74
|
+
Add-Computer -DomainName $Secret.Domain -Credential $credential
|
|
75
|
+
Restart-Computer -Force
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
runPowerShellSSMDocument(name, commands) {
|
|
79
|
+
new aws_cdk_lib_1.aws_ssm.CfnAssociation(this, name, {
|
|
80
|
+
name: 'AWS-RunPowerShellScript',
|
|
81
|
+
parameters: {
|
|
82
|
+
commands: commands,
|
|
83
|
+
},
|
|
84
|
+
targets: [
|
|
85
|
+
{
|
|
86
|
+
key: 'tag:aws:autoscaling:groupName',
|
|
87
|
+
values: [this.asg.autoScalingGroupName],
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
gMSAWebHookAutoInstall(eksCluster, privateSignerName, awsaccountid, awsregion) {
|
|
93
|
+
const certmanager = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'webHookECR', {
|
|
94
|
+
description: 'Allow WebHook',
|
|
95
|
+
statements: [
|
|
96
|
+
new aws_cdk_lib_1.aws_iam.PolicyStatement({
|
|
97
|
+
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
|
|
98
|
+
actions: [
|
|
99
|
+
'ecr:CreateRepository',
|
|
100
|
+
'ecr:DescribeImages',
|
|
101
|
+
'ecr:GetAuthorizationToken',
|
|
102
|
+
'ecr:GetDownloadUrlForLayer',
|
|
103
|
+
'ecr:BatchGetImage',
|
|
104
|
+
'ecr:BatchCheckLayerAvailability',
|
|
105
|
+
'ecr:GetDownloadUrlForLayer',
|
|
106
|
+
'ecr:PutImage',
|
|
107
|
+
'ecr:InitiateLayerUpload',
|
|
108
|
+
'ecr:UploadLayerPart',
|
|
109
|
+
'ecr:CompleteLayerUpload',
|
|
110
|
+
],
|
|
111
|
+
resources: ['arn:aws:ecr:*:*:repository/certmanager-ca-controller'],
|
|
112
|
+
}),
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
const describeCluster = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'AllowWebHookEKSCluster', {
|
|
116
|
+
description: 'Allow WebHook',
|
|
117
|
+
statements: [
|
|
118
|
+
new aws_cdk_lib_1.aws_iam.PolicyStatement({
|
|
119
|
+
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
|
|
120
|
+
actions: ['eks:DescribeCluster'],
|
|
121
|
+
resources: [`arn:aws:eks:*:${awsaccountid}:cluster/*`],
|
|
122
|
+
}),
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
const allowAuthorizationToken = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'AllowWebHookECRCluster', {
|
|
126
|
+
description: 'Allow WebHook',
|
|
127
|
+
statements: [
|
|
128
|
+
new aws_cdk_lib_1.aws_iam.PolicyStatement({
|
|
129
|
+
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
|
|
130
|
+
actions: ['ecr:GetAuthorizationToken'],
|
|
131
|
+
resources: ['*'],
|
|
132
|
+
}),
|
|
133
|
+
],
|
|
134
|
+
});
|
|
135
|
+
const node = new skylight.compute.DomainWindowsNode(this, 'eksWorkerForGMSA', {
|
|
136
|
+
vpc: this.vpc,
|
|
137
|
+
windowsMachine: false,
|
|
138
|
+
iamManagedPoliciesList: [
|
|
139
|
+
certmanager,
|
|
140
|
+
describeCluster,
|
|
141
|
+
allowAuthorizationToken,
|
|
142
|
+
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
|
|
143
|
+
],
|
|
144
|
+
amiName: '*amzn2-ami-hvm-x86_64*',
|
|
145
|
+
instanceType: 't3.small',
|
|
146
|
+
});
|
|
147
|
+
this.asg.connections.allowFrom(node.instance, aws_cdk_lib_1.aws_ec2.Port.tcp(443));
|
|
148
|
+
eksCluster.awsAuth.addRoleMapping(node.nodeRole, {
|
|
149
|
+
groups: ['system:masters'],
|
|
150
|
+
username: 'admin',
|
|
151
|
+
});
|
|
152
|
+
node.runShellCommands([
|
|
153
|
+
'sudo -i',
|
|
154
|
+
'yum install -y git',
|
|
155
|
+
'git clone https://github.com/aws-samples/amazon-eks-gmsa-admission-webhook-autoinstall',
|
|
156
|
+
'cd amazon-eks-gmsa-admission-webhook-autoinstall/',
|
|
157
|
+
`bash installation.sh ${awsaccountid} ${awsregion} ${eksCluster.clusterName} ${privateSignerName}/my-signer AL2`,
|
|
158
|
+
], 'webHookInstallation');
|
|
159
|
+
}
|
|
160
|
+
addStorageDependency(adParametersStore, fsxParametersStore, folderName) {
|
|
161
|
+
const secretName = aws_cdk_lib_1.aws_ssm.StringParameter.valueForStringParameter(this, `/${adParametersStore.namespace}/${adParametersStore.secretPointer}`);
|
|
162
|
+
const fsxEndpoint = aws_cdk_lib_1.aws_ssm.StringParameter.valueForStringParameter(this, `/${fsxParametersStore.namespace}/${fsxParametersStore.dnsEndpoint}`);
|
|
163
|
+
const smbPath = `\\\\${fsxEndpoint}\\${folderName}`;
|
|
164
|
+
const commands = [
|
|
165
|
+
'$bootfix = {',
|
|
166
|
+
'$LocalDrive = Get-SmbGlobalMapping',
|
|
167
|
+
'if ($LocalDrive -eq $null)',
|
|
168
|
+
'{',
|
|
169
|
+
` [string]$SecretAD = '${secretName}'`,
|
|
170
|
+
' $SecretObj = Get-SECSecretValue -SecretId $SecretAD',
|
|
171
|
+
' [PSCustomObject]$Secret = ($SecretObj.SecretString | ConvertFrom-Json)',
|
|
172
|
+
' $password = $Secret.Password | ConvertTo-SecureString -asPlainText -Force',
|
|
173
|
+
" $username = $Secret.UserID + '@' + $Secret.Domain",
|
|
174
|
+
' $domain_admin_credential = New-Object System.Management.Automation.PSCredential($username,$password)',
|
|
175
|
+
` New-SmbGlobalMapping -RemotePath '${smbPath}' -Credential $domain_admin_credential -LocalPath G: -Persistent $true -RequirePrivacy $true -ErrorAction Stop`,
|
|
176
|
+
'}',
|
|
177
|
+
'}',
|
|
178
|
+
'New-Item -ItemType Directory -Path c:\\Scripts',
|
|
179
|
+
'$bootfix | set-content c:\\Scripts\\bootfix.ps1',
|
|
180
|
+
'# Create a scheduled task on startup to execute the mapping',
|
|
181
|
+
"$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument 'c:\\scripts\\bootfix.ps1'",
|
|
182
|
+
'$trigger = New-ScheduledTaskTrigger -AtStartup',
|
|
183
|
+
` [string]$SecretAD = '${secretName}'`,
|
|
184
|
+
' $SecretObj = Get-SECSecretValue -SecretId $SecretAD',
|
|
185
|
+
' [PSCustomObject]$Secret = ($SecretObj.SecretString | ConvertFrom-Json)',
|
|
186
|
+
" $username = $Secret.UserID + '@' + $Secret.Domain",
|
|
187
|
+
"Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'SmbGlobalMapping' -Description 'Mapping the SMB share and adding machine to gMSA' -RunLevel Highest -User $username -Password $Secret.Password",
|
|
188
|
+
'# Running the boot fix now',
|
|
189
|
+
'& $bootfix',
|
|
190
|
+
'',
|
|
191
|
+
];
|
|
192
|
+
this.runPowerShellSSMDocument('SMBGlobalMapping', commands);
|
|
193
|
+
}
|
|
194
|
+
addEKSDependency(eksCluster) {
|
|
195
|
+
const commands = [
|
|
196
|
+
'# Joining EKS Cluster',
|
|
197
|
+
"[string]$EKSBootstrapScriptFile = 'C:\\Program Files\\Amazon\\EKS\\Start-EKSBootstrap.ps1'",
|
|
198
|
+
`powershell -File $EKSBootstrapScriptFile -EKSClusterName '${eksCluster.clusterName}'`,
|
|
199
|
+
];
|
|
200
|
+
this.runPowerShellSSMDocument('EKSBootstrap', commands);
|
|
201
|
+
eksCluster.awsAuth.addRoleMapping(this.windowsWorkersRole, {
|
|
202
|
+
groups: [
|
|
203
|
+
'system:bootstrappers',
|
|
204
|
+
'system:nodes',
|
|
205
|
+
'eks:kube-proxy-windows',
|
|
206
|
+
],
|
|
207
|
+
username: 'system:node:{{EC2PrivateDNSName}}',
|
|
208
|
+
});
|
|
209
|
+
eksCluster.connectAutoScalingGroupCapacity(this.asg, {
|
|
210
|
+
bootstrapEnabled: false, //Windows Bootstrap done manually
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
addLocalCredFile(adParametersStore, ADGroupName, AccountName) {
|
|
214
|
+
const secretName = aws_cdk_lib_1.aws_ssm.StringParameter.valueForStringParameter(this, `/${adParametersStore.namespace}/${adParametersStore.secretPointer}`);
|
|
215
|
+
const commands = [
|
|
216
|
+
'# Getting AD Password',
|
|
217
|
+
`[string]$SecretAD = '${secretName}'`,
|
|
218
|
+
'$SecretObj = Get-SECSecretValue -SecretId $SecretAD',
|
|
219
|
+
'[PSCustomObject]$Secret = ($SecretObj.SecretString | ConvertFrom-Json)',
|
|
220
|
+
'$password = $Secret.Password | ConvertTo-SecureString -asPlainText -Force',
|
|
221
|
+
"$username = $Secret.UserID + '@' + $Secret.Domain",
|
|
222
|
+
'$domain_admin_credential = New-Object System.Management.Automation.PSCredential($username,$password)',
|
|
223
|
+
'Add-WindowsFeature RSAT-AD-PowerShell',
|
|
224
|
+
'Install-PackageProvider NuGet -Force',
|
|
225
|
+
'Install-Module CredentialSpec -Force',
|
|
226
|
+
'Set-PSRepository PSGallery -InstallationPolicy Trusted',
|
|
227
|
+
`New-ADGroup -Name "${ADGroupName} AD Group" -SamAccountName ${ADGroupName}"" -GroupScope DomainLocal -Credential $domain_admin_credential`,
|
|
228
|
+
`New-ADServiceAccount -Name "${AccountName}" -DnsHostName "${AccountName}.$Secret.Domain" -ServicePrincipalNames "host/${AccountName}", "host/${AccountName}.$Secret.Domain" -PrincipalsAllowedToRetrieveManagedPassword "${ADGroupName}" -Credential $domain_admin_credential`,
|
|
229
|
+
`Add-ADGroupMember -Identity '${ADGroupName}' -Members $env:computername$ -Credential $domain_admin_credential`,
|
|
230
|
+
'# Saves the cred file to C:\\ProgramData\\Docker\\CredentialSpecs (default)',
|
|
231
|
+
'#Here upload to S3 the CredFile',
|
|
232
|
+
'$bootfix = {',
|
|
233
|
+
`New-CredentialSpec -AccountName ${AccountName}`,
|
|
234
|
+
'}',
|
|
235
|
+
'# Scheduling onboot',
|
|
236
|
+
'$trigger = New-ScheduledTaskTrigger -AtStartup',
|
|
237
|
+
'$bootfix | set-content c:\\Scripts\\gMSA.ps1',
|
|
238
|
+
"$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument 'c:\\scripts\\gMSA.ps1'",
|
|
239
|
+
"Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'CreateCredSpecFile' -Description 'CreateCredFile and saves it in default folder' -RunLevel Highest -User $username -Password $Secret.Password",
|
|
240
|
+
'# Reboot to apply changes',
|
|
241
|
+
'Restart-Computer -Force',
|
|
242
|
+
'',
|
|
243
|
+
];
|
|
244
|
+
this.runPowerShellSSMDocument('gMSA_AD_Group_CredFile', commands);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.WindowsEKSNodes = WindowsEKSNodes;
|
|
248
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
249
|
+
WindowsEKSNodes[_a] = { fqn: "cdk-skylight.compute.WindowsEKSNodes", version: "0.0.0" };
|
|
250
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2luZG93cy1la3Mtbm9kZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2t5bGlnaHQtY29tcHV0ZS9la3Mvd2luZG93cy1la3Mtbm9kZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7Ozs7Ozs7Ozs7R0FXRztBQUVILDZDQU9xQjtBQUVyQiwyQ0FBdUM7QUFDdkMsd0NBQXdDO0FBc0R4QyxNQUFhLGVBQWdCLFNBQVEsc0JBQVM7SUFPNUMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE0QjtRQUNwRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLEtBQUssQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxjQUFjLENBQUM7UUFDcEQsS0FBSyxDQUFDLFlBQVk7WUFDaEIsS0FBSyxDQUFDLFlBQVksSUFBSSxJQUFJLHFCQUFPLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTdELElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUVyQixNQUFNLG9CQUFvQixHQUFHLElBQUkscUJBQU8sQ0FBQyxrQkFBa0IsQ0FBQztZQUMxRCxJQUFJLEVBQUUsdURBQXVEO1lBQzdELE9BQU8sRUFBRSxJQUFJO1NBQ2QsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHFCQUFPLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsZ0JBQWdCLEVBQUU7WUFDcEUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1NBQ2QsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUkscUJBQU8sQ0FBQyxJQUFJLENBQ3hDLElBQUksRUFDSixtQ0FBbUMsRUFDbkM7WUFDRSxTQUFTLEVBQUUsSUFBSSxxQkFBTyxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixDQUFDO1lBQzVELFFBQVEsRUFBRSxt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RCxnQkFBZ0IsQ0FDZCxpQkFBMkUsRUFDM0UsV0FBbUIsRUFDbkIsV0FBbUI7UUFFbkIsTUFBTSxVQUFVLEdBQUcscUJBQU8sQ0FBQyxlQUFlLENBQUMsdUJBQXVCLENBQ2hFLElBQUksRUFDSixJQUFJLGlCQUFpQixDQUFDLFNBQVMsSUFBSSxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsQ0FDckUsQ0FBQztRQUVGLE1BQU0sUUFBUSxHQUFHO1lBQ2YsdUJBQXVCO1lBQ3ZCLHlCQUF5QixVQUFVLEdBQUc7WUFDdEMscURBQXFEO1lBQ3JELHlFQUF5RTtZQUN6RSw2RUFBNkU7WUFDN0UscURBQXFEO1lBQ3JELHNHQUFzRztZQUN0Ryx1Q0FBdUM7WUFDdkMsc0NBQXNDO1lBQ3RDLHNDQUFzQztZQUN0Qyx3REFBd0Q7WUFDeEQsc0JBQXNCLFdBQVcsOEJBQThCLFdBQVcsaUVBQWlFO1lBQzNJLCtCQUErQixXQUFXLG1CQUFtQixXQUFXLGlEQUFpRCxXQUFXLFlBQVksV0FBVyxpRUFBaUUsV0FBVyx3Q0FBd0M7WUFDL1EsZ0NBQWdDLFdBQVcsb0VBQW9FO1lBQy9HLDZFQUE2RTtZQUM3RSxpQ0FBaUM7WUFDakMsY0FBYztZQUNkLG1DQUFtQyxXQUFXLEVBQUU7WUFDaEQsR0FBRztZQUNILHFCQUFxQjtZQUNyQixpREFBaUQ7WUFDakQsOENBQThDO1lBQzlDLCtGQUErRjtZQUMvRixtTkFBbU47WUFDbk4sMkJBQTJCO1lBQzNCLHlCQUF5QjtZQUN6QixFQUFFO1NBQ0gsQ0FBQztRQUVGLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyx3QkFBd0IsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNwRSxDQUFDOztBQXRVSCwwQ0F1VUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgMjAyMSBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpLiBZb3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiAgd2l0aCB0aGUgTGljZW5zZS4gQSBjb3B5IG9mIHRoZSBMaWNlbnNlIGlzIGxvY2F0ZWQgYXRcbiAqXG4gKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqICBvciBpbiB0aGUgJ2xpY2Vuc2UnIGZpbGUgYWNjb21wYW55aW5nIHRoaXMgZmlsZS4gVGhpcyBmaWxlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICdBUyBJUycgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFU1xuICogIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXG4gKiAgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIGF3c19hdXRvc2NhbGluZyxcbiAgYXdzX2VjMixcbiAgYXdzX2VrcyxcbiAgYXdzX2lhbSxcbiAgYXdzX3NzbSxcbiAgQ2ZuUmVzb3VyY2UsXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IEF1dG9TY2FsaW5nR3JvdXAgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtYXV0b3NjYWxpbmcnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBza3lsaWdodCBmcm9tICcuLi8uLi9pbmRleCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVJ1bnRpbWVOb2RlcyB7XG4gIC8qKlxuICAgKiBNZXRob2QgdG8gYWRkIHVzZXJEYXRhIHRvIHRoZSBub2Rlc1xuICAgKi9cbiAgYWRkVXNlckRhdGEoLi4uY29tbWFuZHM6IHN0cmluZ1tdKTogdm9pZDtcbiAgLyoqXG4gICAqIE1ldGhvZCB0byBjb25maWd1cmUgdGhlIE5vZGVzIHRvIHBhcnQgb2YgQUQgRG9tYWluXG4gICAqIFNlY3JldDogVGhlIHNlY3JldHMgbWFuYWdlciBzZWNyZXQgdG8gdXNlIG11c3QgYmUgaW4gZm9ybWF0OlxuICAgKiAne0RvbWFpbjogPGRvbWFpbi5uYW1lPiwgVXNlcklEOiAnQWRtaW4nLCBQYXNzd29yZDogJzxwYXNzd29yZD4nfScgKEZyb20gY2RrLXNreWxpZ2h0LkF3c01hbmFnZWRNaWNyb3NvZnRBZFI1MyBPYmplY3QpXG4gICAqL1xuICBhZGRBZERlcGVuZGVuY3k/KFxuICAgIGFkUGFyYW1ldGVyc1N0b3JlOiBza3lsaWdodC5hdXRoZW50aWNhdGlvbi5JQXdzTWFuYWdlZE1pY3Jvc29mdEFkUGFyYW1ldGVyc1xuICApOiB2b2lkO1xuICAvKipcbiAgICogTWV0aG9kIHRvIGNvbmZpZ3VyZSBwZXJzaXN0ZW50IHN0b3JhZ2UgZGVwZW5kZW5jeSB0byB0aGUgaG9zdHMgYnkgdXNpbmcgR2xvYmFsIE1hcHBpbmcuXG4gICAqL1xuICBhZGRTdG9yYWdlRGVwZW5kZW5jeShcbiAgICBhZFBhcmFtZXRlcnNTdG9yZTogc2t5bGlnaHQuYXV0aGVudGljYXRpb24uSUF3c01hbmFnZWRNaWNyb3NvZnRBZFBhcmFtZXRlcnMsXG4gICAgZnN4UGFyYW1ldGVyc1N0b3JlOiBza3lsaWdodC5zdG9yYWdlLklGU3hXaW5kb3dzUGFyYW1ldGVycyxcbiAgICBmb2xkZXJOYW1lOiBzdHJpbmdcbiAgKTogdm9pZDtcblxuICAvKipcbiAgICogTWV0aG9kIHRvIGFkZCB0aGUgbm9kZXMgdG8gc3BlY2lmaWMgQ2x1c3RlclxuICAgKi9cbiAgYWRkRUtTRGVwZW5kZW5jeT8oZWtzQ2x1c3RlcjogYXdzX2Vrcy5DbHVzdGVyKTogdm9pZDtcblxuICAvKipcbiAgICogTWV0aG9kIHRvIGFkZCBzdXBwb3J0IGZvciBMb2NhbENyZWRGaWxlIDxFeHBlcmltZW50YWw+XG4gICAqL1xuICBhZGRMb2NhbENyZWRGaWxlPyhcbiAgICBhZFBhcmFtZXRlcnNTdG9yZTogc2t5bGlnaHQuYXV0aGVudGljYXRpb24uSUF3c01hbmFnZWRNaWNyb3NvZnRBZFBhcmFtZXRlcnMsXG4gICAgQURHcm91cE5hbWU6IHN0cmluZyxcbiAgICBBY2NvdW50TmFtZTogc3RyaW5nXG4gICk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVdpbmRvd3NFS1NOb2Rlc1Byb3BzIHtcbiAgdnBjOiBhd3NfZWMyLklWcGM7XG4gIC8qKlxuICAgKiBUaGUgU1NNIG5hbWVzcGFjZSB0byBzYXZlIHBhcmFtZXRlcnMgdG9cbiAgICogQGRlZmF1bHQgLSAnY2RrLXNreWxpZ2h0Jy5cbiAgICovXG4gIG5hbWVzcGFjZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGluc3RhbmNlIHRvIHVzZVxuICAgKiBAZGVmYXVsdCAtICdtNS5sYXJnZScuXG4gICAqL1xuICBpbnN0YW5jZVR5cGU/OiBhd3NfZWMyLkluc3RhbmNlVHlwZTtcbn1cblxuZXhwb3J0IGNsYXNzIFdpbmRvd3NFS1NOb2RlcyBleHRlbmRzIENvbnN0cnVjdCBpbXBsZW1lbnRzIElSdW50aW1lTm9kZXMge1xuICByZWFkb25seSBhc2c6IEF1dG9TY2FsaW5nR3JvdXA7XG4gIHJlYWRvbmx5IHdpbmRvd3NXb3JrZXJzUm9sZTogYXdzX2lhbS5Sb2xlO1xuICByZWFkb25seSBhc2dSZXNvdXJjZTogYXdzX2F1dG9zY2FsaW5nLkNmbkF1dG9TY2FsaW5nR3JvdXA7XG4gIHJlYWRvbmx5IHZwYzogYXdzX2VjMi5JVnBjO1xuICByZWFkb25seSBub2Rlc1NnOiBhd3NfZWMyLlNlY3VyaXR5R3JvdXA7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IElXaW5kb3dzRUtTTm9kZXNQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBwcm9wcy5uYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2UgPz8gJ2Nkay1za3lsaWdodCc7XG4gICAgcHJvcHMuaW5zdGFuY2VUeXBlID1cbiAgICAgIHByb3BzLmluc3RhbmNlVHlwZSA/PyBuZXcgYXdzX2VjMi5JbnN0YW5jZVR5cGUoJ201LmxhcmdlJyk7XG5cbiAgICB0aGlzLnZwYyA9IHByb3BzLnZwYztcblxuICAgIGNvbnN0IHdpbmRvd3NfbWFjaGluZUltYWdlID0gbmV3IGF3c19lYzIuTG9va3VwTWFjaGluZUltYWdlKHtcbiAgICAgIG5hbWU6ICcqV2luZG93c19TZXJ2ZXItMjAxOS1FbmdsaXNoLUZ1bGwtRUtTX09wdGltaXplZC0xLjIxKicsXG4gICAgICB3aW5kb3dzOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5ub2Rlc1NnID0gbmV3IGF3c19lYzIuU2VjdXJpdHlHcm91cCh0aGlzLCBpZCArICctc2VjdXJpdHlHcm91cCcsIHtcbiAgICAgIHZwYzogdGhpcy52cGMsXG4gICAgfSk7XG4gICAgdGhpcy53aW5kb3dzV29ya2Vyc1JvbGUgPSBuZXcgYXdzX2lhbS5Sb2xlKFxuICAgICAgdGhpcyxcbiAgICAgICd3aW5kb3dzLWVrcy13b3JrZXJzLWluc3RhbmNlLXJvbGUnLFxuICAgICAge1xuICAgICAgICBhc3N1bWVkQnk6IG5ldyBhd3NfaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2VjMi5hbWF6b25hd3MuY29tJyksXG4gICAgICAgIHJvbGVOYW1lOiAnd2luZG93cy1la3Mtd29ya2Vycy1pbnN0YW5jZS1yb2xlJyxcbiAgICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgICAgYXdzX2lhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcbiAgICAgICAgICAgICdBbWF6b25TU01NYW5hZ2VkSW5zdGFuY2VDb3JlJyxcbiAgICAgICAgICApLFxuICAgICAgICAgIGF3c19pYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoXG4gICAgICAgICAgICAnQW1hem9uRUtTV29ya2VyTm9kZVBvbGljeScsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhd3NfaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgICAgJ0FtYXpvbkVDMkNvbnRhaW5lclJlZ2lzdHJ5UmVhZE9ubHknLFxuICAgICAgICAgICksXG4gICAgICAgICAgYXdzX2lhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcbiAgICAgICAgICAgICdBbWF6b25FS1NfQ05JX1BvbGljeScsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhd3NfaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgICAgJ0FtYXpvblNTTURpcmVjdG9yeVNlcnZpY2VBY2Nlc3MnLFxuICAgICAgICAgICksXG4gICAgICAgICAgYXdzX2lhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcbiAgICAgICAgICAgICdBV1NLZXlNYW5hZ2VtZW50U2VydmljZVBvd2VyVXNlcicsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhd3NfaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgICAgJ0FtYXpvbkVLU0NsdXN0ZXJQb2xpY3knLFxuICAgICAgICAgICksXG4gICAgICAgICAgYXdzX2lhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcbiAgICAgICAgICAgICdTZWNyZXRzTWFuYWdlclJlYWRXcml0ZScsXG4gICAgICAgICAgKSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIHRoaXMuYXNnID0gbmV3IGF3c19hdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwKFxuICAgICAgdGhpcyxcbiAgICAgICdXaW5kb3dzSW5zdGFuY2VzQ2FwYWNpdHknLFxuICAgICAge1xuICAgICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgICAgcm9sZTogdGhpcy53aW5kb3dzV29ya2Vyc1JvbGUsXG4gICAgICAgIG1pbkNhcGFjaXR5OiAyLFxuICAgICAgICBzZWN1cml0eUdyb3VwOiB0aGlzLm5vZGVzU2csXG4gICAgICAgIG1heENhcGFjaXR5OiAxMCxcbiAgICAgICAgaW5zdGFuY2VUeXBlOiBwcm9wcy5pbnN0YW5jZVR5cGUsXG4gICAgICAgIG1hY2hpbmVJbWFnZTogd2luZG93c19tYWNoaW5lSW1hZ2UsXG4gICAgICB9LFxuICAgICk7XG5cbiAgICB0aGlzLmFzZ1Jlc291cmNlID0gdGhpcy5hc2cubm9kZS5jaGlsZHJlbi5maW5kKFxuICAgICAgKGMpID0+XG4gICAgICAgIChjIGFzIENmblJlc291cmNlKS5jZm5SZXNvdXJjZVR5cGUgPT09XG4gICAgICAgICdBV1M6OkF1dG9TY2FsaW5nOjpBdXRvU2NhbGluZ0dyb3VwJyxcbiAgICApIGFzIGF3c19hdXRvc2NhbGluZy5DZm5BdXRvU2NhbGluZ0dyb3VwO1xuICB9XG5cbiAgYWRkVXNlckRhdGEoLi4uY29tbWFuZHM6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5hc2cuYWRkVXNlckRhdGEoLi4uY29tbWFuZHMpO1xuICB9XG5cbiAgYWRkQWREZXBlbmRlbmN5KFxuICAgIGFkUGFyYW1ldGVyc1N0b3JlOiBza3lsaWdodC5hdXRoZW50aWNhdGlvbi5JQXdzTWFuYWdlZE1pY3Jvc29mdEFkUGFyYW1ldGVycyxcbiAgKSB7XG4gICAgY29uc3Qgc2VjcmV0TmFtZSA9IGF3c19zc20uU3RyaW5nUGFyYW1ldGVyLnZhbHVlRm9yU3RyaW5nUGFyYW1ldGVyKFxuICAgICAgdGhpcyxcbiAgICAgIGAvJHthZFBhcmFtZXRlcnNTdG9yZS5uYW1lc3BhY2V9LyR7YWRQYXJhbWV0ZXJzU3RvcmUuc2VjcmV0UG9pbnRlcn1gLFxuICAgICk7XG5cbiAgICB0aGlzLmFkZFVzZXJEYXRhKGBcblx0XHRcdCNkb21haW4gam9pbiB3aXRoIHNlY3JldCBmcm9tIHNlY3JldCBtYW5hZ2VyXG5cdFx0XHRbc3RyaW5nXSRTZWNyZXRBRCAgPSBcIiR7c2VjcmV0TmFtZX1cIlxuXHRcdFx0JFNlY3JldE9iaiA9IEdldC1TRUNTZWNyZXRWYWx1ZSAtU2VjcmV0SWQgJFNlY3JldEFEXG5cdFx0XHRbUFNDdXN0b21PYmplY3RdJFNlY3JldCA9ICgkU2VjcmV0T2JqLlNlY3JldFN0cmluZyAgfCBDb252ZXJ0RnJvbS1Kc29uKVxuXHRcdFx0JHBhc3N3b3JkICAgPSAkU2VjcmV0LlBhc3N3b3JkIHwgQ29udmVydFRvLVNlY3VyZVN0cmluZyAtYXNQbGFpblRleHQgLUZvcmNlXG5cdFx0XHQkdXNlcm5hbWUgICA9ICRTZWNyZXQuVXNlcklEICsgXCJAXCIgKyAkU2VjcmV0LkRvbWFpblxuXHRcdFx0JGNyZWRlbnRpYWwgPSBOZXctT2JqZWN0IFN5c3RlbS5NYW5hZ2VtZW50LkF1dG9tYXRpb24uUFNDcmVkZW50aWFsKCR1c2VybmFtZSwkcGFzc3dvcmQpXG5cdFx0XHRBZGQtQ29tcHV0ZXIgLURvbWFpbk5hbWUgJFNlY3JldC5Eb21haW4gLUNyZWRlbnRpYWwgJGNyZWRlbnRpYWxcblx0XHRcdFJlc3RhcnQtQ29tcHV0ZXIgLUZvcmNlXG5cdFx0YCk7XG4gIH1cblxuICBydW5Qb3dlclNoZWxsU1NNRG9jdW1lbnQobmFtZTogc3RyaW5nLCBjb21tYW5kczogc3RyaW5nW10pIHtcbiAgICBuZXcgYXdzX3NzbS5DZm5Bc3NvY2lhdGlvbih0aGlzLCBuYW1lLCB7XG4gICAgICBuYW1lOiAnQVdTLVJ1blBvd2VyU2hlbGxTY3JpcHQnLFxuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICBjb21tYW5kczogY29tbWFuZHMsXG4gICAgICB9LFxuICAgICAgdGFyZ2V0czogW1xuICAgICAgICB7XG4gICAgICAgICAga2V5OiAndGFnOmF3czphdXRvc2NhbGluZzpncm91cE5hbWUnLFxuICAgICAgICAgIHZhbHVlczogW3RoaXMuYXNnLmF1dG9TY2FsaW5nR3JvdXBOYW1lXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICBnTVNBV2ViSG9va0F1dG9JbnN0YWxsKFxuICAgIGVrc0NsdXN0ZXI6IGF3c19la3MuQ2x1c3RlcixcbiAgICBwcml2YXRlU2lnbmVyTmFtZTogc3RyaW5nLFxuICAgIGF3c2FjY291bnRpZDogc3RyaW5nLFxuICAgIGF3c3JlZ2lvbjogc3RyaW5nLFxuICApIHtcbiAgICBjb25zdCBjZXJ0bWFuYWdlciA9IG5ldyBhd3NfaWFtLk1hbmFnZWRQb2xpY3kodGhpcywgJ3dlYkhvb2tFQ1InLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IFdlYkhvb2snLFxuICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICBuZXcgYXdzX2lhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogYXdzX2lhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICAgJ2VjcjpDcmVhdGVSZXBvc2l0b3J5JyxcbiAgICAgICAgICAgICdlY3I6RGVzY3JpYmVJbWFnZXMnLFxuICAgICAgICAgICAgJ2VjcjpHZXRBdXRob3JpemF0aW9uVG9rZW4nLFxuICAgICAgICAgICAgJ2VjcjpHZXREb3dubG9hZFVybEZvckxheWVyJyxcbiAgICAgICAgICAgICdlY3I6QmF0Y2hHZXRJbWFnZScsXG4gICAgICAgICAgICAnZWNyOkJhdGNoQ2hlY2tMYXllckF2YWlsYWJpbGl0eScsXG4gICAgICAgICAgICAnZWNyOkdldERvd25sb2FkVXJsRm9yTGF5ZXInLFxuICAgICAgICAgICAgJ2VjcjpQdXRJbWFnZScsXG4gICAgICAgICAgICAnZWNyOkluaXRpYXRlTGF5ZXJVcGxvYWQnLFxuICAgICAgICAgICAgJ2VjcjpVcGxvYWRMYXllclBhcnQnLFxuICAgICAgICAgICAgJ2VjcjpDb21wbGV0ZUxheWVyVXBsb2FkJyxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogWydhcm46YXdzOmVjcjoqOio6cmVwb3NpdG9yeS9jZXJ0bWFuYWdlci1jYS1jb250cm9sbGVyJ10sXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlQ2x1c3RlciA9IG5ldyBhd3NfaWFtLk1hbmFnZWRQb2xpY3koXG4gICAgICB0aGlzLFxuICAgICAgJ0FsbG93V2ViSG9va0VLU0NsdXN0ZXInLFxuICAgICAge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IFdlYkhvb2snLFxuICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgbmV3IGF3c19pYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgIGVmZmVjdDogYXdzX2lhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgICAgICBhY3Rpb25zOiBbJ2VrczpEZXNjcmliZUNsdXN0ZXInXSxcbiAgICAgICAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOmVrczoqOiR7YXdzYWNjb3VudGlkfTpjbHVzdGVyLypgXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGNvbnN0IGFsbG93QXV0aG9yaXphdGlvblRva2VuID0gbmV3IGF3c19pYW0uTWFuYWdlZFBvbGljeShcbiAgICAgIHRoaXMsXG4gICAgICAnQWxsb3dXZWJIb29rRUNSQ2x1c3RlcicsXG4gICAgICB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgV2ViSG9vaycsXG4gICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICBuZXcgYXdzX2lhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgZWZmZWN0OiBhd3NfaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgICAgIGFjdGlvbnM6IFsnZWNyOkdldEF1dGhvcml6YXRpb25Ub2tlbiddLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGNvbnN0IG5vZGUgPSBuZXcgc2t5bGlnaHQuY29tcHV0ZS5Eb21haW5XaW5kb3dzTm9kZShcbiAgICAgIHRoaXMsXG4gICAgICAnZWtzV29ya2VyRm9yR01TQScsXG4gICAgICB7XG4gICAgICAgIHZwYzogdGhpcy52cGMsXG4gICAgICAgIHdpbmRvd3NNYWNoaW5lOiBmYWxzZSxcbiAgICAgICAgaWFtTWFuYWdlZFBvbGljaWVzTGlzdDogW1xuICAgICAgICAgIGNlcnRtYW5hZ2VyLFxuICAgICAgICAgIGRlc2NyaWJlQ2x1c3RlcixcbiAgICAgICAgICBhbGxvd0F1dGhvcml6YXRpb25Ub2tlbixcbiAgICAgICAgICBhd3NfaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgICAgJ0FtYXpvblNTTU1hbmFnZWRJbnN0YW5jZUNvcmUnLFxuICAgICAgICAgICksXG4gICAgICAgIF0sXG4gICAgICAgIGFtaU5hbWU6ICcqYW16bjItYW1pLWh2bS14ODZfNjQqJyxcbiAgICAgICAgaW5zdGFuY2VUeXBlOiAndDMuc21hbGwnLFxuICAgICAgfSxcbiAgICApO1xuXG4gICAgdGhpcy5hc2cuY29ubmVjdGlvbnMuYWxsb3dGcm9tKG5vZGUuaW5zdGFuY2UsIGF3c19lYzIuUG9ydC50Y3AoNDQzKSk7XG5cbiAgICBla3NDbHVzdGVyLmF3c0F1dGguYWRkUm9sZU1hcHBpbmcobm9kZS5ub2RlUm9sZSwge1xuICAgICAgZ3JvdXBzOiBbJ3N5c3RlbTptYXN0ZXJzJ10sXG4gICAgICB1c2VybmFtZTogJ2FkbWluJyxcbiAgICB9KTtcblxuICAgIG5vZGUucnVuU2hlbGxDb21tYW5kcyhcbiAgICAgIFtcbiAgICAgICAgJ3N1ZG8gLWknLFxuICAgICAgICAneXVtIGluc3RhbGwgLXkgZ2l0JyxcbiAgICAgICAgJ2dpdCBjbG9uZSBodHRwczovL2dpdGh1Yi5jb20vYXdzLXNhbXBsZXMvYW1hem9uLWVrcy1nbXNhLWFkbWlzc2lvbi13ZWJob29rLWF1dG9pbnN0YWxsJyxcbiAgICAgICAgJ2NkIGFtYXpvbi1la3MtZ21zYS1hZG1pc3Npb24td2ViaG9vay1hdXRvaW5zdGFsbC8nLFxuICAgICAgICBgYmFzaCBpbnN0YWxsYXRpb24uc2ggJHthd3NhY2NvdW50aWR9ICR7YXdzcmVnaW9ufSAke2Vrc0NsdXN0ZXIuY2x1c3Rlck5hbWV9ICR7cHJpdmF0ZVNpZ25lck5hbWV9L215LXNpZ25lciBBTDJgLFxuICAgICAgXSxcbiAgICAgICd3ZWJIb29rSW5zdGFsbGF0aW9uJyxcbiAgICApO1xuICB9XG5cbiAgYWRkU3RvcmFnZURlcGVuZGVuY3koXG4gICAgYWRQYXJhbWV0ZXJzU3RvcmU6IHNreWxpZ2h0LmF1dGhlbnRpY2F0aW9uLklBd3NNYW5hZ2VkTWljcm9zb2Z0QWRQYXJhbWV0ZXJzLFxuICAgIGZzeFBhcmFtZXRlcnNTdG9yZTogc2t5bGlnaHQuc3RvcmFnZS5JRlN4V2luZG93c1BhcmFtZXRlcnMsXG4gICAgZm9sZGVyTmFtZTogc3RyaW5nLFxuICApIHtcbiAgICBjb25zdCBzZWNyZXROYW1lID0gYXdzX3NzbS5TdHJpbmdQYXJhbWV0ZXIudmFsdWVGb3JTdHJpbmdQYXJhbWV0ZXIoXG4gICAgICB0aGlzLFxuICAgICAgYC8ke2FkUGFyYW1ldGVyc1N0b3JlLm5hbWVzcGFjZX0vJHthZFBhcmFtZXRlcnNTdG9yZS5zZWNyZXRQb2ludGVyfWAsXG4gICAgKTtcblxuICAgIGNvbnN0IGZzeEVuZHBvaW50ID0gYXdzX3NzbS5TdHJpbmdQYXJhbWV0ZXIudmFsdWVGb3JTdHJpbmdQYXJhbWV0ZXIoXG4gICAgICB0aGlzLFxuICAgICAgYC8ke2ZzeFBhcmFtZXRlcnNTdG9yZS5uYW1lc3BhY2V9LyR7ZnN4UGFyYW1ldGVyc1N0b3JlLmRuc0VuZHBvaW50fWAsXG4gICAgKTtcblxuICAgIGNvbnN0IHNtYlBhdGggPSBgXFxcXFxcXFwke2ZzeEVuZHBvaW50fVxcXFwke2ZvbGRlck5hbWV9YDtcblxuICAgIGNvbnN0IGNvbW1hbmRzID0gW1xuICAgICAgJyRib290Zml4ID0geycsXG4gICAgICAnJExvY2FsRHJpdmUgPSBHZXQtU21iR2xvYmFsTWFwcGluZycsXG4gICAgICAnaWYgKCRMb2NhbERyaXZlIC1lcSAkbnVsbCknLFxuICAgICAgJ3snLFxuICAgICAgYCBbc3RyaW5nXSRTZWNyZXRBRCAgPSAnJHtzZWNyZXROYW1lfSdgLFxuICAgICAgJyAkU2VjcmV0T2JqID0gR2V0LVNFQ1NlY3JldFZhbHVlIC1TZWNyZXRJZCAkU2VjcmV0QUQnLFxuICAgICAgJyBbUFNDdXN0b21PYmplY3RdJFNlY3JldCA9ICgkU2VjcmV0T2JqLlNlY3JldFN0cmluZyAgfCBDb252ZXJ0RnJvbS1Kc29uKScsXG4gICAgICAnICRwYXNzd29yZCAgID0gJFNlY3JldC5QYXNzd29yZCB8IENvbnZlcnRUby1TZWN1cmVTdHJpbmcgLWFzUGxhaW5UZXh0IC1Gb3JjZScsXG4gICAgICBcIiAkdXNlcm5hbWUgICA9ICRTZWNyZXQuVXNlcklEICsgJ0AnICsgJFNlY3JldC5Eb21haW5cIixcbiAgICAgICcgJGRvbWFpbl9hZG1pbl9jcmVkZW50aWFsID0gTmV3LU9iamVjdCBTeXN0ZW0uTWFuYWdlbWVudC5BdXRvbWF0aW9uLlBTQ3JlZGVudGlhbCgkdXNlcm5hbWUsJHBhc3N3b3JkKScsXG4gICAgICBgIE5ldy1TbWJHbG9iYWxNYXBwaW5nIC1SZW1vdGVQYXRoICcke3NtYlBhdGh9JyAtQ3JlZGVudGlhbCAkZG9tYWluX2FkbWluX2NyZWRlbnRpYWwgLUxvY2FsUGF0aCBHOiAtUGVyc2lzdGVudCAkdHJ1ZSAtUmVxdWlyZVByaXZhY3kgJHRydWUgLUVycm9yQWN0aW9uIFN0b3BgLFxuICAgICAgJ30nLFxuICAgICAgJ30nLFxuICAgICAgJ05ldy1JdGVtIC1JdGVtVHlwZSBEaXJlY3RvcnkgLVBhdGggYzpcXFxcU2NyaXB0cycsXG4gICAgICAnJGJvb3RmaXggfCBzZXQtY29udGVudCBjOlxcXFxTY3JpcHRzXFxcXGJvb3RmaXgucHMxJyxcbiAgICAgICcjIENyZWF0ZSBhIHNjaGVkdWxlZCB0YXNrIG9uIHN0YXJ0dXAgdG8gZXhlY3V0ZSB0aGUgbWFwcGluZycsXG4gICAgICBcIiRhY3Rpb24gPSBOZXctU2NoZWR1bGVkVGFza0FjdGlvbiAtRXhlY3V0ZSAnUG93ZXJzaGVsbC5leGUnIC1Bcmd1bWVudCAnYzpcXFxcc2NyaXB0c1xcXFxib290Zml4LnBzMSdcIixcbiAgICAgICckdHJpZ2dlciA9ICBOZXctU2NoZWR1bGVkVGFza1RyaWdnZXIgLUF0U3RhcnR1cCcsXG4gICAgICBgIFtzdHJpbmddJFNlY3JldEFEICA9ICcke3NlY3JldE5hbWV9J2AsXG4gICAgICAnICRTZWNyZXRPYmogPSBHZXQtU0VDU2VjcmV0VmFsdWUgLVNlY3JldElkICRTZWNyZXRBRCcsXG4gICAgICAnIFtQU0N1c3RvbU9iamVjdF0kU2VjcmV0ID0gKCRTZWNyZXRPYmouU2VjcmV0U3RyaW5nICB8IENvbnZlcnRGcm9tLUpzb24pJyxcbiAgICAgIFwiICR1c2VybmFtZSAgID0gJFNlY3JldC5Vc2VySUQgKyAnQCcgKyAkU2VjcmV0LkRvbWFpblwiLFxuICAgICAgXCJSZWdpc3Rlci1TY2hlZHVsZWRUYXNrIC1BY3Rpb24gJGFjdGlvbiAtVHJpZ2dlciAkdHJpZ2dlciAtVGFza05hbWUgJ1NtYkdsb2JhbE1hcHBpbmcnIC1EZXNjcmlwdGlvbiAnTWFwcGluZyB0aGUgU01CIHNoYXJlIGFuZCBhZGRpbmcgbWFjaGluZSB0byBnTVNBJyAtUnVuTGV2ZWwgSGlnaGVzdCAtVXNlciAkdXNlcm5hbWUgLVBhc3N3b3JkICRTZWNyZXQuUGFzc3dvcmRcIixcbiAgICAgICcjIFJ1bm5pbmcgdGhlIGJvb3QgZml4IG5vdycsXG4gICAgICAnJiAkYm9vdGZpeCcsXG4gICAgICAnJyxcbiAgICBdO1xuICAgIHRoaXMucnVuUG93ZXJTaGVsbFNTTURvY3VtZW50KCdTTUJHbG9iYWxNYXBwaW5nJywgY29tbWFuZHMpO1xuICB9XG5cbiAgYWRkRUtTRGVwZW5kZW5jeShla3NDbHVzdGVyOiBhd3NfZWtzLkNsdXN0ZXIpIHtcbiAgICBjb25zdCBjb21tYW5kcyA9IFtcbiAgICAgICcjIEpvaW5pbmcgRUtTIENsdXN0ZXInLFxuICAgICAgXCJbc3RyaW5nXSRFS1NCb290c3RyYXBTY3JpcHRGaWxlID0gJ0M6XFxcXFByb2dyYW0gRmlsZXNcXFxcQW1hem9uXFxcXEVLU1xcXFxTdGFydC1FS1NCb290c3RyYXAucHMxJ1wiLFxuICAgICAgYHBvd2Vyc2hlbGwgLUZpbGUgJEVLU0Jvb3RzdHJhcFNjcmlwdEZpbGUgLUVLU0NsdXN0ZXJOYW1lICcke2Vrc0NsdXN0ZXIuY2x1c3Rlck5hbWV9J2AsXG4gICAgXTtcbiAgICB0aGlzLnJ1blBvd2VyU2hlbGxTU01Eb2N1bWVudCgnRUtTQm9vdHN0cmFwJywgY29tbWFuZHMpO1xuICAgIGVrc0NsdXN0ZXIuYXdzQXV0aC5hZGRSb2xlTWFwcGluZyh0aGlzLndpbmRvd3NXb3JrZXJzUm9sZSwge1xuICAgICAgZ3JvdXBzOiBbXG4gICAgICAgICdzeXN0ZW06Ym9vdHN0cmFwcGVycycsXG4gICAgICAgICdzeXN0ZW06bm9kZXMnLFxuICAgICAgICAnZWtzOmt1YmUtcHJveHktd2luZG93cycsXG4gICAgICBdLFxuICAgICAgdXNlcm5hbWU6ICdzeXN0ZW06bm9kZTp7e0VDMlByaXZhdGVETlNOYW1lfX0nLFxuICAgIH0pO1xuICAgIGVrc0NsdXN0ZXIuY29ubmVjdEF1dG9TY2FsaW5nR3JvdXBDYXBhY2l0eSh0aGlzLmFzZywge1xuICAgICAgYm9vdHN0cmFwRW5hYmxlZDogZmFsc2UsIC8vV2luZG93cyBCb290c3RyYXAgZG9uZSBtYW51YWxseVxuICAgIH0pO1xuICB9XG5cbiAgYWRkTG9jYWxDcmVkRmlsZShcbiAgICBhZFBhcmFtZXRlcnNTdG9yZTogc2t5bGlnaHQuYXV0aGVudGljYXRpb24uSUF3c01hbmFnZWRNaWNyb3NvZnRBZFBhcmFtZXRlcnMsXG4gICAgQURHcm91cE5hbWU6IHN0cmluZyxcbiAgICBBY2NvdW50TmFtZTogc3RyaW5nLFxuICApIHtcbiAgICBjb25zdCBzZWNyZXROYW1lID0gYXdzX3NzbS5TdHJpbmdQYXJhbWV0ZXIudmFsdWVGb3JTdHJpbmdQYXJhbWV0ZXIoXG4gICAgICB0aGlzLFxuICAgICAgYC8ke2FkUGFyYW1ldGVyc1N0b3JlLm5hbWVzcGFjZX0vJHthZFBhcmFtZXRlcnNTdG9yZS5zZWNyZXRQb2ludGVyfWAsXG4gICAgKTtcblxuICAgIGNvbnN0IGNvbW1hbmRzID0gW1xuICAgICAgJyMgR2V0dGluZyBBRCBQYXNzd29yZCcsXG4gICAgICBgW3N0cmluZ10kU2VjcmV0QUQgID0gJyR7c2VjcmV0TmFtZX0nYCxcbiAgICAgICckU2VjcmV0T2JqID0gR2V0LVNFQ1NlY3JldFZhbHVlIC1TZWNyZXRJZCAkU2VjcmV0QUQnLFxuICAgICAgJ1tQU0N1c3RvbU9iamVjdF0kU2VjcmV0ID0gKCRTZWNyZXRPYmouU2VjcmV0U3RyaW5nICB8IENvbnZlcnRGcm9tLUpzb24pJyxcbiAgICAgICckcGFzc3dvcmQgICA9ICRTZWNyZXQuUGFzc3dvcmQgfCBDb252ZXJ0VG8tU2VjdXJlU3RyaW5nIC1hc1BsYWluVGV4dCAtRm9yY2UnLFxuICAgICAgXCIkdXNlcm5hbWUgICA9ICRTZWNyZXQuVXNlcklEICsgJ0AnICsgJFNlY3JldC5Eb21haW5cIixcbiAgICAgICckZG9tYWluX2FkbWluX2NyZWRlbnRpYWwgPSBOZXctT2JqZWN0IFN5c3RlbS5NYW5hZ2VtZW50LkF1dG9tYXRpb24uUFNDcmVkZW50aWFsKCR1c2VybmFtZSwkcGFzc3dvcmQpJyxcbiAgICAgICdBZGQtV2luZG93c0ZlYXR1cmUgUlNBVC1BRC1Qb3dlclNoZWxsJyxcbiAgICAgICdJbnN0YWxsLVBhY2thZ2VQcm92aWRlciBOdUdldCAtRm9yY2UnLFxuICAgICAgJ0luc3RhbGwtTW9kdWxlIENyZWRlbnRpYWxTcGVjIC1Gb3JjZScsXG4gICAgICAnU2V0LVBTUmVwb3NpdG9yeSBQU0dhbGxlcnkgLUluc3RhbGxhdGlvblBvbGljeSBUcnVzdGVkJyxcbiAgICAgIGBOZXctQURHcm91cCAtTmFtZSBcIiR7QURHcm91cE5hbWV9IEFEIEdyb3VwXCIgLVNhbUFjY291bnROYW1lICR7QURHcm91cE5hbWV9XCJcIiAtR3JvdXBTY29wZSBEb21haW5Mb2NhbCAtQ3JlZGVudGlhbCAkZG9tYWluX2FkbWluX2NyZWRlbnRpYWxgLFxuICAgICAgYE5ldy1BRFNlcnZpY2VBY2NvdW50IC1OYW1lIFwiJHtBY2NvdW50TmFtZX1cIiAtRG5zSG9zdE5hbWUgXCIke0FjY291bnROYW1lfS4kU2VjcmV0LkRvbWFpblwiIC1TZXJ2aWNlUHJpbmNpcGFsTmFtZXMgXCJob3N0LyR7QWNjb3VudE5hbWV9XCIsIFwiaG9zdC8ke0FjY291bnROYW1lfS4kU2VjcmV0LkRvbWFpblwiIC1QcmluY2lwYWxzQWxsb3dlZFRvUmV0cmlldmVNYW5hZ2VkUGFzc3dvcmQgXCIke0FER3JvdXBOYW1lfVwiIC1DcmVkZW50aWFsICRkb21haW5fYWRtaW5fY3JlZGVudGlhbGAsXG4gICAgICBgQWRkLUFER3JvdXBNZW1iZXIgLUlkZW50aXR5ICcke0FER3JvdXBOYW1lfScgLU1lbWJlcnMgJGVudjpjb21wdXRlcm5hbWUkIC1DcmVkZW50aWFsICRkb21haW5fYWRtaW5fY3JlZGVudGlhbGAsXG4gICAgICAnIyBTYXZlcyB0aGUgY3JlZCBmaWxlIHRvIEM6XFxcXFByb2dyYW1EYXRhXFxcXERvY2tlclxcXFxDcmVkZW50aWFsU3BlY3MgKGRlZmF1bHQpJyxcbiAgICAgICcjSGVyZSB1cGxvYWQgdG8gUzMgdGhlIENyZWRGaWxlJyxcbiAgICAgICckYm9vdGZpeCA9IHsnLFxuICAgICAgYE5ldy1DcmVkZW50aWFsU3BlYyAtQWNjb3VudE5hbWUgJHtBY2NvdW50TmFtZX1gLFxuICAgICAgJ30nLFxuICAgICAgJyMgU2NoZWR1bGluZyBvbmJvb3QnLFxuICAgICAgJyR0cmlnZ2VyID0gIE5ldy1TY2hlZHVsZWRUYXNrVHJpZ2dlciAtQXRTdGFydHVwJyxcbiAgICAgICckYm9vdGZpeCB8IHNldC1jb250ZW50IGM6XFxcXFNjcmlwdHNcXFxcZ01TQS5wczEnLFxuICAgICAgXCIkYWN0aW9uID0gTmV3LVNjaGVkdWxlZFRhc2tBY3Rpb24gLUV4ZWN1dGUgJ1Bvd2Vyc2hlbGwuZXhlJyAtQXJndW1lbnQgJ2M6XFxcXHNjcmlwdHNcXFxcZ01TQS5wczEnXCIsXG4gICAgICBcIlJlZ2lzdGVyLVNjaGVkdWxlZFRhc2sgLUFjdGlvbiAkYWN0aW9uIC1UcmlnZ2VyICR0cmlnZ2VyIC1UYXNrTmFtZSAnQ3JlYXRlQ3JlZFNwZWNGaWxlJyAtRGVzY3JpcHRpb24gJ0NyZWF0ZUNyZWRGaWxlIGFuZCBzYXZlcyBpdCBpbiBkZWZhdWx0IGZvbGRlcicgLVJ1bkxldmVsIEhpZ2hlc3QgLVVzZXIgJHVzZXJuYW1lIC1QYXNzd29yZCAkU2VjcmV0LlBhc3N3b3JkXCIsXG4gICAgICAnIyBSZWJvb3QgdG8gYXBwbHkgY2hhbmdlcycsXG4gICAgICAnUmVzdGFydC1Db21wdXRlciAtRm9yY2UnLFxuICAgICAgJycsXG4gICAgXTtcblxuICAgIHRoaXMucnVuUG93ZXJTaGVsbFNTTURvY3VtZW50KCdnTVNBX0FEX0dyb3VwX0NyZWRGaWxlJywgY29tbWFuZHMpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./windows-node"), exports);
|
|
18
|
+
__exportStar(require("./eks"), exports);
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2t5bGlnaHQtY29tcHV0ZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQStCO0FBQy9CLHdDQUFzQiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vd2luZG93cy1ub2RlJztcbmV4cG9ydCAqIGZyb20gJy4vZWtzJzsiXX0=
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
5
|
+
* with the License. A copy of the License is located at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
10
|
+
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
11
|
+
* and limitations under the License.
|
|
12
|
+
*/
|
|
13
|
+
import { aws_iam as iam, aws_ec2 as ec2, aws_secretsmanager } from 'aws-cdk-lib';
|
|
14
|
+
import { ISecret } from 'aws-cdk-lib/aws-secretsmanager';
|
|
15
|
+
import { Construct } from 'constructs';
|
|
16
|
+
/**
|
|
17
|
+
* The properties of an DomainWindowsNodeProps, requires Active Directory parameter to read the Secret to join the domain
|
|
18
|
+
* Default setting: Domain joined, m5.2xlarge, latest windows, Managed by SSM.
|
|
19
|
+
*/
|
|
20
|
+
export interface IDomainWindowsNodeProps {
|
|
21
|
+
/**
|
|
22
|
+
* IAM Instance role permissions
|
|
23
|
+
* @default - 'AmazonSSMManagedInstanceCore, AmazonSSMDirectoryServiceAccess'.
|
|
24
|
+
*/
|
|
25
|
+
iamManagedPoliciesList?: iam.IManagedPolicy[];
|
|
26
|
+
/**
|
|
27
|
+
* The EC2 Instance type to use
|
|
28
|
+
*
|
|
29
|
+
* @default - 'm5.2xlarge'.
|
|
30
|
+
*/
|
|
31
|
+
instanceType?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Choose if to launch the instance in Private or in Public subnet
|
|
34
|
+
* Private = Subnet that routes to the internet, but not vice versa.
|
|
35
|
+
* Public = Subnet that routes to the internet and vice versa.
|
|
36
|
+
* @default - Private.
|
|
37
|
+
*/
|
|
38
|
+
usePrivateSubnet?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The name of the AMI to search in SSM (ec2.LookupNodeImage) supports Regex
|
|
41
|
+
* @default - 'Windows_Server-2022-English-Full'
|
|
42
|
+
*/
|
|
43
|
+
amiName?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Specific UserData to use
|
|
46
|
+
*
|
|
47
|
+
* The UserData may still be mutated after creation.
|
|
48
|
+
*
|
|
49
|
+
* @default - 'undefined'
|
|
50
|
+
*/
|
|
51
|
+
userData?: string;
|
|
52
|
+
domainName?: string;
|
|
53
|
+
passwordObject?: aws_secretsmanager.ISecret;
|
|
54
|
+
/**
|
|
55
|
+
* @default - 'true'
|
|
56
|
+
*/
|
|
57
|
+
windowsMachine?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* The VPC to use
|
|
60
|
+
*/
|
|
61
|
+
vpc: ec2.IVpc;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A Domain Windows Node represents one Windows EC2 instance configured with Active Directory.
|
|
65
|
+
*
|
|
66
|
+
* The DomainWindowsNode can be customized to different instance sizes and additional permissions set just like any other EC2 Instance.
|
|
67
|
+
* You can use this construct to run elevated domain tasks with domain permissions or run your application in a single instance setup.
|
|
68
|
+
*
|
|
69
|
+
* The machine will be joined to the provided Active Directory domain using a custom CloudFormation bootstrap that will wait until the required reboot to join the domain. Then it will register the machine in SSM and pull tasks from the SSM State manager.
|
|
70
|
+
*
|
|
71
|
+
* You can send tasks to that machine using the provided methods: runPsCommands() and runPSwithDomainAdmin()
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
export declare class DomainWindowsNode extends Construct {
|
|
75
|
+
readonly instance: ec2.Instance;
|
|
76
|
+
readonly nodeRole: iam.Role;
|
|
77
|
+
readonly vpc: ec2.IVpc;
|
|
78
|
+
readonly passwordObject?: ISecret;
|
|
79
|
+
constructor(scope: Construct, id: string, props: IDomainWindowsNodeProps);
|
|
80
|
+
/**
|
|
81
|
+
* Running bash scripts on the Node with SSM Document.
|
|
82
|
+
* i.e: runPsCommands(["echo 'hello world'", "echo 'Second command'"], "myScript")
|
|
83
|
+
*/
|
|
84
|
+
runShellCommands(ShellCommands: string[], id: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Running PowerShell scripts on the Node with SSM Document.
|
|
87
|
+
* i.e: runPsCommands(["Write-host 'Hello world'", "Write-host 'Second command'"], "myScript")
|
|
88
|
+
*/
|
|
89
|
+
runPsCommands(psCommands: string[], id: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Open the security group of the Node Node to specific IP address on port 3389
|
|
92
|
+
* i.e: openRDP("1.1.1.1/32")
|
|
93
|
+
*/
|
|
94
|
+
openRDP(ipaddress: string): void;
|
|
95
|
+
/**
|
|
96
|
+
* Running PowerShell scripts on the Node with SSM Document with Domain Admin (Using the Secret used to join the machine to the domain)
|
|
97
|
+
* i.e: runPsCommands(["Write-host 'Hello world'", "Write-host 'Second command'"], "myScript")
|
|
98
|
+
* The provided psCommands will be stored in C:\Scripts and will be run with scheduled task with Domain Admin rights
|
|
99
|
+
*/
|
|
100
|
+
runPSwithDomainAdmin(psCommands: string[], id: string): void;
|
|
101
|
+
startInstance(): void;
|
|
102
|
+
}
|