serverless-spy 0.0.35 → 0.0.37
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 +236 -9
- package/API.md +161 -0
- package/cli/cli.ts +145 -75
- package/cli/icons/Arch_AWS-Lambda_16.svg +18 -0
- package/cli/icons/Arch_Amazon-DynamoDB_16.svg +18 -0
- package/cli/icons/Arch_Amazon-EventBridge_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Notification-Service_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Queue-Service_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Storage-Service_16.svg +18 -0
- package/cli/index.html +84 -25
- package/cli/node_modules/commander/LICENSE +22 -0
- package/cli/node_modules/commander/Readme.md +1114 -0
- package/cli/node_modules/commander/esm.mjs +16 -0
- package/cli/node_modules/commander/index.js +27 -0
- package/cli/node_modules/commander/lib/argument.js +147 -0
- package/cli/node_modules/commander/lib/command.js +2161 -0
- package/cli/node_modules/commander/lib/error.js +45 -0
- package/cli/node_modules/commander/lib/help.js +406 -0
- package/cli/node_modules/commander/lib/option.js +324 -0
- package/cli/node_modules/commander/lib/suggestSimilar.js +100 -0
- package/cli/node_modules/commander/package-support.json +16 -0
- package/cli/node_modules/commander/package.json +80 -0
- package/cli/node_modules/commander/typings/index.d.ts +879 -0
- package/cli/package.json +23 -0
- package/cli/sampleData.ts +518 -0
- package/cli/style.css +66 -42
- package/cli/webServerlessSpy.ts +461 -0
- package/common/SpyEventSender.ts +291 -0
- package/common/getWebSocketUrl.ts +21 -4
- package/common/spyEvents/EventBridgeBaseSpyEvent.ts +13 -0
- package/common/spyEvents/EventBridgeRuleSpyEvent.ts +2 -7
- package/common/spyEvents/EventBridgeSpyEvent.ts +2 -7
- package/common/spyEvents/FunctionBaseSpyEvent.ts +7 -0
- package/common/spyEvents/FunctionConsole.ts +5 -0
- package/common/spyEvents/FunctionConsoleSpyEvent.ts +5 -8
- package/common/spyEvents/FunctionResponseSpyEvent.ts +2 -5
- package/common/spyEvents/SnsSpyEventBase.ts +11 -0
- package/common/spyEvents/SnsSubscriptionSpyEvent.ts +3 -9
- package/common/spyEvents/SnsTopicSpyEvent.ts +3 -9
- package/dist/releasetag.txt +1 -1
- package/extension/interceptor.ts +107 -27
- package/functions/sendMessage.ts +4 -2
- package/functions/sqsSubscriptionAndDropAllMessages.ts +3 -0
- package/lib/cli/cli.js +124 -65
- package/lib/cli/cli.mjs +125 -66
- package/lib/cli/sampleData.d.ts +892 -0
- package/lib/cli/sampleData.js +481 -0
- package/lib/cli/sampleData.mjs +478 -0
- package/lib/cli/webServerlessSpy.js +5516 -0
- package/lib/cli/webServerlessSpy.js.map +7 -0
- package/lib/common/SpyEventSender.d.ts +17 -0
- package/lib/common/SpyEventSender.js +227 -0
- package/lib/common/SpyEventSender.mjs +223 -0
- package/lib/common/getWebSocketUrl.d.ts +1 -1
- package/lib/common/getWebSocketUrl.js +19 -7
- package/lib/common/getWebSocketUrl.mjs +17 -5
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.d.ts +9 -0
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.js +3 -0
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.mjs +2 -0
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.d.ts +2 -7
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.js +1 -1
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/EventBridgeSpyEvent.d.ts +2 -7
- package/lib/common/spyEvents/EventBridgeSpyEvent.js +1 -1
- package/lib/common/spyEvents/EventBridgeSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/FunctionBaseSpyEvent.d.ts +6 -0
- package/lib/common/spyEvents/FunctionBaseSpyEvent.js +3 -0
- package/lib/common/spyEvents/FunctionBaseSpyEvent.mjs +2 -0
- package/lib/common/spyEvents/FunctionConsole.d.ts +5 -0
- package/lib/common/spyEvents/FunctionConsole.js +3 -0
- package/lib/common/spyEvents/FunctionConsole.mjs +2 -0
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.d.ts +4 -8
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.js +1 -1
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/FunctionResponseSpyEvent.d.ts +2 -5
- package/lib/common/spyEvents/FunctionResponseSpyEvent.js +1 -1
- package/lib/common/spyEvents/FunctionResponseSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/SnsSpyEventBase.d.ts +10 -0
- package/lib/common/spyEvents/SnsSpyEventBase.js +3 -0
- package/lib/common/spyEvents/SnsSpyEventBase.mjs +2 -0
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.d.ts +2 -9
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.js +1 -1
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/SnsTopicSpyEvent.d.ts +2 -9
- package/lib/common/spyEvents/SnsTopicSpyEvent.js +1 -1
- package/lib/common/spyEvents/SnsTopicSpyEvent.mjs +1 -1
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js +10793 -23825
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js.map +4 -4
- package/lib/listener/ServerlessSpyListenerParams.d.ts +1 -0
- package/lib/listener/ServerlessSpyListenerParams.js +1 -1
- package/lib/listener/ServerlessSpyListenerParams.mjs +1 -1
- package/lib/listener/SpyHandlers.ts.d.ts +30 -2
- package/lib/listener/SpyHandlers.ts.js +1 -1
- package/lib/listener/SpyHandlers.ts.mjs +1 -1
- package/lib/listener/WsListener.d.ts +4 -21
- package/lib/listener/WsListener.js +21 -13
- package/lib/listener/WsListener.mjs +22 -14
- package/lib/src/ServerlessSpy.d.ts +44 -14
- package/lib/src/ServerlessSpy.js +228 -86
- package/lib/src/ServerlessSpy.mjs +227 -85
- package/lib/src/common/envVariableNames.d.ts +6 -2
- package/lib/src/common/envVariableNames.js +6 -2
- package/lib/src/common/envVariableNames.mjs +6 -2
- package/listener/ServerlessSpyListenerParams.ts +1 -0
- package/listener/SpyHandlers.ts.ts +70 -9
- package/listener/WsListener.ts +39 -24
- package/package.json +5 -3
- package/cli/serverlessSpy.js +0 -73
- package/cli/ws.ts +0 -79
- package/common/publishSpyEvent.ts +0 -269
- package/lib/cli/ws.d.ts +0 -1
- package/lib/cli/ws.js +0 -68
- package/lib/cli/ws.mjs +0 -66
- package/lib/common/publishSpyEvent.d.ts +0 -4
- package/lib/common/publishSpyEvent.js +0 -211
- package/lib/common/publishSpyEvent.mjs +0 -205
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ApiGatewayManagementApi } from '@aws-sdk/client-apigatewaymanagementapi';
|
|
2
|
+
import { AttributeValue, DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
export declare class SpyEventSender {
|
|
4
|
+
ddb: DynamoDBClient;
|
|
5
|
+
debugMode: boolean;
|
|
6
|
+
apigwManagementApi: ApiGatewayManagementApi;
|
|
7
|
+
connections: Record<string, AttributeValue>[] | undefined;
|
|
8
|
+
constructor(params?: {
|
|
9
|
+
log: (message: string, ...optionalParams: any[]) => void;
|
|
10
|
+
logError: (message: string, ...optionalParams: any[]) => void;
|
|
11
|
+
});
|
|
12
|
+
publishSpyEvent(event: any): Promise<void>;
|
|
13
|
+
private postData;
|
|
14
|
+
private getSpyEventType;
|
|
15
|
+
private log;
|
|
16
|
+
private logError;
|
|
17
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpyEventSender = void 0;
|
|
4
|
+
const client_apigatewaymanagementapi_1 = require("@aws-sdk/client-apigatewaymanagementapi");
|
|
5
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
6
|
+
const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
|
|
7
|
+
const envVariableNames_1 = require("../src/common/envVariableNames");
|
|
8
|
+
class SpyEventSender {
|
|
9
|
+
constructor(params) {
|
|
10
|
+
this.ddb = new client_dynamodb_1.DynamoDBClient({
|
|
11
|
+
region: process.env.AWS_REGION,
|
|
12
|
+
});
|
|
13
|
+
this.debugMode = process.env[envVariableNames_1.envVariableNames.SSPY_DEBUG] === 'true';
|
|
14
|
+
this.apigwManagementApi = new client_apigatewaymanagementapi_1.ApiGatewayManagementApi({
|
|
15
|
+
apiVersion: '2018-11-29',
|
|
16
|
+
endpoint: process.env[envVariableNames_1.envVariableNames.SSPY_WS_ENDPOINT],
|
|
17
|
+
});
|
|
18
|
+
if (params?.log) {
|
|
19
|
+
this.log = params.log;
|
|
20
|
+
}
|
|
21
|
+
if (params?.logError) {
|
|
22
|
+
this.logError = params.logError;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async publishSpyEvent(event) {
|
|
26
|
+
this.log('Event', JSON.stringify(event));
|
|
27
|
+
const mapping = JSON.parse(process.env[envVariableNames_1.envVariableNames.SSPY_INFRA_MAPPING]);
|
|
28
|
+
this.log('ARN to names mapping', JSON.stringify(mapping));
|
|
29
|
+
let connectionData;
|
|
30
|
+
const scanParams = new client_dynamodb_1.ScanCommand({
|
|
31
|
+
TableName: process.env[envVariableNames_1.envVariableNames.SSPY_WS_TABLE_NAME],
|
|
32
|
+
ProjectionExpression: 'connectionId',
|
|
33
|
+
});
|
|
34
|
+
connectionData = await this.ddb.send(scanParams);
|
|
35
|
+
this.connections = connectionData.Items;
|
|
36
|
+
const postDataPromises = [];
|
|
37
|
+
if (event?.Records && event.Records[0]?.Sns) {
|
|
38
|
+
//console.log('*** SNS ***');
|
|
39
|
+
const eventSns = event;
|
|
40
|
+
for (const record of eventSns.Records) {
|
|
41
|
+
const subscriptionArn = record.EventSubscriptionArn;
|
|
42
|
+
let serviceKey;
|
|
43
|
+
if (mapping[subscriptionArn]) {
|
|
44
|
+
// subscription event that could contain filter based on existing subscription
|
|
45
|
+
serviceKey = mapping[subscriptionArn];
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// catch all subscription
|
|
49
|
+
const topicArn = record.Sns.TopicArn;
|
|
50
|
+
serviceKey = mapping[topicArn];
|
|
51
|
+
}
|
|
52
|
+
let message;
|
|
53
|
+
try {
|
|
54
|
+
message = JSON.parse(record.Sns.Message);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
message = record.Sns.Message;
|
|
58
|
+
}
|
|
59
|
+
const spyEventType = this.getSpyEventType(serviceKey);
|
|
60
|
+
const data = {
|
|
61
|
+
spyEventType,
|
|
62
|
+
message,
|
|
63
|
+
subject: record.Sns.Subject,
|
|
64
|
+
timestamp: record.Sns.Timestamp,
|
|
65
|
+
topicArn: record.Sns.TopicArn,
|
|
66
|
+
messageId: record.Sns.MessageId,
|
|
67
|
+
messageAttributes: record.Sns.MessageAttributes,
|
|
68
|
+
};
|
|
69
|
+
const fluentEvent = {
|
|
70
|
+
data,
|
|
71
|
+
serviceKey,
|
|
72
|
+
};
|
|
73
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (event?.Records && event.Records[0]?.eventSource === 'aws:sqs') {
|
|
77
|
+
//console.log('*** SQS ***');
|
|
78
|
+
const eventSqs = event;
|
|
79
|
+
for (const record of eventSqs.Records) {
|
|
80
|
+
const subscriptionArn = record.eventSourceARN;
|
|
81
|
+
const serviceKey = mapping[subscriptionArn];
|
|
82
|
+
let body;
|
|
83
|
+
try {
|
|
84
|
+
body = JSON.parse(record.body);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
body = record.body;
|
|
88
|
+
}
|
|
89
|
+
const data = {
|
|
90
|
+
spyEventType: 'Sqs',
|
|
91
|
+
body,
|
|
92
|
+
messageAttributes: record.messageAttributes,
|
|
93
|
+
};
|
|
94
|
+
const fluentEvent = {
|
|
95
|
+
data,
|
|
96
|
+
serviceKey,
|
|
97
|
+
};
|
|
98
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (event?.Records && event.Records[0]?.s3) {
|
|
102
|
+
//console.log('*** S3 ***');
|
|
103
|
+
const eventS3 = event;
|
|
104
|
+
for (const record of eventS3.Records) {
|
|
105
|
+
const bucketArn = record.s3.bucket.arn;
|
|
106
|
+
const data = {
|
|
107
|
+
spyEventType: 'S3',
|
|
108
|
+
eventName: record.eventName,
|
|
109
|
+
eventTime: record.eventTime,
|
|
110
|
+
bucket: record.s3.bucket.name,
|
|
111
|
+
key: record.s3.object.key,
|
|
112
|
+
};
|
|
113
|
+
const fluentEvent = {
|
|
114
|
+
data,
|
|
115
|
+
serviceKey: mapping[bucketArn],
|
|
116
|
+
};
|
|
117
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (event.Records && event.Records[0]?.dynamodb) {
|
|
121
|
+
//console.log('*** DYNAMODB ***');
|
|
122
|
+
const eventDynamoDB = event;
|
|
123
|
+
for (const record of eventDynamoDB.Records) {
|
|
124
|
+
let arn = record.eventSourceARN;
|
|
125
|
+
arn = arn.substring(0, arn.indexOf('/stream/'));
|
|
126
|
+
const data = {
|
|
127
|
+
spyEventType: 'DynamoDB',
|
|
128
|
+
eventName: record.eventName,
|
|
129
|
+
newImage: (0, util_dynamodb_1.unmarshall)(record.dynamodb?.NewImage),
|
|
130
|
+
keys: (0, util_dynamodb_1.unmarshall)(record.dynamodb?.Keys),
|
|
131
|
+
oldImage: record.dynamodb?.OldImage
|
|
132
|
+
? (0, util_dynamodb_1.unmarshall)(record.dynamodb?.OldImage)
|
|
133
|
+
: undefined,
|
|
134
|
+
};
|
|
135
|
+
const fluentEvent = {
|
|
136
|
+
data,
|
|
137
|
+
serviceKey: mapping[arn],
|
|
138
|
+
};
|
|
139
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (event.detail &&
|
|
143
|
+
event['detail-type'] &&
|
|
144
|
+
event.version &&
|
|
145
|
+
event.source) {
|
|
146
|
+
//console.log('*** EventBridge ***');
|
|
147
|
+
const eventEb = event;
|
|
148
|
+
const serviceKey = mapping.eventBridge; // the is new lambda for each subscription
|
|
149
|
+
const spyEventType = this.getSpyEventType(serviceKey);
|
|
150
|
+
const message = eventEb.detail;
|
|
151
|
+
const data = {
|
|
152
|
+
spyEventType,
|
|
153
|
+
detail: message,
|
|
154
|
+
detailType: eventEb['detail-type'],
|
|
155
|
+
eventBridgeId: eventEb['id'],
|
|
156
|
+
source: eventEb.source,
|
|
157
|
+
time: eventEb.time,
|
|
158
|
+
account: eventEb.account,
|
|
159
|
+
};
|
|
160
|
+
const fluentEvent = {
|
|
161
|
+
data,
|
|
162
|
+
serviceKey,
|
|
163
|
+
};
|
|
164
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
//console.log('*** OTHER ***');
|
|
168
|
+
const fluentEvent = event;
|
|
169
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
170
|
+
}
|
|
171
|
+
await Promise.all(postDataPromises);
|
|
172
|
+
}
|
|
173
|
+
async postData(spyMessage) {
|
|
174
|
+
this.log('Post spy message', JSON.stringify(spyMessage));
|
|
175
|
+
if (!this.connections) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const postCalls = this.connections.map(async ({ connectionId }) => {
|
|
179
|
+
this.log(`Sending message to client: ${connectionId.S}`);
|
|
180
|
+
try {
|
|
181
|
+
const postToConnectionCommand = new client_apigatewaymanagementapi_1.PostToConnectionCommand({
|
|
182
|
+
ConnectionId: connectionId.S,
|
|
183
|
+
Data: JSON.stringify({
|
|
184
|
+
timestamp: new Date().toISOString(),
|
|
185
|
+
serviceKey: spyMessage.serviceKey,
|
|
186
|
+
data: spyMessage.data,
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
await this.apigwManagementApi.send(postToConnectionCommand);
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
this.logError(`Faild sending spy message to: ${connectionId.S}`, e);
|
|
193
|
+
if (e.$metadata.httpStatusCode === 410) {
|
|
194
|
+
this.log(`Found stale connection, deleting ${connectionId}`);
|
|
195
|
+
const deleteParams = new client_dynamodb_1.DeleteItemCommand({
|
|
196
|
+
TableName: process.env[envVariableNames_1.envVariableNames.SSPY_WS_TABLE_NAME],
|
|
197
|
+
Key: { connectionId },
|
|
198
|
+
});
|
|
199
|
+
await this.ddb.send(deleteParams);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
throw e;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
await Promise.all(postCalls);
|
|
207
|
+
this.log('Send spy message finish');
|
|
208
|
+
}
|
|
209
|
+
getSpyEventType(serviceKey) {
|
|
210
|
+
if (!serviceKey) {
|
|
211
|
+
throw new Error('Missing serviceKey');
|
|
212
|
+
}
|
|
213
|
+
return serviceKey.substring(0, serviceKey.indexOf('#'));
|
|
214
|
+
}
|
|
215
|
+
log(message, ...optionalParams) {
|
|
216
|
+
if (this.debugMode) {
|
|
217
|
+
console.debug('SSPY EXTENSION', message, ...optionalParams);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
logError(message, ...optionalParams) {
|
|
221
|
+
if (this.debugMode) {
|
|
222
|
+
console.error('SSPY EXTENSION', message, ...optionalParams);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.SpyEventSender = SpyEventSender;
|
|
227
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3B5RXZlbnRTZW5kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jb21tb24vU3B5RXZlbnRTZW5kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNEZBR2lEO0FBQ2pELDhEQUtrQztBQUVsQywwREFBb0Q7QUFRcEQscUVBQWtFO0FBVWxFLE1BQWEsY0FBYztJQVd6QixZQUFZLE1BR1g7UUFiRCxRQUFHLEdBQUcsSUFBSSxnQ0FBYyxDQUFDO1lBQ3ZCLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVU7U0FDL0IsQ0FBQyxDQUFDO1FBQ0gsY0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQWdCLENBQUMsVUFBVSxDQUFDLEtBQUssTUFBTSxDQUFDO1FBQ2hFLHVCQUFrQixHQUFHLElBQUksd0RBQXVCLENBQUM7WUFDL0MsVUFBVSxFQUFFLFlBQVk7WUFDeEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQWdCLENBQUMsZ0JBQWdCLENBQUU7U0FDMUQsQ0FBQyxDQUFDO1FBT0QsSUFBSSxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ2YsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1NBQ3ZCO1FBRUQsSUFBSSxNQUFNLEVBQUUsUUFBUSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUNqQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQVU7UUFDckMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBRXpDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQWdCLENBQUMsa0JBQWtCLENBQUUsQ0FDbEQsQ0FBQztRQUNGLElBQUksQ0FBQyxHQUFHLENB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QU07b0JBQ0wsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7YUFDRjtRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxHQUFHLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRU8sZUFBZSxDQUFDLFVBQWtCO1FBQ3hDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLG9CQUFvQixDQUFDLENBQUM7U0FDdkM7UUFFRCxPQUFPLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRU8sR0FBRyxDQUFDLE9BQWUsRUFBRSxHQUFHLGNBQXFCO1FBQ25ELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNsQixPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFDO1NBQzdEO0lBQ0gsQ0FBQztJQUVPLFFBQVEsQ0FBQyxPQUFlLEVBQUUsR0FBRyxjQUFxQjtRQUN4RCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsR0FBRyxjQUFjLENBQUMsQ0FBQztTQUM3RDtJQUNILENBQUM7Q0FDRjtBQXJRRCx3Q0FxUUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBcGlHYXRld2F5TWFuYWdlbWVudEFwaSxcbiAgUG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1hcGlnYXRld2F5bWFuYWdlbWVudGFwaSc7XG5pbXBvcnQge1xuICBBdHRyaWJ1dGVWYWx1ZSxcbiAgRGVsZXRlSXRlbUNvbW1hbmQsXG4gIER5bmFtb0RCQ2xpZW50LFxuICBTY2FuQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWR5bmFtb2RiJztcblxuaW1wb3J0IHsgdW5tYXJzaGFsbCB9IGZyb20gJ0Bhd3Mtc2RrL3V0aWwtZHluYW1vZGInO1xuaW1wb3J0IHtcbiAgRHluYW1vREJTdHJlYW1FdmVudCxcbiAgUzNFdmVudCxcbiAgU05TRXZlbnQsXG4gIEV2ZW50QnJpZGdlRXZlbnQsXG4gIFNRU0V2ZW50LFxufSBmcm9tICdhd3MtbGFtYmRhJztcbmltcG9ydCB7IGVudlZhcmlhYmxlTmFtZXMgfSBmcm9tICcuLi9zcmMvY29tbW9uL2VudlZhcmlhYmxlTmFtZXMnO1xuaW1wb3J0IHsgRHluYW1vREJTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL0R5bmFtb0RCU3B5RXZlbnQnO1xuaW1wb3J0IHsgRXZlbnRCcmlkZ2VSdWxlU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9FdmVudEJyaWRnZVJ1bGVTcHlFdmVudCc7XG5pbXBvcnQgeyBFdmVudEJyaWRnZVNweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvRXZlbnRCcmlkZ2VTcHlFdmVudCc7XG5pbXBvcnQgeyBTM1NweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvUzNTcHlFdmVudCc7XG5pbXBvcnQgeyBTbnNTdWJzY3JpcHRpb25TcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL1Nuc1N1YnNjcmlwdGlvblNweUV2ZW50JztcbmltcG9ydCB7IFNuc1RvcGljU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9TbnNUb3BpY1NweUV2ZW50JztcbmltcG9ydCB7IFNweU1lc3NhZ2UgfSBmcm9tICcuL3NweUV2ZW50cy9TcHlNZXNzYWdlJztcbmltcG9ydCB7IFNxc1NweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvU3FzU3B5RXZlbnQnO1xuXG5leHBvcnQgY2xhc3MgU3B5RXZlbnRTZW5kZXIge1xuICBkZGIgPSBuZXcgRHluYW1vREJDbGllbnQoe1xuICAgIHJlZ2lvbjogcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTixcbiAgfSk7XG4gIGRlYnVnTW9kZSA9IHByb2Nlc3MuZW52W2VudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVR10gPT09ICd0cnVlJztcbiAgYXBpZ3dNYW5hZ2VtZW50QXBpID0gbmV3IEFwaUdhdGV3YXlNYW5hZ2VtZW50QXBpKHtcbiAgICBhcGlWZXJzaW9uOiAnMjAxOC0xMS0yOScsXG4gICAgZW5kcG9pbnQ6IHByb2Nlc3MuZW52W2VudlZhcmlhYmxlTmFtZXMuU1NQWV9XU19FTkRQT0lOVF0hLFxuICB9KTtcbiAgY29ubmVjdGlvbnM6IFJlY29yZDxzdHJpbmcsIEF0dHJpYnV0ZVZhbHVlPltdIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKHBhcmFtcz86IHtcbiAgICBsb2c6IChtZXNzYWdlOiBzdHJpbmcsIC4uLm9wdGlvbmFsUGFyYW1zOiBhbnlbXSkgPT4gdm9pZDtcbiAgICBsb2dFcnJvcjogKG1lc3NhZ2U6IHN0cmluZywgLi4ub3B0aW9uYWxQYXJhbXM6IGFueVtdKSA9PiB2b2lkO1xuICB9KSB7XG4gICAgaWYgKHBhcmFtcz8ubG9nKSB7XG4gICAgICB0aGlzLmxvZyA9IHBhcmFtcy5sb2c7XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcz8ubG9nRXJyb3IpIHtcbiAgICAgIHRoaXMubG9nRXJyb3IgPSBwYXJhbXMubG9nRXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHB1Ymxpc2hTcHlFdmVudChldmVudDogYW55KSB7XG4gICAgdGhpcy5sb2coJ0V2ZW50JywgSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcblxuICAgIGNvbnN0IG1hcHBpbmcgPSBKU09OLnBhcnNlKFxuICAgICAgcHJvY2Vzcy5lbnZbZW52VmFyaWFibGVOYW1lcy5TU1BZX0lORlJBX01BUFBJTkddIVxuICAgICk7XG4gICAgdGhpcy5sb2coJ0FSTiB0byBuYW1lcyBtYXBwaW5nJywgSlNPTi5zdHJpbmdpZnkobWFwcGluZykpO1xuXG4gICAgbGV0IGNvbm5lY3Rpb25EYXRhO1xuXG4gICAgY29uc3Qgc2NhblBhcmFtcyA9IG5ldyBTY2FuQ29tbWFuZCh7XG4gICAgICBUYWJsZU5hbWU6IHByb2Nlc3MuZW52W2VudlZhcmlhYmxlTmFtZXMuU1NQWV9XU19UQUJMRV9OQU1FXSBhcyBzdHJpbmcsXG4gICAgICBQcm9qZWN0aW9uRXhwcmVzc2lvbjogJ2Nvbm5lY3Rpb25JZCcsXG4gICAgfSk7XG5cbiAgICBjb25uZWN0aW9uRGF0YSA9IGF3YWl0IHRoaXMuZGRiLnNlbmQoc2NhblBhcmFtcyk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb25zID0gY29ubmVjdGlvbkRhdGEuSXRlbXM7XG5cbiAgICBjb25zdCBwb3N0RGF0YVByb21pc2VzOiBQcm9taXNlPGFueT5bXSA9IFtdO1xuXG4gICAgaWYgKGV2ZW50Py5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LlNucykge1xuICAgICAgLy9jb25zb2xlLmxvZygnKioqIFNOUyAqKionKTtcbiAgICAgIGNvbnN0IGV2ZW50U25zID0gZXZlbnQgYXMgU05TRXZlbnQ7XG4gICAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiBldmVudFNucy5SZWNvcmRzKSB7XG4gICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbkFybiA9IHJlY29yZC5FdmVudFN1YnNjcmlwdGlvbkFybjtcblxuICAgICAgICBsZXQgc2VydmljZUtleTogc3RyaW5nO1xuICAgICAgICBpZiAobWFwcGluZ1tzdWJzY3JpcHRpb25Bcm5dKSB7XG4gICAgICAgICAgLy8gc3Vic2NyaXB0aW9uIGV2ZW50IHRoYXQgY291bGQgY29udGFpbiBmaWx0ZXIgYmFzZWQgb24gZXhpc3Rpbmcgc3Vic2NyaXB0aW9uXG4gICAgICAgICAgc2VydmljZUtleSA9IG1hcHBpbmdbc3Vic2NyaXB0aW9uQXJuXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBjYXRjaCBhbGwgc3Vic2NyaXB0aW9uXG4gICAgICAgICAgY29uc3QgdG9waWNBcm4gPSByZWNvcmQuU25zLlRvcGljQXJuO1xuICAgICAgICAgIHNlcnZpY2VLZXkgPSBtYXBwaW5nW3RvcGljQXJuXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBtZXNzYWdlID0gSlNPTi5wYXJzZShyZWNvcmQuU25zLk1lc3NhZ2UpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBtZXNzYWdlID0gcmVjb3JkLlNucy5NZXNzYWdlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3B5RXZlbnRUeXBlID0gdGhpcy5nZXRTcHlFdmVudFR5cGUoc2VydmljZUtleSkgYXNcbiAgICAgICAgICB8ICdGdW5jdGlvblNuc1RvcGljJ1xuICAgICAgICAgIHwgJ0Z1bmN0aW9uU25zU3Vic2NyaXB0aW9uJztcblxuICAgICAgICBjb25zdCBkYXRhOiBTbnNUb3BpY1NweUV2ZW50IHwgU25zU3Vic2NyaXB0aW9uU3B5RXZlbnQgPSB7XG4gICAgICAgICAgc3B5RXZlbnRUeXBlLFxuICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgc3ViamVjdDogcmVjb3JkLlNucy5TdWJqZWN0LFxuICAgICAgICAgIHRpbWVzdGFtcDogcmVjb3JkLlNucy5UaW1lc3RhbXAsXG4gICAgICAgICAgdG9waWNBcm46IHJlY29yZC5TbnMuVG9waWNBcm4sXG4gICAgICAgICAgbWVzc2FnZUlkOiByZWNvcmQuU25zLk1lc3NhZ2VJZCxcbiAgICAgICAgICBtZXNzYWdlQXR0cmlidXRlczogcmVjb3JkLlNucy5NZXNzYWdlQXR0cmlidXRlcyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBzZXJ2aWNlS2V5LFxuICAgICAgICB9O1xuICAgICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2godGhpcy5wb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZXZlbnQ/LlJlY29yZHMgJiYgZXZlbnQuUmVjb3Jkc1swXT8uZXZlbnRTb3VyY2UgPT09ICdhd3M6c3FzJykge1xuICAgICAgLy9jb25zb2xlLmxvZygnKioqIFNRUyAqKionKTtcbiAgICAgIGNvbnN0IGV2ZW50U3FzID0gZXZlbnQgYXMgU1FTRXZlbnQ7XG4gICAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiBldmVudFNxcy5SZWNvcmRzKSB7XG4gICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbkFybiA9IHJlY29yZC5ldmVudFNvdXJjZUFSTjtcblxuICAgICAgICBjb25zdCBzZXJ2aWNlS2V5ID0gbWFwcGluZ1tzdWJzY3JpcHRpb25Bcm5dO1xuICAgICAgICBsZXQgYm9keTogc3RyaW5nO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYm9keSA9IEpTT04ucGFyc2UocmVjb3JkLmJvZHkpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBib2R5ID0gcmVjb3JkLmJvZHk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkYXRhOiBTcXNTcHlFdmVudCA9IHtcbiAgICAgICAgICBzcHlFdmVudFR5cGU6ICdTcXMnLFxuICAgICAgICAgIGJvZHksXG4gICAgICAgICAgbWVzc2FnZUF0dHJpYnV0ZXM6IHJlY29yZC5tZXNzYWdlQXR0cmlidXRlcyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBzZXJ2aWNlS2V5LFxuICAgICAgICB9O1xuICAgICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2godGhpcy5wb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZXZlbnQ/LlJlY29yZHMgJiYgZXZlbnQuUmVjb3Jkc1swXT8uczMpIHtcbiAgICAgIC8vY29uc29sZS5sb2coJyoqKiBTMyAqKionKTtcbiAgICAgIGNvbnN0IGV2ZW50UzMgPSBldmVudCBhcyBTM0V2ZW50O1xuICAgICAgZm9yIChjb25zdCByZWNvcmQgb2YgZXZlbnRTMy5SZWNvcmRzKSB7XG4gICAgICAgIGNvbnN0IGJ1Y2tldEFybiA9IHJlY29yZC5zMy5idWNrZXQuYXJuO1xuXG4gICAgICAgIGNvbnN0IGRhdGE6IFMzU3B5RXZlbnQgPSB7XG4gICAgICAgICAgc3B5RXZlbnRUeXBlOiAnUzMnLFxuICAgICAgICAgIGV2ZW50TmFtZTogcmVjb3JkLmV2ZW50TmFtZSxcbiAgICAgICAgICBldmVudFRpbWU6IHJlY29yZC5ldmVudFRpbWUsXG4gICAgICAgICAgYnVja2V0OiByZWNvcmQuczMuYnVja2V0Lm5hbWUsXG4gICAgICAgICAga2V5OiByZWNvcmQuczMub2JqZWN0LmtleSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBzZXJ2aWNlS2V5OiBtYXBwaW5nW2J1Y2tldEFybl0sXG4gICAgICAgIH07XG4gICAgICAgIHBvc3REYXRhUHJvbWlzZXMucHVzaCh0aGlzLnBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChldmVudC5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LmR5bmFtb2RiKSB7XG4gICAgICAvL2NvbnNvbGUubG9nKCcqKiogRFlOQU1PREIgKioqJyk7XG4gICAgICBjb25zdCBldmVudER5bmFtb0RCID0gZXZlbnQgYXMgRHluYW1vREJTdHJlYW1FdmVudDtcbiAgICAgIGZvciAoY29uc3QgcmVjb3JkIG9mIGV2ZW50RHluYW1vREIuUmVjb3Jkcykge1xuICAgICAgICBsZXQgYXJuID0gcmVjb3JkLmV2ZW50U291cmNlQVJOITtcbiAgICAgICAgYXJuID0gYXJuLnN1YnN0cmluZygwLCBhcm4uaW5kZXhPZignL3N0cmVhbS8nKSk7XG5cbiAgICAgICAgY29uc3QgZGF0YTogRHluYW1vREJTcHlFdmVudCA9IHtcbiAgICAgICAgICBzcHlFdmVudFR5cGU6ICdEeW5hbW9EQicsXG4gICAgICAgICAgZXZlbnROYW1lOiByZWNvcmQuZXZlbnROYW1lLFxuICAgICAgICAgIG5ld0ltYWdlOiB1bm1hcnNoYWxsKHJlY29yZC5keW5hbW9kYj8uTmV3SW1hZ2UgYXMgYW55KSxcbiAgICAgICAgICBrZXlzOiB1bm1hcnNoYWxsKHJlY29yZC5keW5hbW9kYj8uS2V5cyBhcyBhbnkpLFxuICAgICAgICAgIG9sZEltYWdlOiByZWNvcmQuZHluYW1vZGI/Lk9sZEltYWdlXG4gICAgICAgICAgICA/IHVubWFyc2hhbGwocmVjb3JkLmR5bmFtb2RiPy5PbGRJbWFnZSBhcyBhbnkpXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBzZXJ2aWNlS2V5OiBtYXBwaW5nW2Fybl0sXG4gICAgICAgIH07XG4gICAgICAgIHBvc3REYXRhUHJvbWlzZXMucHVzaCh0aGlzLnBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGV2ZW50LmRldGFpbCAmJlxuICAgICAgZXZlbnRbJ2RldGFpbC10eXBlJ10gJiZcbiAgICAgIGV2ZW50LnZlcnNpb24gJiZcbiAgICAgIGV2ZW50LnNvdXJjZVxuICAgICkge1xuICAgICAgLy9jb25zb2xlLmxvZygnKioqIEV2ZW50QnJpZGdlICoqKicpO1xuICAgICAgY29uc3QgZXZlbnRFYiA9IGV2ZW50IGFzIEV2ZW50QnJpZGdlRXZlbnQ8YW55LCBhbnk+O1xuXG4gICAgICBjb25zdCBzZXJ2aWNlS2V5ID0gbWFwcGluZy5ldmVudEJyaWRnZTsgLy8gdGhlIGlzIG5ldyBsYW1iZGEgZm9yIGVhY2ggc3Vic2NyaXB0aW9uXG5cbiAgICAgIGNvbnN0IHNweUV2ZW50VHlwZSA9IHRoaXMuZ2V0U3B5RXZlbnRUeXBlKHNlcnZpY2VLZXkpIGFzXG4gICAgICAgIHwgJ0V2ZW50QnJpZGdlJ1xuICAgICAgICB8ICdFdmVudEJyaWRnZVJ1bGUnO1xuXG4gICAgICBjb25zdCBtZXNzYWdlID0gZXZlbnRFYi5kZXRhaWw7XG5cbiAgICAgIGNvbnN0IGRhdGE6IEV2ZW50QnJpZGdlU3B5RXZlbnQgfCBFdmVudEJyaWRnZVJ1bGVTcHlFdmVudCA9IHtcbiAgICAgICAgc3B5RXZlbnRUeXBlLFxuICAgICAgICBkZXRhaWw6IG1lc3NhZ2UsXG4gICAgICAgIGRldGFpbFR5cGU6IGV2ZW50RWJbJ2RldGFpbC10eXBlJ10sXG4gICAgICAgIGV2ZW50QnJpZGdlSWQ6IGV2ZW50RWJbJ2lkJ10sXG4gICAgICAgIHNvdXJjZTogZXZlbnRFYi5zb3VyY2UsXG4gICAgICAgIHRpbWU6IGV2ZW50RWIudGltZSxcbiAgICAgICAgYWNjb3VudDogZXZlbnRFYi5hY2NvdW50LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICBkYXRhLFxuICAgICAgICBzZXJ2aWNlS2V5LFxuICAgICAgfTtcbiAgICAgIHBvc3REYXRhUHJvbWlzZXMucHVzaCh0aGlzLnBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vY29uc29sZS5sb2coJyoqKiBPVEhFUiAqKionKTtcbiAgICAgIGNvbnN0IGZsdWVudEV2ZW50OiBPbWl0PFNweU1lc3NhZ2UsICd0aW1lc3RhbXAnPiA9IGV2ZW50O1xuICAgICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHRoaXMucG9zdERhdGEoZmx1ZW50RXZlbnQpKTtcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwb3N0RGF0YVByb21pc2VzKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcG9zdERhdGEoc3B5TWVzc2FnZTogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4pIHtcbiAgICB0aGlzLmxvZygnUG9zdCBzcHkgbWVzc2FnZScsIEpTT04uc3RyaW5naWZ5KHNweU1lc3NhZ2UpKTtcblxuICAgIGlmICghdGhpcy5jb25uZWN0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBvc3RDYWxscyA9IHRoaXMuY29ubmVjdGlvbnMubWFwKGFzeW5jICh7IGNvbm5lY3Rpb25JZCB9KSA9PiB7XG4gICAgICB0aGlzLmxvZyhgU2VuZGluZyBtZXNzYWdlIHRvIGNsaWVudDogJHtjb25uZWN0aW9uSWQuU31gKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQgPSBuZXcgUG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQoe1xuICAgICAgICAgIENvbm5lY3Rpb25JZDogY29ubmVjdGlvbklkLlMsXG4gICAgICAgICAgRGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICBzZXJ2aWNlS2V5OiBzcHlNZXNzYWdlLnNlcnZpY2VLZXksXG4gICAgICAgICAgICBkYXRhOiBzcHlNZXNzYWdlLmRhdGEsXG4gICAgICAgICAgfSkgYXMgYW55LFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCB0aGlzLmFwaWd3TWFuYWdlbWVudEFwaS5zZW5kKHBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5sb2dFcnJvcihgRmFpbGQgc2VuZGluZyBzcHkgbWVzc2FnZSB0bzogJHtjb25uZWN0aW9uSWQuU31gLCBlKTtcbiAgICAgICAgaWYgKChlIGFzIGFueSkuJG1ldGFkYXRhLmh0dHBTdGF0dXNDb2RlID09PSA0MTApIHtcbiAgICAgICAgICB0aGlzLmxvZyhgRm91bmQgc3RhbGUgY29ubmVjdGlvbiwgZGVsZXRpbmcgJHtjb25uZWN0aW9uSWR9YCk7XG5cbiAgICAgICAgICBjb25zdCBkZWxldGVQYXJhbXMgPSBuZXcgRGVsZXRlSXRlbUNvbW1hbmQoe1xuICAgICAgICAgICAgVGFibGVOYW1lOiBwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfVEFCTEVfTkFNRV0sXG4gICAgICAgICAgICBLZXk6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmRkYi5zZW5kKGRlbGV0ZVBhcmFtcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocG9zdENhbGxzKTtcbiAgICB0aGlzLmxvZygnU2VuZCBzcHkgbWVzc2FnZSBmaW5pc2gnKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U3B5RXZlbnRUeXBlKHNlcnZpY2VLZXk6IHN0cmluZykge1xuICAgIGlmICghc2VydmljZUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNlcnZpY2VLZXknKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VydmljZUtleS5zdWJzdHJpbmcoMCwgc2VydmljZUtleS5pbmRleE9mKCcjJykpO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2cobWVzc2FnZTogc3RyaW5nLCAuLi5vcHRpb25hbFBhcmFtczogYW55W10pIHtcbiAgICBpZiAodGhpcy5kZWJ1Z01vZGUpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ1NTUFkgRVhURU5TSU9OJywgbWVzc2FnZSwgLi4ub3B0aW9uYWxQYXJhbXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbG9nRXJyb3IobWVzc2FnZTogc3RyaW5nLCAuLi5vcHRpb25hbFBhcmFtczogYW55W10pIHtcbiAgICBpZiAodGhpcy5kZWJ1Z01vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1NTUFkgRVhURU5TSU9OJywgbWVzc2FnZSwgLi4ub3B0aW9uYWxQYXJhbXMpO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { ApiGatewayManagementApi, PostToConnectionCommand, } from '@aws-sdk/client-apigatewaymanagementapi';
|
|
2
|
+
import { DeleteItemCommand, DynamoDBClient, ScanCommand, } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
import { unmarshall } from '@aws-sdk/util-dynamodb';
|
|
4
|
+
import { envVariableNames } from '../src/common/envVariableNames';
|
|
5
|
+
export class SpyEventSender {
|
|
6
|
+
constructor(params) {
|
|
7
|
+
this.ddb = new DynamoDBClient({
|
|
8
|
+
region: process.env.AWS_REGION,
|
|
9
|
+
});
|
|
10
|
+
this.debugMode = process.env[envVariableNames.SSPY_DEBUG] === 'true';
|
|
11
|
+
this.apigwManagementApi = new ApiGatewayManagementApi({
|
|
12
|
+
apiVersion: '2018-11-29',
|
|
13
|
+
endpoint: process.env[envVariableNames.SSPY_WS_ENDPOINT],
|
|
14
|
+
});
|
|
15
|
+
if (params?.log) {
|
|
16
|
+
this.log = params.log;
|
|
17
|
+
}
|
|
18
|
+
if (params?.logError) {
|
|
19
|
+
this.logError = params.logError;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async publishSpyEvent(event) {
|
|
23
|
+
this.log('Event', JSON.stringify(event));
|
|
24
|
+
const mapping = JSON.parse(process.env[envVariableNames.SSPY_INFRA_MAPPING]);
|
|
25
|
+
this.log('ARN to names mapping', JSON.stringify(mapping));
|
|
26
|
+
let connectionData;
|
|
27
|
+
const scanParams = new ScanCommand({
|
|
28
|
+
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME],
|
|
29
|
+
ProjectionExpression: 'connectionId',
|
|
30
|
+
});
|
|
31
|
+
connectionData = await this.ddb.send(scanParams);
|
|
32
|
+
this.connections = connectionData.Items;
|
|
33
|
+
const postDataPromises = [];
|
|
34
|
+
if (event?.Records && event.Records[0]?.Sns) {
|
|
35
|
+
//console.log('*** SNS ***');
|
|
36
|
+
const eventSns = event;
|
|
37
|
+
for (const record of eventSns.Records) {
|
|
38
|
+
const subscriptionArn = record.EventSubscriptionArn;
|
|
39
|
+
let serviceKey;
|
|
40
|
+
if (mapping[subscriptionArn]) {
|
|
41
|
+
// subscription event that could contain filter based on existing subscription
|
|
42
|
+
serviceKey = mapping[subscriptionArn];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// catch all subscription
|
|
46
|
+
const topicArn = record.Sns.TopicArn;
|
|
47
|
+
serviceKey = mapping[topicArn];
|
|
48
|
+
}
|
|
49
|
+
let message;
|
|
50
|
+
try {
|
|
51
|
+
message = JSON.parse(record.Sns.Message);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
message = record.Sns.Message;
|
|
55
|
+
}
|
|
56
|
+
const spyEventType = this.getSpyEventType(serviceKey);
|
|
57
|
+
const data = {
|
|
58
|
+
spyEventType,
|
|
59
|
+
message,
|
|
60
|
+
subject: record.Sns.Subject,
|
|
61
|
+
timestamp: record.Sns.Timestamp,
|
|
62
|
+
topicArn: record.Sns.TopicArn,
|
|
63
|
+
messageId: record.Sns.MessageId,
|
|
64
|
+
messageAttributes: record.Sns.MessageAttributes,
|
|
65
|
+
};
|
|
66
|
+
const fluentEvent = {
|
|
67
|
+
data,
|
|
68
|
+
serviceKey,
|
|
69
|
+
};
|
|
70
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (event?.Records && event.Records[0]?.eventSource === 'aws:sqs') {
|
|
74
|
+
//console.log('*** SQS ***');
|
|
75
|
+
const eventSqs = event;
|
|
76
|
+
for (const record of eventSqs.Records) {
|
|
77
|
+
const subscriptionArn = record.eventSourceARN;
|
|
78
|
+
const serviceKey = mapping[subscriptionArn];
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = JSON.parse(record.body);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
body = record.body;
|
|
85
|
+
}
|
|
86
|
+
const data = {
|
|
87
|
+
spyEventType: 'Sqs',
|
|
88
|
+
body,
|
|
89
|
+
messageAttributes: record.messageAttributes,
|
|
90
|
+
};
|
|
91
|
+
const fluentEvent = {
|
|
92
|
+
data,
|
|
93
|
+
serviceKey,
|
|
94
|
+
};
|
|
95
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (event?.Records && event.Records[0]?.s3) {
|
|
99
|
+
//console.log('*** S3 ***');
|
|
100
|
+
const eventS3 = event;
|
|
101
|
+
for (const record of eventS3.Records) {
|
|
102
|
+
const bucketArn = record.s3.bucket.arn;
|
|
103
|
+
const data = {
|
|
104
|
+
spyEventType: 'S3',
|
|
105
|
+
eventName: record.eventName,
|
|
106
|
+
eventTime: record.eventTime,
|
|
107
|
+
bucket: record.s3.bucket.name,
|
|
108
|
+
key: record.s3.object.key,
|
|
109
|
+
};
|
|
110
|
+
const fluentEvent = {
|
|
111
|
+
data,
|
|
112
|
+
serviceKey: mapping[bucketArn],
|
|
113
|
+
};
|
|
114
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (event.Records && event.Records[0]?.dynamodb) {
|
|
118
|
+
//console.log('*** DYNAMODB ***');
|
|
119
|
+
const eventDynamoDB = event;
|
|
120
|
+
for (const record of eventDynamoDB.Records) {
|
|
121
|
+
let arn = record.eventSourceARN;
|
|
122
|
+
arn = arn.substring(0, arn.indexOf('/stream/'));
|
|
123
|
+
const data = {
|
|
124
|
+
spyEventType: 'DynamoDB',
|
|
125
|
+
eventName: record.eventName,
|
|
126
|
+
newImage: unmarshall(record.dynamodb?.NewImage),
|
|
127
|
+
keys: unmarshall(record.dynamodb?.Keys),
|
|
128
|
+
oldImage: record.dynamodb?.OldImage
|
|
129
|
+
? unmarshall(record.dynamodb?.OldImage)
|
|
130
|
+
: undefined,
|
|
131
|
+
};
|
|
132
|
+
const fluentEvent = {
|
|
133
|
+
data,
|
|
134
|
+
serviceKey: mapping[arn],
|
|
135
|
+
};
|
|
136
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (event.detail &&
|
|
140
|
+
event['detail-type'] &&
|
|
141
|
+
event.version &&
|
|
142
|
+
event.source) {
|
|
143
|
+
//console.log('*** EventBridge ***');
|
|
144
|
+
const eventEb = event;
|
|
145
|
+
const serviceKey = mapping.eventBridge; // the is new lambda for each subscription
|
|
146
|
+
const spyEventType = this.getSpyEventType(serviceKey);
|
|
147
|
+
const message = eventEb.detail;
|
|
148
|
+
const data = {
|
|
149
|
+
spyEventType,
|
|
150
|
+
detail: message,
|
|
151
|
+
detailType: eventEb['detail-type'],
|
|
152
|
+
eventBridgeId: eventEb['id'],
|
|
153
|
+
source: eventEb.source,
|
|
154
|
+
time: eventEb.time,
|
|
155
|
+
account: eventEb.account,
|
|
156
|
+
};
|
|
157
|
+
const fluentEvent = {
|
|
158
|
+
data,
|
|
159
|
+
serviceKey,
|
|
160
|
+
};
|
|
161
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
//console.log('*** OTHER ***');
|
|
165
|
+
const fluentEvent = event;
|
|
166
|
+
postDataPromises.push(this.postData(fluentEvent));
|
|
167
|
+
}
|
|
168
|
+
await Promise.all(postDataPromises);
|
|
169
|
+
}
|
|
170
|
+
async postData(spyMessage) {
|
|
171
|
+
this.log('Post spy message', JSON.stringify(spyMessage));
|
|
172
|
+
if (!this.connections) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const postCalls = this.connections.map(async ({ connectionId }) => {
|
|
176
|
+
this.log(`Sending message to client: ${connectionId.S}`);
|
|
177
|
+
try {
|
|
178
|
+
const postToConnectionCommand = new PostToConnectionCommand({
|
|
179
|
+
ConnectionId: connectionId.S,
|
|
180
|
+
Data: JSON.stringify({
|
|
181
|
+
timestamp: new Date().toISOString(),
|
|
182
|
+
serviceKey: spyMessage.serviceKey,
|
|
183
|
+
data: spyMessage.data,
|
|
184
|
+
}),
|
|
185
|
+
});
|
|
186
|
+
await this.apigwManagementApi.send(postToConnectionCommand);
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
this.logError(`Faild sending spy message to: ${connectionId.S}`, e);
|
|
190
|
+
if (e.$metadata.httpStatusCode === 410) {
|
|
191
|
+
this.log(`Found stale connection, deleting ${connectionId}`);
|
|
192
|
+
const deleteParams = new DeleteItemCommand({
|
|
193
|
+
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME],
|
|
194
|
+
Key: { connectionId },
|
|
195
|
+
});
|
|
196
|
+
await this.ddb.send(deleteParams);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
throw e;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
await Promise.all(postCalls);
|
|
204
|
+
this.log('Send spy message finish');
|
|
205
|
+
}
|
|
206
|
+
getSpyEventType(serviceKey) {
|
|
207
|
+
if (!serviceKey) {
|
|
208
|
+
throw new Error('Missing serviceKey');
|
|
209
|
+
}
|
|
210
|
+
return serviceKey.substring(0, serviceKey.indexOf('#'));
|
|
211
|
+
}
|
|
212
|
+
log(message, ...optionalParams) {
|
|
213
|
+
if (this.debugMode) {
|
|
214
|
+
console.debug('SSPY EXTENSION', message, ...optionalParams);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
logError(message, ...optionalParams) {
|
|
218
|
+
if (this.debugMode) {
|
|
219
|
+
console.error('SSPY EXTENSION', message, ...optionalParams);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3B5RXZlbnRTZW5kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jb21tb24vU3B5RXZlbnRTZW5kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2Qix1QkFBdUIsR0FDeEIsTUFBTSx5Q0FBeUMsQ0FBQztBQUNqRCxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLGNBQWMsRUFDZCxXQUFXLEdBQ1osTUFBTSwwQkFBMEIsQ0FBQztBQUVsQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFRcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFVbEUsTUFBTSxPQUFPLGNBQWM7SUFXekIsWUFBWSxNQUdYO1FBYkQsUUFBRyxHQUFHLElBQUksY0FBYyxDQUFDO1lBQ3ZCLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVU7U0FDL0IsQ0FBQyxDQUFDO1FBQ0gsY0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLEtBQUssTUFBTSxDQUFDO1FBQ2hFLHVCQUFrQixHQUFHLElBQUksdUJBQXVCLENBQUM7WUFDL0MsVUFBVSxFQUFFLFlBQVk7WUFDeEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUU7U0FDMUQsQ0FBQyxDQUFDO1FBT0QsSUFBSSxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ2YsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1NBQ3ZCO1FBRUQsSUFBSSxNQUFNLEVBQUUsUUFBUSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUNqQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQVU7UUFDckMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVB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QUFDLGdCQUFnQixDQUFDLGtCQUFrQixDQUFDO3dCQUMzRCxHQUFHLEVBQUUsRUFBRSxZQUFZLEVBQUU7cUJBQ3RCLENBQUMsQ0FBQztvQkFFSCxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2lCQUNuQztxQkFBTTtvQkFDTCxNQUFNLENBQUMsQ0FBQztpQkFDVDthQUNGO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFTyxlQUFlLENBQUMsVUFBa0I7UUFDeEMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztTQUN2QztRQUVELE9BQU8sVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFTyxHQUFHLENBQUMsT0FBZSxFQUFFLEdBQUcsY0FBcUI7UUFDbkQsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLEdBQUcsY0FBYyxDQUFDLENBQUM7U0FDN0Q7SUFDSCxDQUFDO0lBRU8sUUFBUSxDQUFDLE9BQWUsRUFBRSxHQUFHLGNBQXFCO1FBQ3hELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNsQixPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFDO1NBQzdEO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQXBpR2F0ZXdheU1hbmFnZW1lbnRBcGksXG4gIFBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtYXBpZ2F0ZXdheW1hbmFnZW1lbnRhcGknO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlVmFsdWUsXG4gIERlbGV0ZUl0ZW1Db21tYW5kLFxuICBEeW5hbW9EQkNsaWVudCxcbiAgU2NhbkNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1keW5hbW9kYic7XG5cbmltcG9ydCB7IHVubWFyc2hhbGwgfSBmcm9tICdAYXdzLXNkay91dGlsLWR5bmFtb2RiJztcbmltcG9ydCB7XG4gIER5bmFtb0RCU3RyZWFtRXZlbnQsXG4gIFMzRXZlbnQsXG4gIFNOU0V2ZW50LFxuICBFdmVudEJyaWRnZUV2ZW50LFxuICBTUVNFdmVudCxcbn0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBlbnZWYXJpYWJsZU5hbWVzIH0gZnJvbSAnLi4vc3JjL2NvbW1vbi9lbnZWYXJpYWJsZU5hbWVzJztcbmltcG9ydCB7IER5bmFtb0RCU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9EeW5hbW9EQlNweUV2ZW50JztcbmltcG9ydCB7IEV2ZW50QnJpZGdlUnVsZVNweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvRXZlbnRCcmlkZ2VSdWxlU3B5RXZlbnQnO1xuaW1wb3J0IHsgRXZlbnRCcmlkZ2VTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL0V2ZW50QnJpZGdlU3B5RXZlbnQnO1xuaW1wb3J0IHsgUzNTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL1MzU3B5RXZlbnQnO1xuaW1wb3J0IHsgU25zU3Vic2NyaXB0aW9uU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9TbnNTdWJzY3JpcHRpb25TcHlFdmVudCc7XG5pbXBvcnQgeyBTbnNUb3BpY1NweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvU25zVG9waWNTcHlFdmVudCc7XG5pbXBvcnQgeyBTcHlNZXNzYWdlIH0gZnJvbSAnLi9zcHlFdmVudHMvU3B5TWVzc2FnZSc7XG5pbXBvcnQgeyBTcXNTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL1Nxc1NweUV2ZW50JztcblxuZXhwb3J0IGNsYXNzIFNweUV2ZW50U2VuZGVyIHtcbiAgZGRiID0gbmV3IER5bmFtb0RCQ2xpZW50KHtcbiAgICByZWdpb246IHByb2Nlc3MuZW52LkFXU19SRUdJT04sXG4gIH0pO1xuICBkZWJ1Z01vZGUgPSBwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfREVCVUddID09PSAndHJ1ZSc7XG4gIGFwaWd3TWFuYWdlbWVudEFwaSA9IG5ldyBBcGlHYXRld2F5TWFuYWdlbWVudEFwaSh7XG4gICAgYXBpVmVyc2lvbjogJzIwMTgtMTEtMjknLFxuICAgIGVuZHBvaW50OiBwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfRU5EUE9JTlRdISxcbiAgfSk7XG4gIGNvbm5lY3Rpb25zOiBSZWNvcmQ8c3RyaW5nLCBBdHRyaWJ1dGVWYWx1ZT5bXSB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM/OiB7XG4gICAgbG9nOiAobWVzc2FnZTogc3RyaW5nLCAuLi5vcHRpb25hbFBhcmFtczogYW55W10pID0+IHZvaWQ7XG4gICAgbG9nRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcsIC4uLm9wdGlvbmFsUGFyYW1zOiBhbnlbXSkgPT4gdm9pZDtcbiAgfSkge1xuICAgIGlmIChwYXJhbXM/LmxvZykge1xuICAgICAgdGhpcy5sb2cgPSBwYXJhbXMubG9nO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXM/LmxvZ0Vycm9yKSB7XG4gICAgICB0aGlzLmxvZ0Vycm9yID0gcGFyYW1zLmxvZ0Vycm9yO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBwdWJsaXNoU3B5RXZlbnQoZXZlbnQ6IGFueSkge1xuICAgIHRoaXMubG9nKCdFdmVudCcsIEpTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG5cbiAgICBjb25zdCBtYXBwaW5nID0gSlNPTi5wYXJzZShcbiAgICAgIHByb2Nlc3MuZW52W2VudlZhcmlhYmxlTmFtZXMuU1NQWV9JTkZSQV9NQVBQSU5HXSFcbiAgICApO1xuICAgIHRoaXMubG9nKCdBUk4gdG8gbmFtZXMgbWFwcGluZycsIEpTT04uc3RyaW5naWZ5KG1hcHBpbmcpKTtcblxuICAgIGxldCBjb25uZWN0aW9uRGF0YTtcblxuICAgIGNvbnN0IHNjYW5QYXJhbXMgPSBuZXcgU2NhbkNvbW1hbmQoe1xuICAgICAgVGFibGVOYW1lOiBwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfVEFCTEVfTkFNRV0gYXMgc3RyaW5nLFxuICAgICAgUHJvamVjdGlvbkV4cHJlc3Npb246ICdjb25uZWN0aW9uSWQnLFxuICAgIH0pO1xuXG4gICAgY29ubmVjdGlvbkRhdGEgPSBhd2FpdCB0aGlzLmRkYi5zZW5kKHNjYW5QYXJhbXMpO1xuXG4gICAgdGhpcy5jb25uZWN0aW9ucyA9IGNvbm5lY3Rpb25EYXRhLkl0ZW1zO1xuXG4gICAgY29uc3QgcG9zdERhdGFQcm9taXNlczogUHJvbWlzZTxhbnk+W10gPSBbXTtcblxuICAgIGlmIChldmVudD8uUmVjb3JkcyAmJiBldmVudC5SZWNvcmRzWzBdPy5TbnMpIHtcbiAgICAgIC8vY29uc29sZS5sb2coJyoqKiBTTlMgKioqJyk7XG4gICAgICBjb25zdCBldmVudFNucyA9IGV2ZW50IGFzIFNOU0V2ZW50O1xuICAgICAgZm9yIChjb25zdCByZWNvcmQgb2YgZXZlbnRTbnMuUmVjb3Jkcykge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb25Bcm4gPSByZWNvcmQuRXZlbnRTdWJzY3JpcHRpb25Bcm47XG5cbiAgICAgICAgbGV0IHNlcnZpY2VLZXk6IHN0cmluZztcbiAgICAgICAgaWYgKG1hcHBpbmdbc3Vic2NyaXB0aW9uQXJuXSkge1xuICAgICAgICAgIC8vIHN1YnNjcmlwdGlvbiBldmVudCB0aGF0IGNvdWxkIGNvbnRhaW4gZmlsdGVyIGJhc2VkIG9uIGV4aXN0aW5nIHN1YnNjcmlwdGlvblxuICAgICAgICAgIHNlcnZpY2VLZXkgPSBtYXBwaW5nW3N1YnNjcmlwdGlvbkFybl07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gY2F0Y2ggYWxsIHN1YnNjcmlwdGlvblxuICAgICAgICAgIGNvbnN0IHRvcGljQXJuID0gcmVjb3JkLlNucy5Ub3BpY0FybjtcbiAgICAgICAgICBzZXJ2aWNlS2V5ID0gbWFwcGluZ1t0b3BpY0Fybl07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2UocmVjb3JkLlNucy5NZXNzYWdlKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgbWVzc2FnZSA9IHJlY29yZC5TbnMuTWVzc2FnZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNweUV2ZW50VHlwZSA9IHRoaXMuZ2V0U3B5RXZlbnRUeXBlKHNlcnZpY2VLZXkpIGFzXG4gICAgICAgICAgfCAnRnVuY3Rpb25TbnNUb3BpYydcbiAgICAgICAgICB8ICdGdW5jdGlvblNuc1N1YnNjcmlwdGlvbic7XG5cbiAgICAgICAgY29uc3QgZGF0YTogU25zVG9waWNTcHlFdmVudCB8IFNuc1N1YnNjcmlwdGlvblNweUV2ZW50ID0ge1xuICAgICAgICAgIHNweUV2ZW50VHlwZSxcbiAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgIHN1YmplY3Q6IHJlY29yZC5TbnMuU3ViamVjdCxcbiAgICAgICAgICB0aW1lc3RhbXA6IHJlY29yZC5TbnMuVGltZXN0YW1wLFxuICAgICAgICAgIHRvcGljQXJuOiByZWNvcmQuU25zLlRvcGljQXJuLFxuICAgICAgICAgIG1lc3NhZ2VJZDogcmVjb3JkLlNucy5NZXNzYWdlSWQsXG4gICAgICAgICAgbWVzc2FnZUF0dHJpYnV0ZXM6IHJlY29yZC5TbnMuTWVzc2FnZUF0dHJpYnV0ZXMsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgc2VydmljZUtleSxcbiAgICAgICAgfTtcbiAgICAgICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHRoaXMucG9zdERhdGEoZmx1ZW50RXZlbnQpKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV2ZW50Py5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LmV2ZW50U291cmNlID09PSAnYXdzOnNxcycpIHtcbiAgICAgIC8vY29uc29sZS5sb2coJyoqKiBTUVMgKioqJyk7XG4gICAgICBjb25zdCBldmVudFNxcyA9IGV2ZW50IGFzIFNRU0V2ZW50O1xuICAgICAgZm9yIChjb25zdCByZWNvcmQgb2YgZXZlbnRTcXMuUmVjb3Jkcykge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb25Bcm4gPSByZWNvcmQuZXZlbnRTb3VyY2VBUk47XG5cbiAgICAgICAgY29uc3Qgc2VydmljZUtleSA9IG1hcHBpbmdbc3Vic2NyaXB0aW9uQXJuXTtcbiAgICAgICAgbGV0IGJvZHk6IHN0cmluZztcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGJvZHkgPSBKU09OLnBhcnNlKHJlY29yZC5ib2R5KTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgYm9keSA9IHJlY29yZC5ib2R5O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGF0YTogU3FzU3B5RXZlbnQgPSB7XG4gICAgICAgICAgc3B5RXZlbnRUeXBlOiAnU3FzJyxcbiAgICAgICAgICBib2R5LFxuICAgICAgICAgIG1lc3NhZ2VBdHRyaWJ1dGVzOiByZWNvcmQubWVzc2FnZUF0dHJpYnV0ZXMsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgc2VydmljZUtleSxcbiAgICAgICAgfTtcbiAgICAgICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHRoaXMucG9zdERhdGEoZmx1ZW50RXZlbnQpKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV2ZW50Py5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LnMzKSB7XG4gICAgICAvL2NvbnNvbGUubG9nKCcqKiogUzMgKioqJyk7XG4gICAgICBjb25zdCBldmVudFMzID0gZXZlbnQgYXMgUzNFdmVudDtcbiAgICAgIGZvciAoY29uc3QgcmVjb3JkIG9mIGV2ZW50UzMuUmVjb3Jkcykge1xuICAgICAgICBjb25zdCBidWNrZXRBcm4gPSByZWNvcmQuczMuYnVja2V0LmFybjtcblxuICAgICAgICBjb25zdCBkYXRhOiBTM1NweUV2ZW50ID0ge1xuICAgICAgICAgIHNweUV2ZW50VHlwZTogJ1MzJyxcbiAgICAgICAgICBldmVudE5hbWU6IHJlY29yZC5ldmVudE5hbWUsXG4gICAgICAgICAgZXZlbnRUaW1lOiByZWNvcmQuZXZlbnRUaW1lLFxuICAgICAgICAgIGJ1Y2tldDogcmVjb3JkLnMzLmJ1Y2tldC5uYW1lLFxuICAgICAgICAgIGtleTogcmVjb3JkLnMzLm9iamVjdC5rZXksXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgc2VydmljZUtleTogbWFwcGluZ1tidWNrZXRBcm5dLFxuICAgICAgICB9O1xuICAgICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2godGhpcy5wb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZXZlbnQuUmVjb3JkcyAmJiBldmVudC5SZWNvcmRzWzBdPy5keW5hbW9kYikge1xuICAgICAgLy9jb25zb2xlLmxvZygnKioqIERZTkFNT0RCICoqKicpO1xuICAgICAgY29uc3QgZXZlbnREeW5hbW9EQiA9IGV2ZW50IGFzIER5bmFtb0RCU3RyZWFtRXZlbnQ7XG4gICAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiBldmVudER5bmFtb0RCLlJlY29yZHMpIHtcbiAgICAgICAgbGV0IGFybiA9IHJlY29yZC5ldmVudFNvdXJjZUFSTiE7XG4gICAgICAgIGFybiA9IGFybi5zdWJzdHJpbmcoMCwgYXJuLmluZGV4T2YoJy9zdHJlYW0vJykpO1xuXG4gICAgICAgIGNvbnN0IGRhdGE6IER5bmFtb0RCU3B5RXZlbnQgPSB7XG4gICAgICAgICAgc3B5RXZlbnRUeXBlOiAnRHluYW1vREInLFxuICAgICAgICAgIGV2ZW50TmFtZTogcmVjb3JkLmV2ZW50TmFtZSxcbiAgICAgICAgICBuZXdJbWFnZTogdW5tYXJzaGFsbChyZWNvcmQuZHluYW1vZGI/Lk5ld0ltYWdlIGFzIGFueSksXG4gICAgICAgICAga2V5czogdW5tYXJzaGFsbChyZWNvcmQuZHluYW1vZGI/LktleXMgYXMgYW55KSxcbiAgICAgICAgICBvbGRJbWFnZTogcmVjb3JkLmR5bmFtb2RiPy5PbGRJbWFnZVxuICAgICAgICAgICAgPyB1bm1hcnNoYWxsKHJlY29yZC5keW5hbW9kYj8uT2xkSW1hZ2UgYXMgYW55KVxuICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgc2VydmljZUtleTogbWFwcGluZ1thcm5dLFxuICAgICAgICB9O1xuICAgICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2godGhpcy5wb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXG4gICAgICBldmVudC5kZXRhaWwgJiZcbiAgICAgIGV2ZW50WydkZXRhaWwtdHlwZSddICYmXG4gICAgICBldmVudC52ZXJzaW9uICYmXG4gICAgICBldmVudC5zb3VyY2VcbiAgICApIHtcbiAgICAgIC8vY29uc29sZS5sb2coJyoqKiBFdmVudEJyaWRnZSAqKionKTtcbiAgICAgIGNvbnN0IGV2ZW50RWIgPSBldmVudCBhcyBFdmVudEJyaWRnZUV2ZW50PGFueSwgYW55PjtcblxuICAgICAgY29uc3Qgc2VydmljZUtleSA9IG1hcHBpbmcuZXZlbnRCcmlkZ2U7IC8vIHRoZSBpcyBuZXcgbGFtYmRhIGZvciBlYWNoIHN1YnNjcmlwdGlvblxuXG4gICAgICBjb25zdCBzcHlFdmVudFR5cGUgPSB0aGlzLmdldFNweUV2ZW50VHlwZShzZXJ2aWNlS2V5KSBhc1xuICAgICAgICB8ICdFdmVudEJyaWRnZSdcbiAgICAgICAgfCAnRXZlbnRCcmlkZ2VSdWxlJztcblxuICAgICAgY29uc3QgbWVzc2FnZSA9IGV2ZW50RWIuZGV0YWlsO1xuXG4gICAgICBjb25zdCBkYXRhOiBFdmVudEJyaWRnZVNweUV2ZW50IHwgRXZlbnRCcmlkZ2VSdWxlU3B5RXZlbnQgPSB7XG4gICAgICAgIHNweUV2ZW50VHlwZSxcbiAgICAgICAgZGV0YWlsOiBtZXNzYWdlLFxuICAgICAgICBkZXRhaWxUeXBlOiBldmVudEViWydkZXRhaWwtdHlwZSddLFxuICAgICAgICBldmVudEJyaWRnZUlkOiBldmVudEViWydpZCddLFxuICAgICAgICBzb3VyY2U6IGV2ZW50RWIuc291cmNlLFxuICAgICAgICB0aW1lOiBldmVudEViLnRpbWUsXG4gICAgICAgIGFjY291bnQ6IGV2ZW50RWIuYWNjb3VudCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGZsdWVudEV2ZW50OiBPbWl0PFNweU1lc3NhZ2UsICd0aW1lc3RhbXAnPiA9IHtcbiAgICAgICAgZGF0YSxcbiAgICAgICAgc2VydmljZUtleSxcbiAgICAgIH07XG4gICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2godGhpcy5wb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvL2NvbnNvbGUubG9nKCcqKiogT1RIRVIgKioqJyk7XG4gICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSBldmVudDtcbiAgICAgIHBvc3REYXRhUHJvbWlzZXMucHVzaCh0aGlzLnBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocG9zdERhdGFQcm9taXNlcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBvc3REYXRhKHNweU1lc3NhZ2U6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+KSB7XG4gICAgdGhpcy5sb2coJ1Bvc3Qgc3B5IG1lc3NhZ2UnLCBKU09OLnN0cmluZ2lmeShzcHlNZXNzYWdlKSk7XG5cbiAgICBpZiAoIXRoaXMuY29ubmVjdGlvbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwb3N0Q2FsbHMgPSB0aGlzLmNvbm5lY3Rpb25zLm1hcChhc3luYyAoeyBjb25uZWN0aW9uSWQgfSkgPT4ge1xuICAgICAgdGhpcy5sb2coYFNlbmRpbmcgbWVzc2FnZSB0byBjbGllbnQ6ICR7Y29ubmVjdGlvbklkLlN9YCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kID0gbmV3IFBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kKHtcbiAgICAgICAgICBDb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb25JZC5TLFxuICAgICAgICAgIERhdGE6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgc2VydmljZUtleTogc3B5TWVzc2FnZS5zZXJ2aWNlS2V5LFxuICAgICAgICAgICAgZGF0YTogc3B5TWVzc2FnZS5kYXRhLFxuICAgICAgICAgIH0pIGFzIGFueSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5hcGlnd01hbmFnZW1lbnRBcGkuc2VuZChwb3N0VG9Db25uZWN0aW9uQ29tbWFuZCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMubG9nRXJyb3IoYEZhaWxkIHNlbmRpbmcgc3B5IG1lc3NhZ2UgdG86ICR7Y29ubmVjdGlvbklkLlN9YCwgZSk7XG4gICAgICAgIGlmICgoZSBhcyBhbnkpLiRtZXRhZGF0YS5odHRwU3RhdHVzQ29kZSA9PT0gNDEwKSB7XG4gICAgICAgICAgdGhpcy5sb2coYEZvdW5kIHN0YWxlIGNvbm5lY3Rpb24sIGRlbGV0aW5nICR7Y29ubmVjdGlvbklkfWApO1xuXG4gICAgICAgICAgY29uc3QgZGVsZXRlUGFyYW1zID0gbmV3IERlbGV0ZUl0ZW1Db21tYW5kKHtcbiAgICAgICAgICAgIFRhYmxlTmFtZTogcHJvY2Vzcy5lbnZbZW52VmFyaWFibGVOYW1lcy5TU1BZX1dTX1RBQkxFX05BTUVdLFxuICAgICAgICAgICAgS2V5OiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXdhaXQgdGhpcy5kZGIuc2VuZChkZWxldGVQYXJhbXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHBvc3RDYWxscyk7XG4gICAgdGhpcy5sb2coJ1NlbmQgc3B5IG1lc3NhZ2UgZmluaXNoJyk7XG4gIH1cblxuICBwcml2YXRlIGdldFNweUV2ZW50VHlwZShzZXJ2aWNlS2V5OiBzdHJpbmcpIHtcbiAgICBpZiAoIXNlcnZpY2VLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBzZXJ2aWNlS2V5Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlcnZpY2VLZXkuc3Vic3RyaW5nKDAsIHNlcnZpY2VLZXkuaW5kZXhPZignIycpKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nKG1lc3NhZ2U6IHN0cmluZywgLi4ub3B0aW9uYWxQYXJhbXM6IGFueVtdKSB7XG4gICAgaWYgKHRoaXMuZGVidWdNb2RlKSB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdTU1BZIEVYVEVOU0lPTicsIG1lc3NhZ2UsIC4uLm9wdGlvbmFsUGFyYW1zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxvZ0Vycm9yKG1lc3NhZ2U6IHN0cmluZywgLi4ub3B0aW9uYWxQYXJhbXM6IGFueVtdKSB7XG4gICAgaWYgKHRoaXMuZGVidWdNb2RlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdTU1BZIEVYVEVOU0lPTicsIG1lc3NhZ2UsIC4uLm9wdGlvbmFsUGFyYW1zKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Credentials } from '@aws-sdk/types';
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function getSignedWebSocketUrl(url: string, credentials?: Credentials): Promise<string>;
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getSignedWebSocketUrl = void 0;
|
|
4
4
|
const credential_providers_1 = require("@aws-sdk/credential-providers");
|
|
5
5
|
const aws4 = require("aws4");
|
|
6
6
|
// ""wss://m6g3w6ttdh.execute-api.eu-west-1.amazonaws.com/prod";"
|
|
7
|
-
async function
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
async function getSignedWebSocketUrl(url, credentials) {
|
|
8
|
+
let hostParts;
|
|
9
|
+
let pathname;
|
|
10
|
+
if (!url) {
|
|
11
|
+
throw new Error(`Missing websocket URL`);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
new URL(url); //validate URL
|
|
15
|
+
const urlParsed = parseUrl(url);
|
|
16
|
+
pathname = urlParsed.pathname;
|
|
17
|
+
hostParts = urlParsed.host.split('.');
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new Error(`Invalid websocket URL ${url}`);
|
|
21
|
+
}
|
|
10
22
|
if (!credentials) {
|
|
11
23
|
const credentialsProvider = (0, credential_providers_1.fromNodeProviderChain)();
|
|
12
24
|
credentials = await credentialsProvider();
|
|
13
25
|
}
|
|
14
26
|
const AWS_REGION = hostParts[2]; // The region of your API-gateway
|
|
15
27
|
const SOCKET_HOST = hostParts[0]; // Your API-gateway ID
|
|
16
|
-
const ENV =
|
|
28
|
+
const ENV = pathname.replace(/^\//, ''); // The stage of your target deployment
|
|
17
29
|
const WEBSOCKET_URL = `${SOCKET_HOST}.execute-api.${AWS_REGION}.amazonaws.com`; // Don't prepend with wss!
|
|
18
30
|
// const AWS_REGION = "eu-west-1"; // The region of your API-gateway
|
|
19
31
|
// const SOCKET_HOST = "m6g3w6ttdh"; // Your API-gateway ID
|
|
@@ -38,7 +50,7 @@ async function getWebSocketUrl(url, credentials) {
|
|
|
38
50
|
const url2 = `wss://${WEBSOCKET_URL}${path}`;
|
|
39
51
|
return url2;
|
|
40
52
|
}
|
|
41
|
-
exports.
|
|
53
|
+
exports.getSignedWebSocketUrl = getSignedWebSocketUrl;
|
|
42
54
|
function parseUrl(href) {
|
|
43
55
|
const match = href.match(/^(wss?:)\/\/(([^:/?#]*)(?::([0-9]+))?)([/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
|
|
44
56
|
return (match && {
|
|
@@ -52,4 +64,4 @@ function parseUrl(href) {
|
|
|
52
64
|
hash: match[7],
|
|
53
65
|
});
|
|
54
66
|
}
|
|
55
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0V2ViU29ja2V0VXJsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vY29tbW9uL2dldFdlYlNvY2tldFVybC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx3RUFBc0U7QUFFdEUsNkJBQTZCO0FBRTdCLGlFQUFpRTtBQUUxRCxLQUFLLFVBQVUscUJBQXFCLENBQ3pDLEdBQVcsRUFDWCxXQUF5QjtJQUV6QixJQUFJLFNBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFnQixDQUFDO0lBRXJCLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDUixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7S0FDMUM7SUFFRCxJQUFJO1FBQ0YsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxjQUFjO1FBRTVCLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoQyxRQUFRLEdBQUcsU0FBVSxDQUFDLFFBQVMsQ0FBQztRQUNoQyxTQUFTLEdBQUcsU0FBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDeEM7SUFBQyxNQUFNO1FBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxFQUFFLENBQUMsQ0FBQztLQUNqRDtJQUVELElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDaEIsTUFBTSxtQkFBbUIsR0FBRyxJQUFBLDRDQUFxQixHQUFFLENBQUM7UUFDcEQsV0FBVyxHQUFHLE1BQU0sbUJBQW1CLEVBQUUsQ0FBQztLQUMzQztJQUVELE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztJQUNsRSxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxzQkFBc0I7SUFDeEQsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxzQ0FBc0M7SUFDL0UsTUFBTSxhQUFhLEdBQUcsR0FBRyxXQUFXLGdCQUFnQixVQUFVLGdCQUFnQixDQUFDLENBQUMsMEJBQTBCO0lBQzFHLG9FQUFvRTtJQUNwRSwyREFBMkQ7SUFDM0QsNkRBQTZEO0lBQzdELDZHQUE2RztJQUU3RyxvQkFBb0I7SUFDcEIsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQ3hCO1FBQ0UsTUFBTSxFQUFFLEtBQUs7UUFDYixJQUFJLEVBQUUsYUFBYTtRQUNuQiw0REFBNEQ7UUFDNUQsK0JBQStCO1FBQy9CLE9BQU87UUFDUCxJQUFJLEVBQUUsSUFBSSxHQUFHLEVBQUU7UUFDZixPQUFPLEVBQUUsYUFBYTtRQUN0QixNQUFNLEVBQUUsVUFBVTtRQUNsQixTQUFTLEVBQUUsSUFBSTtLQUNoQixFQUNEO1FBQ0UsV0FBVyxFQUFFLFdBQVcsQ0FBQyxXQUFXO1FBQ3BDLGVBQWUsRUFBRSxXQUFXLENBQUMsZUFBZTtRQUM1QyxZQUFZLEVBQUUsV0FBVyxDQUFDLFlBQVk7S0FDdkMsQ0FDRixDQUFDO0lBRUYsTUFBTSxJQUFJLEdBQUcsU0FBUyxhQUFhLEdBQUcsSUFBSSxFQUFFLENBQUM7SUFDN0MsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBekRELHNEQXlEQztBQUVELFNBQVMsUUFBUSxDQUFDLElBQVk7SUFDNUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FDdEIseUVBQXlFLENBQzFFLENBQUM7SUFDRixPQUFPLENBQ0wsS0FBSyxJQUFJO1FBQ1AsSUFBSTtRQUNKLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ2QsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDbEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDZCxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNsQixNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNoQixJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztLQUNmLENBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmcm9tTm9kZVByb3ZpZGVyQ2hhaW4gfSBmcm9tICdAYXdzLXNkay9jcmVkZW50aWFsLXByb3ZpZGVycyc7XG5pbXBvcnQgeyBDcmVkZW50aWFscyB9IGZyb20gJ0Bhd3Mtc2RrL3R5cGVzJztcbmltcG9ydCAqIGFzIGF3czQgZnJvbSAnYXdzNCc7XG5cbi8vIFwiXCJ3c3M6Ly9tNmczdzZ0dGRoLmV4ZWN1dGUtYXBpLmV1LXdlc3QtMS5hbWF6b25hd3MuY29tL3Byb2RcIjtcIlxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0U2lnbmVkV2ViU29ja2V0VXJsKFxuICB1cmw6IHN0cmluZyxcbiAgY3JlZGVudGlhbHM/OiBDcmVkZW50aWFsc1xuKSB7XG4gIGxldCBob3N0UGFydHM6IHN0cmluZ1tdO1xuICBsZXQgcGF0aG5hbWU6IHN0cmluZztcblxuICBpZiAoIXVybCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB3ZWJzb2NrZXQgVVJMYCk7XG4gIH1cblxuICB0cnkge1xuICAgIG5ldyBVUkwodXJsKTsgLy92YWxpZGF0ZSBVUkxcblxuICAgIGNvbnN0IHVybFBhcnNlZCA9IHBhcnNlVXJsKHVybCk7XG4gICAgcGF0aG5hbWUgPSB1cmxQYXJzZWQhLnBhdGhuYW1lITtcbiAgICBob3N0UGFydHMgPSB1cmxQYXJzZWQhLmhvc3Quc3BsaXQoJy4nKTtcbiAgfSBjYXRjaCB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHdlYnNvY2tldCBVUkwgJHt1cmx9YCk7XG4gIH1cblxuICBpZiAoIWNyZWRlbnRpYWxzKSB7XG4gICAgY29uc3QgY3JlZGVudGlhbHNQcm92aWRlciA9IGZyb21Ob2RlUHJvdmlkZXJDaGFpbigpO1xuICAgIGNyZWRlbnRpYWxzID0gYXdhaXQgY3JlZGVudGlhbHNQcm92aWRlcigpO1xuICB9XG5cbiAgY29uc3QgQVdTX1JFR0lPTiA9IGhvc3RQYXJ0c1syXTsgLy8gVGhlIHJlZ2lvbiBvZiB5b3VyIEFQSS1nYXRld2F5XG4gIGNvbnN0IFNPQ0tFVF9IT1NUID0gaG9zdFBhcnRzWzBdOyAvLyBZb3VyIEFQSS1nYXRld2F5IElEXG4gIGNvbnN0IEVOViA9IHBhdGhuYW1lLnJlcGxhY2UoL15cXC8vLCAnJyk7IC8vIFRoZSBzdGFnZSBvZiB5b3VyIHRhcmdldCBkZXBsb3ltZW50XG4gIGNvbnN0IFdFQlNPQ0tFVF9VUkwgPSBgJHtTT0NLRVRfSE9TVH0uZXhlY3V0ZS1hcGkuJHtBV1NfUkVHSU9OfS5hbWF6b25hd3MuY29tYDsgLy8gRG9uJ3QgcHJlcGVuZCB3aXRoIHdzcyFcbiAgLy8gY29uc3QgQVdTX1JFR0lPTiA9IFwiZXUtd2VzdC0xXCI7IC8vIFRoZSByZWdpb24gb2YgeW91ciBBUEktZ2F0ZXdheVxuICAvLyBjb25zdCBTT0NLRVRfSE9TVCA9IFwibTZnM3c2dHRkaFwiOyAvLyBZb3VyIEFQSS1nYXRld2F5IElEXG4gIC8vIGNvbnN0IEVOViA9IFwicHJvZFwiOyAvLyBUaGUgc3RhZ2Ugb2YgeW91ciB0YXJnZXQgZGVwbG95bWVudFxuICAvLyBjb25zdCBXRUJTT0NLRVRfVVJMID0gYCR7U09DS0VUX0hPU1R9LmV4ZWN1dGUtYXBpLiR7QVdTX1JFR0lPTn0uYW1hem9uYXdzLmNvbWA7IC8vIERvbid0IHByZXBlbmQgd2l0aCB3c3MhXG5cbiAgLy8gR2V0IGEgc2lnbmVkIHBhdGhcbiAgY29uc3QgeyBwYXRoIH0gPSBhd3M0LnNpZ24oXG4gICAge1xuICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgIGhvc3Q6IFdFQlNPQ0tFVF9VUkwsXG4gICAgICAvLyBwYXRoOiBgLyR7RU5WfT9YLUFtei1TZWN1cml0eS1Ub2tlbj0ke2VuY29kZVVSSUNvbXBvbmVudChcbiAgICAgIC8vICAgY3JlZGVudGlhbHMhLlNlc3Npb25Ub2tlbiFcbiAgICAgIC8vICl9YCxcbiAgICAgIHBhdGg6IGAvJHtFTlZ9YCxcbiAgICAgIHNlcnZpY2U6ICdleGVjdXRlLWFwaScsXG4gICAgICByZWdpb246IEFXU19SRUdJT04sXG4gICAgICBzaWduUXVlcnk6IHRydWUsXG4gICAgfSxcbiAgICB7XG4gICAgICBhY2Nlc3NLZXlJZDogY3JlZGVudGlhbHMuYWNjZXNzS2V5SWQsXG4gICAgICBzZWNyZXRBY2Nlc3NLZXk6IGNyZWRlbnRpYWxzLnNlY3JldEFjY2Vzc0tleSxcbiAgICAgIHNlc3Npb25Ub2tlbjogY3JlZGVudGlhbHMuc2Vzc2lvblRva2VuLFxuICAgIH1cbiAgKTtcblxuICBjb25zdCB1cmwyID0gYHdzczovLyR7V0VCU09DS0VUX1VSTH0ke3BhdGh9YDtcbiAgcmV0dXJuIHVybDI7XG59XG5cbmZ1bmN0aW9uIHBhcnNlVXJsKGhyZWY6IHN0cmluZykge1xuICBjb25zdCBtYXRjaCA9IGhyZWYubWF0Y2goXG4gICAgL14od3NzPzopXFwvXFwvKChbXjovPyNdKikoPzo6KFswLTldKykpPykoWy9dezAsMX1bXj8jXSopKFxcP1teI10qfCkoIy4qfCkkL1xuICApO1xuICByZXR1cm4gKFxuICAgIG1hdGNoICYmIHtcbiAgICAgIGhyZWYsXG4gICAgICBwcm90b2NvbDogbWF0Y2hbMV0sXG4gICAgICBob3N0OiBtYXRjaFsyXSxcbiAgICAgIGhvc3RuYW1lOiBtYXRjaFszXSxcbiAgICAgIHBvcnQ6IG1hdGNoWzRdLFxuICAgICAgcGF0aG5hbWU6IG1hdGNoWzVdLFxuICAgICAgc2VhcmNoOiBtYXRjaFs2XSxcbiAgICAgIGhhc2g6IG1hdGNoWzddLFxuICAgIH1cbiAgKTtcbn1cbiJdfQ==
|