@alliander-opensource/aws-jwt-sts 0.2.6

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.
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ // SPDX-FileCopyrightText: 2023 Alliander NV
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handler = void 0;
7
+ const client_kms_1 = require("@aws-sdk/client-kms");
8
+ const client_s3_1 = require("@aws-sdk/client-s3");
9
+ const jsrsasign_1 = require("jsrsasign");
10
+ const client = new client_kms_1.KMSClient({});
11
+ const ALIAS_PREVIOUS = 'alias/sts/PREVIOUS';
12
+ const ALIAS_CURRENT = 'alias/sts/CURRENT';
13
+ const ALIAS_PENDING = 'alias/sts/PENDING';
14
+ const ALIASES = [
15
+ ALIAS_PREVIOUS,
16
+ ALIAS_CURRENT,
17
+ ALIAS_PENDING
18
+ ];
19
+ const handler = async (event) => {
20
+ // retrieve the step from the event
21
+ const step = (event.step);
22
+ // match the step with the corresponding function
23
+ switch (step) {
24
+ case 'deletePrevious':
25
+ await deletePrevious();
26
+ break;
27
+ case 'movePrevious':
28
+ await movePrevious();
29
+ break;
30
+ case 'moveCurrent':
31
+ await moveCurrent();
32
+ break;
33
+ case 'createPending':
34
+ await createPending();
35
+ break;
36
+ case 'generateArtifacts':
37
+ await generateJWKS();
38
+ await generateOpenIDConfiguration();
39
+ break;
40
+ default:
41
+ console.log('invalid step');
42
+ }
43
+ };
44
+ exports.handler = handler;
45
+ async function deletePrevious() {
46
+ console.log('Deleting PREVIOUS aliased key');
47
+ const prevKeyId = await getKeyIdForAlias(ALIAS_PREVIOUS);
48
+ if (prevKeyId) {
49
+ const ScheduleDeleteResponse = await client.send(new client_kms_1.ScheduleKeyDeletionCommand({ KeyId: prevKeyId }));
50
+ console.log(ScheduleDeleteResponse);
51
+ }
52
+ else {
53
+ console.log('No PREVIOUS key at the moment, skip deletion');
54
+ }
55
+ }
56
+ async function movePrevious() {
57
+ console.log('moving PREVIOUS alias');
58
+ const currentKeyId = await getKeyIdForAlias(ALIAS_CURRENT);
59
+ if (currentKeyId) {
60
+ await updateOrCreateAlias(ALIAS_PREVIOUS, currentKeyId);
61
+ }
62
+ else {
63
+ console.log('No CURRENT key at the moment, skip assigning the PREVIOUS alias to this key.');
64
+ }
65
+ }
66
+ async function moveCurrent() {
67
+ console.log('Moving CURRENT alias');
68
+ const pendingKeyId = await getKeyIdForAlias(ALIAS_PENDING);
69
+ if (pendingKeyId) {
70
+ await updateOrCreateAlias(ALIAS_CURRENT, pendingKeyId);
71
+ }
72
+ else {
73
+ console.log('No PENDING key at the moment, skip assigning the CURRENT alias to this key.');
74
+ }
75
+ }
76
+ async function createPending() {
77
+ console.log('Creating new key for PENDING');
78
+ // Create new key
79
+ const createResponse = await client.send(new client_kms_1.CreateKeyCommand({
80
+ KeySpec: 'RSA_2048',
81
+ KeyUsage: 'SIGN_VERIFY'
82
+ }));
83
+ console.log(createResponse);
84
+ // Update the new key with pending alias
85
+ await updateOrCreateAlias(ALIAS_PENDING, createResponse.KeyMetadata.KeyId);
86
+ }
87
+ async function updateOrCreateAlias(aliasName, keyId) {
88
+ try {
89
+ const updateResponse = await client.send(new client_kms_1.UpdateAliasCommand({
90
+ AliasName: aliasName,
91
+ TargetKeyId: keyId
92
+ }));
93
+ console.log(updateResponse);
94
+ }
95
+ catch (err) {
96
+ if (err instanceof client_kms_1.NotFoundException) {
97
+ console.log('ALIAS not found, creating it.');
98
+ const createResponse = await client.send(new client_kms_1.CreateAliasCommand({
99
+ AliasName: aliasName,
100
+ TargetKeyId: keyId
101
+ }));
102
+ console.log(createResponse);
103
+ }
104
+ else {
105
+ throw (err);
106
+ }
107
+ }
108
+ }
109
+ async function getKeyIdForAlias(keyId) {
110
+ try {
111
+ const response = await client.send(new client_kms_1.DescribeKeyCommand({ KeyId: keyId }));
112
+ console.log(response);
113
+ return response.KeyMetadata?.KeyId;
114
+ }
115
+ catch (err) {
116
+ if (err instanceof client_kms_1.NotFoundException) {
117
+ return null;
118
+ }
119
+ else {
120
+ throw err;
121
+ }
122
+ }
123
+ }
124
+ async function generateJWKS() {
125
+ const allKeys = [];
126
+ for (const keyAlias of ALIASES) {
127
+ const keyId = await getKeyIdForAlias(keyAlias);
128
+ if (keyId) {
129
+ const jwkContents = await generateJWK(keyAlias);
130
+ await setKMSKeyTags(keyId, [{ TagKey: 'jwk_kid', TagValue: jwkContents.kid }]);
131
+ allKeys.push(jwkContents);
132
+ }
133
+ }
134
+ const result = { keys: allKeys };
135
+ await uploadToS3('discovery/keys', result);
136
+ }
137
+ async function generateOpenIDConfiguration() {
138
+ const issuer = process.env.ISSUER;
139
+ const openIdConfiguration = {
140
+ issuer,
141
+ jwks_uri: `${issuer}/discovery/keys`,
142
+ response_types_supported: [
143
+ 'token'
144
+ ],
145
+ id_token_signing_alg_values_supported: [
146
+ 'RS256'
147
+ ],
148
+ scopes_supported: [
149
+ 'openid'
150
+ ],
151
+ token_endpoint_auth_methods_supported: [
152
+ 'client_secret_basic'
153
+ ],
154
+ claims_supported: [
155
+ 'aud',
156
+ 'exp',
157
+ 'iat',
158
+ 'iss',
159
+ 'sub'
160
+ ]
161
+ };
162
+ await uploadToS3('.well-known/openid-configuration', openIdConfiguration);
163
+ }
164
+ async function generateJWK(keyAlias) {
165
+ // Get the public key from kms
166
+ const getPubKeyResponse = await client.send(new client_kms_1.GetPublicKeyCommand({ KeyId: keyAlias }));
167
+ // generate HEX format from the response (DER)
168
+ const pubKeyHex = Buffer.from(getPubKeyResponse.PublicKey).toString('hex');
169
+ // Get the pub key in pem format
170
+ const pubKeyPem = jsrsasign_1.KJUR.asn1.ASN1Util.getPEMStringFromHex(pubKeyHex, 'PUBLIC KEY');
171
+ // return the JWK format for the key
172
+ const jwk = jsrsasign_1.KEYUTIL.getJWK(pubKeyPem);
173
+ jwk.use = 'sig';
174
+ jwk.alg = 'RS256';
175
+ return jwk;
176
+ }
177
+ async function setKMSKeyTags(keyAlias, tags) {
178
+ return await client.send(new client_kms_1.TagResourceCommand({ KeyId: keyAlias, Tags: tags }));
179
+ }
180
+ async function uploadToS3(key, contents) {
181
+ // get S3 bucket from environment variables
182
+ const s3Bucket = process.env.S3_BUCKET;
183
+ const s3client = new client_s3_1.S3Client({});
184
+ // Write jwk to s3 bucket
185
+ await s3client.send(new client_s3_1.PutObjectCommand({
186
+ Bucket: s3Bucket,
187
+ Key: key,
188
+ Body: Buffer.from(JSON.stringify(contents)),
189
+ ContentType: 'application/json',
190
+ ContentEncoding: ''
191
+ }));
192
+ }
193
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXgua2V5cm90YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2luZGV4LmtleXJvdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNENBQTRDO0FBQzVDLEVBQUU7QUFDRixzQ0FBc0M7OztBQUV0QyxvREFXNEI7QUFDNUIsa0RBQStEO0FBQy9ELHlDQUF5QztBQUV6QyxNQUFNLE1BQU0sR0FBRyxJQUFJLHNCQUFTLENBQUMsRUFBRSxDQUFDLENBQUE7QUFFaEMsTUFBTSxjQUFjLEdBQUcsb0JBQW9CLENBQUE7QUFDM0MsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUE7QUFDekMsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUE7QUFFekMsTUFBTSxPQUFPLEdBQWE7SUFDeEIsY0FBYztJQUNkLGFBQWE7SUFDYixhQUFhO0NBQ2QsQ0FBQTtBQUVNLE1BQU0sT0FBTyxHQUFHLEtBQUssRUFBRSxLQUFVLEVBQWdCLEVBQUU7SUFDeEQsbUNBQW1DO0lBQ25DLE1BQU0sSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBRXpCLGlEQUFpRDtJQUNqRCxRQUFRLElBQUksRUFBRTtRQUNaLEtBQUssZ0JBQWdCO1lBQ25CLE1BQU0sY0FBYyxFQUFFLENBQUE7WUFDdEIsTUFBSztRQUNQLEtBQUssY0FBYztZQUNqQixNQUFNLFlBQVksRUFBRSxDQUFBO1lBQ3BCLE1BQUs7UUFDUCxLQUFLLGFBQWE7WUFDaEIsTUFBTSxXQUFXLEVBQUUsQ0FBQTtZQUNuQixNQUFLO1FBQ1AsS0FBSyxlQUFlO1lBQ2xCLE1BQU0sYUFBYSxFQUFFLENBQUE7WUFDckIsTUFBSztRQUNQLEtBQUssbUJBQW1CO1lBQ3RCLE1BQU0sWUFBWSxFQUFFLENBQUE7WUFDcEIsTUFBTSwyQkFBMkIsRUFBRSxDQUFBO1lBQ25DLE1BQUs7UUFFUDtZQUNFLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUE7S0FDOUI7QUFD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QVc7SUFDekQsT0FBTyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSwrQkFBa0IsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUNuRixDQUFDO0FBRUQsS0FBSyxVQUFVLFVBQVUsQ0FBRSxHQUFXLEVBQUUsUUFBZ0I7SUFDdEQsMkNBQTJDO0lBQzNDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFBO0lBRXRDLE1BQU0sUUFBUSxHQUFHLElBQUksb0JBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUVqQyx5QkFBeUI7SUFDekIsTUFBTSxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksNEJBQWdCLENBQUM7UUFDdkMsTUFBTSxFQUFFLFFBQVE7UUFDaEIsR0FBRyxFQUFFLEdBQUc7UUFDUixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzNDLFdBQVcsRUFBRSxrQkFBa0I7UUFDL0IsZUFBZSxFQUFFLEVBQUU7S0FDcEIsQ0FBQyxDQUFDLENBQUE7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1GaWxlQ29weXJpZ2h0VGV4dDogMjAyMyBBbGxpYW5kZXIgTlZcbi8vXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQge1xuICBLTVNDbGllbnQsXG4gIERlc2NyaWJlS2V5Q29tbWFuZCxcbiAgR2V0UHVibGljS2V5Q29tbWFuZCxcbiAgQ3JlYXRlS2V5Q29tbWFuZCxcbiAgVXBkYXRlQWxpYXNDb21tYW5kLFxuICBTY2hlZHVsZUtleURlbGV0aW9uQ29tbWFuZCxcbiAgVGFnUmVzb3VyY2VDb21tYW5kLFxuICBUYWcsXG4gIE5vdEZvdW5kRXhjZXB0aW9uLFxuICBDcmVhdGVBbGlhc0NvbW1hbmRcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWttcydcbmltcG9ydCB7IFMzQ2xpZW50LCBQdXRPYmplY3RDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXMzJ1xuaW1wb3J0IHsgS0VZVVRJTCwgS0pVUiB9IGZyb20gJ2pzcnNhc2lnbidcblxuY29uc3QgY2xpZW50ID0gbmV3IEtNU0NsaWVudCh7fSlcblxuY29uc3QgQUxJQVNfUFJFVklPVVMgPSAnYWxpYXMvc3RzL1BSRVZJT1VTJ1xuY29uc3QgQUxJQVNfQ1VSUkVOVCA9ICdhbGlhcy9zdHMvQ1VSUkVOVCdcbmNvbnN0IEFMSUFTX1BFTkRJTkcgPSAnYWxpYXMvc3RzL1BFTkRJTkcnXG5cbmNvbnN0IEFMSUFTRVM6IHN0cmluZ1tdID0gW1xuICBBTElBU19QUkVWSU9VUyxcbiAgQUxJQVNfQ1VSUkVOVCxcbiAgQUxJQVNfUEVORElOR1xuXVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jIChldmVudDogYW55KTogUHJvbWlzZTxhbnk+ID0+IHtcbiAgLy8gcmV0cmlldmUgdGhlIHN0ZXAgZnJvbSB0aGUgZXZlbnRcbiAgY29uc3Qgc3RlcCA9IChldmVudC5zdGVwKVxuXG4gIC8vIG1hdGNoIHRoZSBzdGVwIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgZnVuY3Rpb25cbiAgc3dpdGNoIChzdGVwKSB7XG4gICAgY2FzZSAnZGVsZXRlUHJldmlvdXMnOlxuICAgICAgYXdhaXQgZGVsZXRlUHJldmlvdXMoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdtb3ZlUHJldmlvdXMnOlxuICAgICAgYXdhaXQgbW92ZVByZXZpb3VzKClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnbW92ZUN1cnJlbnQnOlxuICAgICAgYXdhaXQgbW92ZUN1cnJlbnQoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdjcmVhdGVQZW5kaW5nJzpcbiAgICAgIGF3YWl0IGNyZWF0ZVBlbmRpbmcoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdnZW5lcmF0ZUFydGlmYWN0cyc6XG4gICAgICBhd2FpdCBnZW5lcmF0ZUpXS1MoKVxuICAgICAgYXdhaXQgZ2VuZXJhdGVPcGVuSURDb25maWd1cmF0aW9uKClcbiAgICAgIGJyZWFrXG5cbiAgICBkZWZhdWx0OlxuICAgICAgY29uc29sZS5sb2coJ2ludmFsaWQgc3RlcCcpXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVsZXRlUHJldmlvdXMgKCkge1xuICBjb25zb2xlLmxvZygnRGVsZXRpbmcgUFJFVklPVVMgYWxpYXNlZCBrZXknKVxuXG4gIGNvbnN0IHByZXZLZXlJZCA9IGF3YWl0IGdldEtleUlkRm9yQWxpYXMoQUxJQVNfUFJFVklPVVMpXG4gIGlmIChwcmV2S2V5SWQpIHtcbiAgICBjb25zdCBTY2hlZHVsZURlbGV0ZVJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnNlbmQoXG4gICAgICBuZXcgU2NoZWR1bGVLZXlEZWxldGlvbkNvbW1hbmQoeyBLZXlJZDogcHJldktleUlkIH0pXG4gICAgKVxuICAgIGNvbnNvbGUubG9nKFNjaGVkdWxlRGVsZXRlUmVzcG9uc2UpXG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coJ05vIFBSRVZJT1VTIGtleSBhdCB0aGUgbW9tZW50LCBza2lwIGRlbGV0aW9uJylcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtb3ZlUHJldmlvdXMgKCkge1xuICBjb25zb2xlLmxvZygnbW92aW5nIFBSRVZJT1VTIGFsaWFzJylcbiAgY29uc3QgY3VycmVudEtleUlkID0gYXdhaXQgZ2V0S2V5SWRGb3JBbGlhcyhBTElBU19DVVJSRU5UKVxuICBpZiAoY3VycmVudEtleUlkKSB7XG4gICAgYXdhaXQgdXBkYXRlT3JDcmVhdGVBbGlhcyhBTElBU19QUkVWSU9VUywgY3VycmVudEtleUlkKVxuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKCdObyBDVVJSRU5UIGtleSBhdCB0aGUgbW9tZW50LCBza2lwIGFzc2lnbmluZyB0aGUgUFJFVklPVVMgYWxpYXMgdG8gdGhpcyBrZXkuJylcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtb3ZlQ3VycmVudCAoKSB7XG4gIGNvbnNvbGUubG9nKCdNb3ZpbmcgQ1VSUkVOVCBhbGlhcycpXG5cbiAgY29uc3QgcGVuZGluZ0tleUlkID0gYXdhaXQgZ2V0S2V5SWRGb3JBbGlhcyhBTElBU19QRU5ESU5HKVxuICBpZiAocGVuZGluZ0tleUlkKSB7XG4gICAgYXdhaXQgdXBkYXRlT3JDcmVhdGVBbGlhcyhBTElBU19DVVJSRU5ULCBwZW5kaW5nS2V5SWQpXG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coJ05vIFBFTkRJTkcga2V5IGF0IHRoZSBtb21lbnQsIHNraXAgYXNzaWduaW5nIHRoZSBDVVJSRU5UIGFsaWFzIHRvIHRoaXMga2V5LicpXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlUGVuZGluZyAoKSB7XG4gIGNvbnNvbGUubG9nKCdDcmVhdGluZyBuZXcga2V5IGZvciBQRU5ESU5HJylcblxuICAvLyBDcmVhdGUgbmV3IGtleVxuICBjb25zdCBjcmVhdGVSZXNwb25zZSA9IGF3YWl0IGNsaWVudC5zZW5kKG5ldyBDcmVhdGVLZXlDb21tYW5kKHtcbiAgICBLZXlTcGVjOiAnUlNBXzIwNDgnLFxuICAgIEtleVVzYWdlOiAnU0lHTl9WRVJJRlknXG4gIH0pKVxuICBjb25zb2xlLmxvZyhjcmVhdGVSZXNwb25zZSlcblxuICAvLyBVcGRhdGUgdGhlIG5ldyBrZXkgd2l0aCBwZW5kaW5nIGFsaWFzXG4gIGF3YWl0IHVwZGF0ZU9yQ3JlYXRlQWxpYXMoQUxJQVNfUEVORElORywgY3JlYXRlUmVzcG9uc2UuS2V5TWV0YWRhdGEhLktleUlkISlcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlT3JDcmVhdGVBbGlhcyAoYWxpYXNOYW1lOiBzdHJpbmcsIGtleUlkOiBzdHJpbmcpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IGNsaWVudC5zZW5kKG5ldyBVcGRhdGVBbGlhc0NvbW1hbmQoe1xuICAgICAgQWxpYXNOYW1lOiBhbGlhc05hbWUsXG4gICAgICBUYXJnZXRLZXlJZDoga2V5SWRcbiAgICB9KSlcbiAgICBjb25zb2xlLmxvZyh1cGRhdGVSZXNwb25zZSlcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uKSB7XG4gICAgICBjb25zb2xlLmxvZygnQUxJQVMgbm90IGZvdW5kLCBjcmVhdGluZyBpdC4nKVxuICAgICAgY29uc3QgY3JlYXRlUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuc2VuZChuZXcgQ3JlYXRlQWxpYXNDb21tYW5kKHtcbiAgICAgICAgQWxpYXNOYW1lOiBhbGlhc05hbWUsXG4gICAgICAgIFRhcmdldEtleUlkOiBrZXlJZFxuICAgICAgfSkpXG4gICAgICBjb25zb2xlLmxvZyhjcmVhdGVSZXNwb25zZSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgKGVycilcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0S2V5SWRGb3JBbGlhcyAoa2V5SWQ6IHN0cmluZykge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlS2V5Q29tbWFuZCh7IEtleUlkOiBrZXlJZCB9KSlcbiAgICBjb25zb2xlLmxvZyhyZXNwb25zZSlcbiAgICByZXR1cm4gcmVzcG9uc2UuS2V5TWV0YWRhdGE/LktleUlkXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBOb3RGb3VuZEV4Y2VwdGlvbikge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlSldLUyAoKSB7XG4gIGNvbnN0IGFsbEtleXM6IG9iamVjdFtdID0gW11cblxuICBmb3IgKGNvbnN0IGtleUFsaWFzIG9mIEFMSUFTRVMpIHtcbiAgICBjb25zdCBrZXlJZCA9IGF3YWl0IGdldEtleUlkRm9yQWxpYXMoa2V5QWxpYXMpXG4gICAgaWYgKGtleUlkKSB7XG4gICAgICBjb25zdCBqd2tDb250ZW50cyA9IGF3YWl0IGdlbmVyYXRlSldLKGtleUFsaWFzKVxuICAgICAgYXdhaXQgc2V0S01TS2V5VGFncyhrZXlJZCwgW3sgVGFnS2V5OiAnandrX2tpZCcsIFRhZ1ZhbHVlOiBqd2tDb250ZW50cy5raWQgfV0pXG4gICAgICBhbGxLZXlzLnB1c2goandrQ29udGVudHMpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0geyBrZXlzOiBhbGxLZXlzIH1cblxuICBhd2FpdCB1cGxvYWRUb1MzKCdkaXNjb3Zlcnkva2V5cycsIHJlc3VsdClcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVPcGVuSURDb25maWd1cmF0aW9uICgpIHtcbiAgY29uc3QgaXNzdWVyID0gcHJvY2Vzcy5lbnYuSVNTVUVSXG5cbiAgY29uc3Qgb3BlbklkQ29uZmlndXJhdGlvbiA9IHtcbiAgICBpc3N1ZXIsXG4gICAgandrc191cmk6IGAke2lzc3Vlcn0vZGlzY292ZXJ5L2tleXNgLFxuICAgIHJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZDogW1xuICAgICAgJ3Rva2VuJ1xuICAgIF0sXG4gICAgaWRfdG9rZW5fc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZDogW1xuICAgICAgJ1JTMjU2J1xuICAgIF0sXG4gICAgc2NvcGVzX3N1cHBvcnRlZDogW1xuICAgICAgJ29wZW5pZCdcbiAgICBdLFxuICAgIHRva2VuX2VuZHBvaW50X2F1dGhfbWV0aG9kc19zdXBwb3J0ZWQ6IFtcbiAgICAgICdjbGllbnRfc2VjcmV0X2Jhc2ljJ1xuICAgIF0sXG4gICAgY2xhaW1zX3N1cHBvcnRlZDogW1xuICAgICAgJ2F1ZCcsXG4gICAgICAnZXhwJyxcbiAgICAgICdpYXQnLFxuICAgICAgJ2lzcycsXG4gICAgICAnc3ViJ1xuICAgIF1cbiAgfVxuXG4gIGF3YWl0IHVwbG9hZFRvUzMoJy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uJywgb3BlbklkQ29uZmlndXJhdGlvbilcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVKV0sgKGtleUFsaWFzOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAvLyBHZXQgdGhlIHB1YmxpYyBrZXkgZnJvbSBrbXNcbiAgY29uc3QgZ2V0UHViS2V5UmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuc2VuZChuZXcgR2V0UHVibGljS2V5Q29tbWFuZCh7IEtleUlkOiBrZXlBbGlhcyB9KSlcblxuICAvLyBnZW5lcmF0ZSBIRVggZm9ybWF0IGZyb20gdGhlIHJlc3BvbnNlIChERVIpXG4gIGNvbnN0IHB1YktleUhleCA9IEJ1ZmZlci5mcm9tKGdldFB1YktleVJlc3BvbnNlLlB1YmxpY0tleSBhcyBVaW50OEFycmF5KS50b1N0cmluZygnaGV4JylcblxuICAvLyBHZXQgdGhlIHB1YiBrZXkgaW4gcGVtIGZvcm1hdFxuICBjb25zdCBwdWJLZXlQZW0gPSBLSlVSLmFzbjEuQVNOMVV0aWwuZ2V0UEVNU3RyaW5nRnJvbUhleChwdWJLZXlIZXgsICdQVUJMSUMgS0VZJylcblxuICAvLyByZXR1cm4gdGhlIEpXSyBmb3JtYXQgZm9yIHRoZSBrZXlcbiAgY29uc3QgandrOiBhbnkgPSBLRVlVVElMLmdldEpXSyhwdWJLZXlQZW0pXG5cbiAgandrLnVzZSA9ICdzaWcnXG4gIGp3ay5hbGcgPSAnUlMyNTYnXG5cbiAgcmV0dXJuIGp3a1xufVxuXG5hc3luYyBmdW5jdGlvbiBzZXRLTVNLZXlUYWdzIChrZXlBbGlhczogc3RyaW5nLCB0YWdzOiBUYWdbXSkge1xuICByZXR1cm4gYXdhaXQgY2xpZW50LnNlbmQobmV3IFRhZ1Jlc291cmNlQ29tbWFuZCh7IEtleUlkOiBrZXlBbGlhcywgVGFnczogdGFncyB9KSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBsb2FkVG9TMyAoa2V5OiBzdHJpbmcsIGNvbnRlbnRzOiBvYmplY3QpIHtcbiAgLy8gZ2V0IFMzIGJ1Y2tldCBmcm9tIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICBjb25zdCBzM0J1Y2tldCA9IHByb2Nlc3MuZW52LlMzX0JVQ0tFVFxuXG4gIGNvbnN0IHMzY2xpZW50ID0gbmV3IFMzQ2xpZW50KHt9KVxuXG4gIC8vIFdyaXRlIGp3ayB0byBzMyBidWNrZXRcbiAgYXdhaXQgczNjbGllbnQuc2VuZChuZXcgUHV0T2JqZWN0Q29tbWFuZCh7XG4gICAgQnVja2V0OiBzM0J1Y2tldCxcbiAgICBLZXk6IGtleSwgLy8gRmlsZSBuYW1lIHlvdSB3YW50IHRvIHNhdmUgYXMgaW4gUzNcbiAgICBCb2R5OiBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShjb250ZW50cykpLFxuICAgIENvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgQ29udGVudEVuY29kaW5nOiAnJ1xuICB9KSlcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { Context, APIGatewayProxyResult } from 'aws-lambda';
2
+ export declare const handler: (apiEvent: import("aws-lambda").APIGatewayProxyEvent, context: Context) => Promise<APIGatewayProxyResult>;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ // SPDX-FileCopyrightText: 2023 Alliander NV
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handler = void 0;
7
+ const client_kms_1 = require("@aws-sdk/client-kms");
8
+ const base64url_1 = require("base64url");
9
+ const logger_1 = require("@aws-lambda-powertools/logger");
10
+ const KEY_ALIAS_CURRENT = 'alias/sts/CURRENT';
11
+ const logger = new logger_1.Logger();
12
+ const handler = async (apiEvent, context) => {
13
+ const identityArn = getARNFromIdentity(apiEvent.requestContext.identity?.userArn);
14
+ logger.debug(identityArn);
15
+ if (identityArn === undefined || identityArn === null) {
16
+ logger.info(`Unable to resolve identityArn for userArn: ${apiEvent.requestContext.identity?.userArn}`);
17
+ return respond('Unable to resolve identity', 400);
18
+ }
19
+ let aud = process.env.DEFAULT_AUDIENCE;
20
+ if (apiEvent.queryStringParameters && apiEvent.queryStringParameters.aud) {
21
+ aud = apiEvent.queryStringParameters.aud;
22
+ }
23
+ const kms = new client_kms_1.KMSClient({});
24
+ // Get KeyID which will be sent as kid in JWT token
25
+ const currentResponse = await kms.send(new client_kms_1.DescribeKeyCommand({ KeyId: `${KEY_ALIAS_CURRENT}` }));
26
+ const currentKeyId = currentResponse.KeyMetadata?.KeyId;
27
+ if (currentKeyId === undefined) {
28
+ return respond('KMS key could not be retrieved', 500);
29
+ }
30
+ // Retrieve Tags for KMS Key - the key is tagged with the `kid` from the JWK which is used in the JWT headers
31
+ const listResourceTagsResponse = await kms.send(new client_kms_1.ListResourceTagsCommand({ KeyId: currentKeyId }));
32
+ const kid = getTagValueFromTags('jwk_kid', listResourceTagsResponse.Tags ?? []);
33
+ if (kid == null) {
34
+ return respond('KMS key is not correctly tagged', 500);
35
+ }
36
+ const iss = process.env.ISSUER;
37
+ // JWT Token headers
38
+ const headers = {
39
+ alg: 'RS256',
40
+ typ: 'JWT',
41
+ kid: `${kid}`
42
+ };
43
+ // prepare token lifetime property values
44
+ const issuedAtDate = new Date();
45
+ const expirationDate = new Date(issuedAtDate);
46
+ const notBeforeDate = new Date(issuedAtDate);
47
+ expirationDate.setTime(expirationDate.getTime() + 60 * 60 * 1000); // valid for one hour
48
+ notBeforeDate.setTime(notBeforeDate.getTime() - 5 * 60 * 1000); // 5m before issuedAtDate
49
+ // JWT Token payload
50
+ const payload = {
51
+ sub: `${identityArn}`,
52
+ aud,
53
+ iss,
54
+ iat: Math.floor(issuedAtDate.getTime() / 1000),
55
+ exp: Math.floor(expirationDate.getTime() / 1000),
56
+ nbf: Math.floor(notBeforeDate.getTime() / 1000)
57
+ };
58
+ // Prepare message to be signed by KMS
59
+ const tokenHeaders = (0, base64url_1.default)(JSON.stringify(headers));
60
+ const tokenPayload = (0, base64url_1.default)(JSON.stringify(payload));
61
+ // Sign message with KMS
62
+ const signResponse = await kms.send(new client_kms_1.SignCommand({
63
+ KeyId: currentKeyId,
64
+ Message: Buffer.from(`${tokenHeaders}.${tokenPayload}`),
65
+ SigningAlgorithm: 'RSASSA_PKCS1_V1_5_SHA_256',
66
+ MessageType: 'RAW'
67
+ }));
68
+ logger.debug(JSON.stringify(signResponse));
69
+ const signature = Buffer
70
+ .from(signResponse.Signature)
71
+ .toString('base64')
72
+ .replace(/\+/g, '-')
73
+ .replace(/\//g, '_')
74
+ .replace(/=/g, '');
75
+ const token = `${tokenHeaders}.${tokenPayload}.${signature}`;
76
+ logger.debug(token);
77
+ return respond(JSON.stringify({
78
+ token
79
+ }));
80
+ };
81
+ exports.handler = handler;
82
+ function respond(message, statusCode = 200) {
83
+ return {
84
+ statusCode,
85
+ body: message
86
+ };
87
+ }
88
+ function getARNFromIdentity(identityArn) {
89
+ if (identityArn === undefined || identityArn === null) {
90
+ return null;
91
+ }
92
+ // Regex for converting arn to base role
93
+ const captGroups = [
94
+ 'arn:aws:sts:',
95
+ '(?<regionName>[^:]*)',
96
+ ':',
97
+ '(?<accountId>\\d{12})',
98
+ ':assumed-role\\/',
99
+ '(?<roleName>[A-z0-9\\-]+?)',
100
+ '\\/',
101
+ '(?<user>[^:]*)',
102
+ '$'
103
+ ];
104
+ const regex = new RegExp(captGroups.join(''));
105
+ const { regionName, accountId, roleName } = regex.exec(identityArn)?.groups ?? {};
106
+ if (regionName === undefined || accountId === undefined || roleName === undefined) {
107
+ return null;
108
+ }
109
+ // Build base role arn
110
+ return `arn:aws:iam:${regionName}:${accountId}:role/${roleName}`;
111
+ }
112
+ function getTagValueFromTags(tagKey, tags) {
113
+ for (const tag of tags) {
114
+ if (tag.TagKey === tagKey) {
115
+ return tag.TagValue;
116
+ }
117
+ }
118
+ return null;
119
+ }
120
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguc2lnbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5zaWduLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw0Q0FBNEM7QUFDNUMsRUFBRTtBQUNGLHNDQUFzQzs7O0FBR3RDLG9EQUE4RztBQUM5Ryx5Q0FBaUM7QUFFakMsMERBQXNEO0FBRXRELE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CLENBQUE7QUFDN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFNLEVBQUUsQ0FBQTtBQUVwQixNQUFNLE9BQU8sR0FBRyxLQUFLLEVBQUUsUUFBeUIsRUFBRSxPQUFnQixFQUFrQyxFQUFFO0lBQzNHLE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ2pGLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBWSxDQUFDLENBQUE7SUFFMUIsSUFBSSxXQUFXLEtBQUssU0FBUyxJQUFJLFdBQVcsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxDQUFDLElBQUksQ0FBQyw4Q0FBOEMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtRQUN0RyxPQUFPLE9BQU8sQ0FBQyw0QkFBNEIsRUFBRSxHQUFHLENBQUMsQ0FBQTtLQUNsRDtJQUVELElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUE7SUFFdEMsSUFBSSxRQUFRLENBQUMscUJBQXFCLElBQUksUUFBUSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsRUFBRTtRQUN4RSxHQUFHLEdBQUcsUUFBUSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQTtLQUN6QztJQUVELE1BQU0sR0FBRyxHQUFHLElBQUksc0JBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUU3QixtREFBbUQ7SUFDbkQsTUFBTSxlQUFlLEdBQUcsTUFBTSxHQUFHLENBQUMs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VyxDQUFDLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQTtJQUVqRixJQUFJLFVBQVUsS0FBSyxTQUFTLElBQUksU0FBUyxLQUFLLFNBQVMsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFO1FBQ2pGLE9BQU8sSUFBSSxDQUFBO0tBQ1o7SUFFRCxzQkFBc0I7SUFDdEIsT0FBTyxlQUFlLFVBQVUsSUFBSSxTQUFTLFNBQVMsUUFBUSxFQUFFLENBQUE7QUFDbEUsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUUsTUFBYyxFQUFFLElBQVc7SUFDdkQsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUU7UUFDdEIsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU0sRUFBRTtZQUN6QixPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUE7U0FDcEI7S0FDRjtJQUVELE9BQU8sSUFBSSxDQUFBO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtRmlsZUNvcHlyaWdodFRleHQ6IDIwMjMgQWxsaWFuZGVyIE5WXG4vL1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgQ29udGV4dCwgQVBJR2F0ZXdheVByb3h5UmVzdWx0LCBBUElHYXRld2F5RXZlbnQgfSBmcm9tICdhd3MtbGFtYmRhJ1xuaW1wb3J0IHsgS01TQ2xpZW50LCBTaWduQ29tbWFuZCwgRGVzY3JpYmVLZXlDb21tYW5kLCBMaXN0UmVzb3VyY2VUYWdzQ29tbWFuZCwgVGFnIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWttcydcbmltcG9ydCBiYXNlNjR1cmwgZnJvbSAnYmFzZTY0dXJsJ1xuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICdAYXdzLWxhbWJkYS1wb3dlcnRvb2xzL2xvZ2dlcidcblxuY29uc3QgS0VZX0FMSUFTX0NVUlJFTlQgPSAnYWxpYXMvc3RzL0NVUlJFTlQnXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKClcblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoYXBpRXZlbnQ6IEFQSUdhdGV3YXlFdmVudCwgY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8QVBJR2F0ZXdheVByb3h5UmVzdWx0PiA9PiB7XG4gIGNvbnN0IGlkZW50aXR5QXJuID0gZ2V0QVJORnJvbUlkZW50aXR5KGFwaUV2ZW50LnJlcXVlc3RDb250ZXh0LmlkZW50aXR5Py51c2VyQXJuKVxuICBsb2dnZXIuZGVidWcoaWRlbnRpdHlBcm4hKVxuXG4gIGlmIChpZGVudGl0eUFybiA9PT0gdW5kZWZpbmVkIHx8IGlkZW50aXR5QXJuID09PSBudWxsKSB7XG4gICAgbG9nZ2VyLmluZm8oYFVuYWJsZSB0byByZXNvbHZlIGlkZW50aXR5QXJuIGZvciB1c2VyQXJuOiAke2FwaUV2ZW50LnJlcXVlc3RDb250ZXh0LmlkZW50aXR5Py51c2VyQXJufWApXG4gICAgcmV0dXJuIHJlc3BvbmQoJ1VuYWJsZSB0byByZXNvbHZlIGlkZW50aXR5JywgNDAwKVxuICB9XG5cbiAgbGV0IGF1ZCA9IHByb2Nlc3MuZW52LkRFRkFVTFRfQVVESUVOQ0VcblxuICBpZiAoYXBpRXZlbnQucXVlcnlTdHJpbmdQYXJhbWV0ZXJzICYmIGFwaUV2ZW50LnF1ZXJ5U3RyaW5nUGFyYW1ldGVycy5hdWQpIHtcbiAgICBhdWQgPSBhcGlFdmVudC5xdWVyeVN0cmluZ1BhcmFtZXRlcnMuYXVkXG4gIH1cblxuICBjb25zdCBrbXMgPSBuZXcgS01TQ2xpZW50KHt9KVxuXG4gIC8vIEdldCBLZXlJRCB3aGljaCB3aWxsIGJlIHNlbnQgYXMga2lkIGluIEpXVCB0b2tlblxuICBjb25zdCBjdXJyZW50UmVzcG9uc2UgPSBhd2FpdCBrbXMuc2VuZChuZXcgRGVzY3JpYmVLZXlDb21tYW5kKHsgS2V5SWQ6IGAke0tFWV9BTElBU19DVVJSRU5UfWAgfSkpXG4gIGNvbnN0IGN1cnJlbnRLZXlJZCA9IGN1cnJlbnRSZXNwb25zZS5LZXlNZXRhZGF0YT8uS2V5SWRcblxuICBpZiAoY3VycmVudEtleUlkID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gcmVzcG9uZCgnS01TIGtleSBjb3VsZCBub3QgYmUgcmV0cmlldmVkJywgNTAwKVxuICB9XG5cbiAgLy8gUmV0cmlldmUgVGFncyBmb3IgS01TIEtleSAtIHRoZSBrZXkgaXMgdGFnZ2VkIHdpdGggdGhlIGBraWRgIGZyb20gdGhlIEpXSyB3aGljaCBpcyB1c2VkIGluIHRoZSBKV1QgaGVhZGVyc1xuICBjb25zdCBsaXN0UmVzb3VyY2VUYWdzUmVzcG9uc2UgPSBhd2FpdCBrbXMuc2VuZChuZXcgTGlzdFJlc291cmNlVGFnc0NvbW1hbmQoeyBLZXlJZDogY3VycmVudEtleUlkIH0pKVxuICBjb25zdCBraWQgPSBnZXRUYWdWYWx1ZUZyb21UYWdzKCdqd2tfa2lkJywgbGlzdFJlc291cmNlVGFnc1Jlc3BvbnNlLlRhZ3MgPz8gW10pXG5cbiAgaWYgKGtpZCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIHJlc3BvbmQoJ0tNUyBrZXkgaXMgbm90IGNvcnJlY3RseSB0YWdnZWQnLCA1MDApXG4gIH1cblxuICBjb25zdCBpc3MgPSBwcm9jZXNzLmVudi5JU1NVRVJcblxuICAvLyBKV1QgVG9rZW4gaGVhZGVyc1xuICBjb25zdCBoZWFkZXJzOiBhbnkgPSB7XG4gICAgYWxnOiAnUlMyNTYnLFxuICAgIHR5cDogJ0pXVCcsXG4gICAga2lkOiBgJHtraWR9YFxuICB9XG5cbiAgLy8gcHJlcGFyZSB0b2tlbiBsaWZldGltZSBwcm9wZXJ0eSB2YWx1ZXNcbiAgY29uc3QgaXNzdWVkQXREYXRlID0gbmV3IERhdGUoKVxuICBjb25zdCBleHBpcmF0aW9uRGF0ZSA9IG5ldyBEYXRlKGlzc3VlZEF0RGF0ZSlcbiAgY29uc3Qgbm90QmVmb3JlRGF0ZSA9IG5ldyBEYXRlKGlzc3VlZEF0RGF0ZSlcbiAgZXhwaXJhdGlvbkRhdGUuc2V0VGltZShleHBpcmF0aW9uRGF0ZS5nZXRUaW1lKCkgKyA2MCAqIDYwICogMTAwMCkgLy8gdmFsaWQgZm9yIG9uZSBob3VyXG4gIG5vdEJlZm9yZURhdGUuc2V0VGltZShub3RCZWZvcmVEYXRlLmdldFRpbWUoKSAtIDUgKiA2MCAqIDEwMDApIC8vIDVtIGJlZm9yZSBpc3N1ZWRBdERhdGVcblxuICAvLyBKV1QgVG9rZW4gcGF5bG9hZFxuICBjb25zdCBwYXlsb2FkOiBhbnkgPSB7XG4gICAgc3ViOiBgJHtpZGVudGl0eUFybn1gLCAvLyBTZXQgcm9sZSBhcm4gYXMgbWVzc2FnZSBmb3IgcGF5bG9hZFxuICAgIGF1ZCxcbiAgICBpc3MsXG4gICAgaWF0OiBNYXRoLmZsb29yKGlzc3VlZEF0RGF0ZS5nZXRUaW1lKCkgLyAxMDAwKSxcbiAgICBleHA6IE1hdGguZmxvb3IoZXhwaXJhdGlvbkRhdGUuZ2V0VGltZSgpIC8gMTAwMCksXG4gICAgbmJmOiBNYXRoLmZsb29yKG5vdEJlZm9yZURhdGUuZ2V0VGltZSgpIC8gMTAwMClcbiAgfVxuXG4gIC8vIFByZXBhcmUgbWVzc2FnZSB0byBiZSBzaWduZWQgYnkgS01TXG4gIGNvbnN0IHRva2VuSGVhZGVycyA9IGJhc2U2NHVybChKU09OLnN0cmluZ2lmeShoZWFkZXJzKSlcbiAgY29uc3QgdG9rZW5QYXlsb2FkID0gYmFzZTY0dXJsKEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKVxuXG4gIC8vIFNpZ24gbWVzc2FnZSB3aXRoIEtNU1xuICBjb25zdCBzaWduUmVzcG9uc2UgPSBhd2FpdCBrbXMuc2VuZChuZXcgU2lnbkNvbW1hbmQoe1xuICAgIEtleUlkOiBjdXJyZW50S2V5SWQsXG4gICAgTWVzc2FnZTogQnVmZmVyLmZyb20oYCR7dG9rZW5IZWFkZXJzfS4ke3Rva2VuUGF5bG9hZH1gKSxcbiAgICBTaWduaW5nQWxnb3JpdGhtOiAnUlNBU1NBX1BLQ1MxX1YxXzVfU0hBXzI1NicsXG4gICAgTWVzc2FnZVR5cGU6ICdSQVcnXG4gIH0pKVxuICBsb2dnZXIuZGVidWcoSlNPTi5zdHJpbmdpZnkoc2lnblJlc3BvbnNlKSlcblxuICBjb25zdCBzaWduYXR1cmUgPSBCdWZmZXJcbiAgICAuZnJvbShzaWduUmVzcG9uc2UuU2lnbmF0dXJlIGFzIFVpbnQ4QXJyYXkpXG4gICAgLnRvU3RyaW5nKCdiYXNlNjQnKVxuICAgIC5yZXBsYWNlKC9cXCsvZywgJy0nKVxuICAgIC5yZXBsYWNlKC9cXC8vZywgJ18nKVxuICAgIC5yZXBsYWNlKC89L2csICcnKVxuXG4gIGNvbnN0IHRva2VuID0gYCR7dG9rZW5IZWFkZXJzfS4ke3Rva2VuUGF5bG9hZH0uJHtzaWduYXR1cmV9YFxuICBsb2dnZXIuZGVidWcodG9rZW4pXG5cbiAgcmV0dXJuIHJlc3BvbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgIHRva2VuXG4gIH0pKVxufVxuXG5mdW5jdGlvbiByZXNwb25kIChtZXNzYWdlOiBzdHJpbmcsIHN0YXR1c0NvZGU6IG51bWJlciA9IDIwMCkge1xuICByZXR1cm4ge1xuICAgIHN0YXR1c0NvZGUsXG4gICAgYm9keTogbWVzc2FnZVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEFSTkZyb21JZGVudGl0eSAoaWRlbnRpdHlBcm46IHN0cmluZyB8IG51bGwpIHtcbiAgaWYgKGlkZW50aXR5QXJuID09PSB1bmRlZmluZWQgfHwgaWRlbnRpdHlBcm4gPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgLy8gUmVnZXggZm9yIGNvbnZlcnRpbmcgYXJuIHRvIGJhc2Ugcm9sZVxuICBjb25zdCBjYXB0R3JvdXBzID0gW1xuICAgICdhcm46YXdzOnN0czonLFxuICAgICcoPzxyZWdpb25OYW1lPlteOl0qKScsIC8vIGdyb3VwIDFcbiAgICAnOicsXG4gICAgJyg/PGFjY291bnRJZD5cXFxcZHsxMn0pJywgLy8gZ3JvdXAgMlxuICAgICc6YXNzdW1lZC1yb2xlXFxcXC8nLFxuICAgICcoPzxyb2xlTmFtZT5bQS16MC05XFxcXC1dKz8pJywgLy8gZ3JvdXAgM1xuICAgICdcXFxcLycsXG4gICAgJyg/PHVzZXI+W146XSopJywgLy8gZ3JvdXAgNFxuICAgICckJ1xuICBdXG5cbiAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKGNhcHRHcm91cHMuam9pbignJykpXG4gIGNvbnN0IHsgcmVnaW9uTmFtZSwgYWNjb3VudElkLCByb2xlTmFtZSB9ID0gcmVnZXguZXhlYyhpZGVudGl0eUFybik/Lmdyb3VwcyA/PyB7fVxuXG4gIGlmIChyZWdpb25OYW1lID09PSB1bmRlZmluZWQgfHwgYWNjb3VudElkID09PSB1bmRlZmluZWQgfHwgcm9sZU5hbWUgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvLyBCdWlsZCBiYXNlIHJvbGUgYXJuXG4gIHJldHVybiBgYXJuOmF3czppYW06JHtyZWdpb25OYW1lfToke2FjY291bnRJZH06cm9sZS8ke3JvbGVOYW1lfWBcbn1cblxuZnVuY3Rpb24gZ2V0VGFnVmFsdWVGcm9tVGFncyAodGFnS2V5OiBzdHJpbmcsIHRhZ3M6IFRhZ1tdKSB7XG4gIGZvciAoY29uc3QgdGFnIG9mIHRhZ3MpIHtcbiAgICBpZiAodGFnLlRhZ0tleSA9PT0gdGFnS2V5KSB7XG4gICAgICByZXR1cm4gdGFnLlRhZ1ZhbHVlXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGxcbn1cbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ // SPDX-FileCopyrightText: 2023 Alliander NV
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const aws_sdk_client_mock_1 = require("aws-sdk-client-mock");
7
+ const client_kms_1 = require("@aws-sdk/client-kms");
8
+ const client_s3_1 = require("@aws-sdk/client-s3");
9
+ const index_keyrotate_1 = require("../index.keyrotate");
10
+ const kmsMock = (0, aws_sdk_client_mock_1.mockClient)(client_kms_1.KMSClient);
11
+ const s3Mock = (0, aws_sdk_client_mock_1.mockClient)(client_s3_1.S3Client);
12
+ const pubKeys = {
13
+ PREVIOUS: {
14
+ pem: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt0O+biOuAYD5FrM2R6dAliN1v9HA5XpsuoAtXTn8OVKsLvvBFEhBFlghvSXPpu71vE/JYpUj0lL7J54o/RmCz9ZRDzojLU7aWEYM2sEC9nO2ITdu8it+rr3faa70+7PGW09o4iFD+mXYUgadYT8VWxrKQ3eV/LQrSM+6/KYl3BhlNZNxwjtbHGWAldOlzvy14I59GU5W/zDPgOIWSQBbpRvoJKT2rzOZYDtn7C62197hJYAU7QIZ4mOz/ia10ayFFI7p2Uogku3tY5cyYEtSWGzlTL3EiEzSvvsfQ0717bA5ybbDqCWtShg8+IoOxmby4K9X7XuGAQZYE/fgNAXg3wIDAQAB',
15
+ jwk_kid: 'reND9IAI5hj2pe8UfKm2X6r-SjW1v7s23oC3_N5WPiQ'
16
+ },
17
+ CURRENT: {
18
+ pem: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/PC3f+8XOs6yway2FhPLdZrWU67RIqFACSPJ0A4q/eJ8GlGXDj8cxHcJBJyvTxEU/rttSe3f44ZfrvwlDUbgAmTi2zYEDrBRHr+LmR6qoyvczLNZkiMmJZygdeOMT87gPx1fb8hhFAXQkOL8dHKiBZ+s4Hls8yu5eMuBhjh+hUYxEQWw0ilDgaXCaGRjooHPSU6+I+Qbm73MuCbBAyzSIAGDKyyD50Kx9Z9Cc0i+6ZfXwWU/2Sda7u4U4R2B/PkhAy0fIjn7kMaw9sgpdQHHxygxQ8y7PduNgDBF/C1zOeKJuRa3QGoMXY9kn/OVBwnZG7bQ9Enz3RnTkM3q0nf9JQIDAQAB',
19
+ jwk_kid: '-NIJE4RQ8NYWrOOh5_JyGKFAobfY5_oCKo1MrNXoQOg'
20
+ },
21
+ PENDING: {
22
+ pem: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzeWAt2aRiX57vDd78OwF+83IdEI0mWh05hXvAzQXMqt+QR49hiIWjJtYh1B3sYvbp9BWC8yo+BlWWtsI5fu5mCXsBBp/Q/sgfArEsji+dWEXc+xGRN3hptb9tT+sabIWmd6Qyw4dYCksrBzJvSLO+Hi10Otd2NtzYbAqjZ6soaaClSnrOiw9+J4/GFHuY5gOw8P0uaMclI5sDLGN+G/ayGpUK7xegfEAd9VB6mhdgWoYEAT6yEDnFt0BwvTOYT6TI/5v6scRE7Bywsq5V2Mz5VZe43POcSt1n7vIZ9cXXHSGW8JPv1KKcniHsxIc3Fc74OjcEbqWKw49kVGCE3ayfQIDAQAB',
23
+ jwk_kid: 'bHyjPYB3AfII8o_X3tGkOCVzThZzQN2UKwKVCO9E9gY'
24
+ }
25
+ };
26
+ describe('handlers/keyrotate/keyrotate.test.ts', () => {
27
+ const OLD_ENV = process.env;
28
+ beforeEach(() => {
29
+ jest.resetModules();
30
+ kmsMock.reset();
31
+ s3Mock.reset();
32
+ process.env = { ...OLD_ENV };
33
+ });
34
+ afterEach(() => {
35
+ kmsMock.reset();
36
+ s3Mock.reset();
37
+ process.env = OLD_ENV;
38
+ });
39
+ test('should generate & upload correct JWKS file to S3', async () => {
40
+ kmsMock
41
+ .on(client_kms_1.GetPublicKeyCommand, { KeyId: 'alias/sts/PREVIOUS' }).resolves({
42
+ PublicKey: base64ToArrayBuffer(pubKeys.PREVIOUS.pem)
43
+ })
44
+ .on(client_kms_1.GetPublicKeyCommand, { KeyId: 'alias/sts/CURRENT' }).resolves({
45
+ PublicKey: base64ToArrayBuffer(pubKeys.CURRENT.pem)
46
+ })
47
+ .on(client_kms_1.GetPublicKeyCommand, { KeyId: 'alias/sts/PENDING' }).resolves({
48
+ PublicKey: base64ToArrayBuffer(pubKeys.PENDING.pem)
49
+ })
50
+ .on(client_kms_1.DescribeKeyCommand, { KeyId: 'alias/sts/PREVIOUS' }).resolves({
51
+ KeyMetadata: {
52
+ KeyId: 'key-1'
53
+ }
54
+ })
55
+ .on(client_kms_1.DescribeKeyCommand, { KeyId: 'alias/sts/CURRENT' }).resolves({
56
+ KeyMetadata: {
57
+ KeyId: 'key-2'
58
+ }
59
+ })
60
+ .on(client_kms_1.DescribeKeyCommand, { KeyId: 'alias/sts/PENDING' }).resolves({
61
+ KeyMetadata: {
62
+ KeyId: 'key-3'
63
+ }
64
+ });
65
+ process.env.S3_BUCKET = 'test-bucket-name';
66
+ process.env.ISSUER = 'test-issuer.com';
67
+ await (0, index_keyrotate_1.handler)({ step: 'generateArtifacts' });
68
+ // @ts-ignore
69
+ const tagsPrevious = kmsMock.call(2).args[0].input.Tags;
70
+ expect(tagsPrevious[0].TagKey).toBe('jwk_kid');
71
+ expect(tagsPrevious[0].TagValue).toBe(pubKeys.PREVIOUS.jwk_kid);
72
+ // @ts-ignore
73
+ const tagsCurrent = kmsMock.call(5).args[0].input.Tags;
74
+ expect(tagsCurrent[0].TagKey).toBe('jwk_kid');
75
+ expect(tagsCurrent[0].TagValue).toBe(pubKeys.CURRENT.jwk_kid);
76
+ // @ts-ignore
77
+ const tagsPending = kmsMock.call(8).args[0].input.Tags;
78
+ expect(tagsPending[0].TagKey).toBe('jwk_kid');
79
+ expect(tagsPending[0].TagValue).toBe(pubKeys.PENDING.jwk_kid);
80
+ // @ts-ignore
81
+ const s3Key = s3Mock.call(0).args[0].input.Key;
82
+ expect(s3Key).toBe('discovery/keys');
83
+ // @ts-ignore
84
+ const s3Bucket = s3Mock.call(0).args[0].input.Bucket;
85
+ expect(s3Bucket).toBe('test-bucket-name');
86
+ // @ts-ignore
87
+ const s3Body = JSON.parse(s3Mock.call(0).args[0].input.Body.toString());
88
+ expect(s3Body).toEqual({
89
+ keys: [
90
+ {
91
+ e: 'AQAB',
92
+ kid: 'reND9IAI5hj2pe8UfKm2X6r-SjW1v7s23oC3_N5WPiQ',
93
+ kty: 'RSA',
94
+ n: 't0O-biOuAYD5FrM2R6dAliN1v9HA5XpsuoAtXTn8OVKsLvvBFEhBFlghvSXPpu71vE_JYpUj0lL7J54o_RmCz9ZRDzojLU7aWEYM2sEC9nO2ITdu8it-rr3faa70-7PGW09o4iFD-mXYUgadYT8VWxrKQ3eV_LQrSM-6_KYl3BhlNZNxwjtbHGWAldOlzvy14I59GU5W_zDPgOIWSQBbpRvoJKT2rzOZYDtn7C62197hJYAU7QIZ4mOz_ia10ayFFI7p2Uogku3tY5cyYEtSWGzlTL3EiEzSvvsfQ0717bA5ybbDqCWtShg8-IoOxmby4K9X7XuGAQZYE_fgNAXg3w',
95
+ alg: 'RS256',
96
+ use: 'sig'
97
+ }, {
98
+ e: 'AQAB',
99
+ kid: '-NIJE4RQ8NYWrOOh5_JyGKFAobfY5_oCKo1MrNXoQOg',
100
+ kty: 'RSA',
101
+ n: '_PC3f-8XOs6yway2FhPLdZrWU67RIqFACSPJ0A4q_eJ8GlGXDj8cxHcJBJyvTxEU_rttSe3f44ZfrvwlDUbgAmTi2zYEDrBRHr-LmR6qoyvczLNZkiMmJZygdeOMT87gPx1fb8hhFAXQkOL8dHKiBZ-s4Hls8yu5eMuBhjh-hUYxEQWw0ilDgaXCaGRjooHPSU6-I-Qbm73MuCbBAyzSIAGDKyyD50Kx9Z9Cc0i-6ZfXwWU_2Sda7u4U4R2B_PkhAy0fIjn7kMaw9sgpdQHHxygxQ8y7PduNgDBF_C1zOeKJuRa3QGoMXY9kn_OVBwnZG7bQ9Enz3RnTkM3q0nf9JQ',
102
+ alg: 'RS256',
103
+ use: 'sig'
104
+ }, {
105
+ e: 'AQAB',
106
+ kid: 'bHyjPYB3AfII8o_X3tGkOCVzThZzQN2UKwKVCO9E9gY',
107
+ kty: 'RSA',
108
+ n: 'zeWAt2aRiX57vDd78OwF-83IdEI0mWh05hXvAzQXMqt-QR49hiIWjJtYh1B3sYvbp9BWC8yo-BlWWtsI5fu5mCXsBBp_Q_sgfArEsji-dWEXc-xGRN3hptb9tT-sabIWmd6Qyw4dYCksrBzJvSLO-Hi10Otd2NtzYbAqjZ6soaaClSnrOiw9-J4_GFHuY5gOw8P0uaMclI5sDLGN-G_ayGpUK7xegfEAd9VB6mhdgWoYEAT6yEDnFt0BwvTOYT6TI_5v6scRE7Bywsq5V2Mz5VZe43POcSt1n7vIZ9cXXHSGW8JPv1KKcniHsxIc3Fc74OjcEbqWKw49kVGCE3ayfQ',
109
+ alg: 'RS256',
110
+ use: 'sig'
111
+ }
112
+ ]
113
+ });
114
+ // @ts-ignore
115
+ const s3KeyOpenidConfiguration = s3Mock.call(1).args[0].input.Key;
116
+ expect(s3KeyOpenidConfiguration).toBe('.well-known/openid-configuration');
117
+ // @ts-ignore
118
+ const s3BodyOpenidConfiguration = JSON.parse(s3Mock.call(1).args[0].input.Body.toString());
119
+ expect(s3BodyOpenidConfiguration).toEqual({
120
+ issuer: 'test-issuer.com',
121
+ jwks_uri: 'test-issuer.com/discovery/keys',
122
+ response_types_supported: [
123
+ 'token'
124
+ ],
125
+ id_token_signing_alg_values_supported: [
126
+ 'RS256'
127
+ ],
128
+ scopes_supported: [
129
+ 'openid'
130
+ ],
131
+ token_endpoint_auth_methods_supported: [
132
+ 'client_secret_basic'
133
+ ],
134
+ claims_supported: [
135
+ 'aud',
136
+ 'exp',
137
+ 'iat',
138
+ 'iss',
139
+ 'sub'
140
+ ]
141
+ });
142
+ });
143
+ });
144
+ function base64ToArrayBuffer(b64) {
145
+ const byteString = atob(b64);
146
+ const byteArray = new Uint8Array(byteString.length);
147
+ for (let i = 0; i < byteString.length; i++) {
148
+ byteArray[i] = byteString.charCodeAt(i);
149
+ }
150
+ return byteArray;
151
+ }
152
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXgua2V5cm90YXRlLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdC9pbmRleC5rZXlyb3RhdGUudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNENBQTRDO0FBQzVDLEVBQUU7QUFDRixzQ0FBc0M7O0FBRXRDLDZEQUFnRDtBQUNoRCxvREFBd0Y7QUFDeEYsa0RBQTZDO0FBRTdDLHdEQUE0QztBQUU1QyxNQUFNLE9BQU8sR0FBRyxJQUFBLGdDQUFVLEVBQUMsc0JBQVMsQ0FBQyxDQUFBO0FBQ3JDLE1BQU0sTUFBTSxHQUFHLElBQUEsZ0NBQVUsRUFBQyxvQkFBUSxDQUFDLENBQUE7QUFFbkMsTUFBTSxPQUFPLEdBQUc7SUFDZCxRQUFRLEVBQUU7UUFDUixHQUFHLEVBQUUsMFlBQTBZO1FBQy9ZLE9BQU8sRUFBRSw2Q0FBNkM7S0FDdkQ7SUFDRCxPQUFPLEVBQUU7UUFDUCxHQUFHLEVBQUUsMFlBQTBZO1FBQy9ZLE9BQU8sRUFBRSw2Q0FBNkM7S0FDdkQ7SUFDRCxPQUFPLEVBQUU7UUFDUCxHQUFHLEVBQUUsMFlBQTBZO1FBQy9ZLE9BQU8sRUFBRSw2Q0FBNkM7S0FDdkQ7Q0FDRixDQUFBO0FBRUQsUUFBUSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtJQUNwRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFBO0lBRTNCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUE7UUFDbkIsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2YsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2QsT0FBTyxDQUFDLEdBQUcsR0FBRyxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUE7SUFDOUIsQ0FBQyxDQUFDLENBQUE7SUFFRixTQUFTLENBQUMsR0FBRyxFQUFFO1FBQ2IsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2YsTUFBTSxDQUFDLEtB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U0FDRixDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBO0FBRUYsU0FBUyxtQkFBbUIsQ0FBRSxHQUFXO0lBQ3ZDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUM1QixNQUFNLFNBQVMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbkQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDMUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUE7S0FDeEM7SUFFRCxPQUFPLFNBQVMsQ0FBQTtBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1GaWxlQ29weXJpZ2h0VGV4dDogMjAyMyBBbGxpYW5kZXIgTlZcbi8vXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBtb2NrQ2xpZW50IH0gZnJvbSAnYXdzLXNkay1jbGllbnQtbW9jaydcbmltcG9ydCB7IEtNU0NsaWVudCwgR2V0UHVibGljS2V5Q29tbWFuZCwgRGVzY3JpYmVLZXlDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWttcydcbmltcG9ydCB7IFMzQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXMzJ1xuXG5pbXBvcnQgeyBoYW5kbGVyIH0gZnJvbSAnLi4vaW5kZXgua2V5cm90YXRlJ1xuXG5jb25zdCBrbXNNb2NrID0gbW9ja0NsaWVudChLTVNDbGllbnQpXG5jb25zdCBzM01vY2sgPSBtb2NrQ2xpZW50KFMzQ2xpZW50KVxuXG5jb25zdCBwdWJLZXlzID0ge1xuICBQUkVWSU9VUzoge1xuICAgIHBlbTogJ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdDBPK2JpT3VBWUQ1RnJNMlI2ZEFsaU4xdjlIQTVYcHN1b0F0WFRuOE9WS3NMdnZCRkVoQkZsZ2h2U1hQcHU3MXZFL0pZcFVqMGxMN0o1NG8vUm1DejlaUkR6b2pMVTdhV0VZTTJzRUM5bk8ySVRkdThpdCtycjNmYWE3MCs3UEdXMDlvNGlGRCttWFlVZ2FkWVQ4Vld4cktRM2VWL0xRclNNKzYvS1lsM0JobE5aTnh3anRiSEdXQWxkT2x6dnkxNEk1OUdVNVcvekRQZ09JV1NRQmJwUnZvSktUMnJ6T1pZRHRuN0M2MjE5N2hKWUFVN1FJWjRtT3ovaWExMGF5RkZJN3AyVW9na3UzdFk1Y3lZRXRTV0d6bFRMM0VpRXpTdnZzZlEwNzE3YkE1eWJiRHFDV3RTaGc4K0lvT3htYnk0SzlYN1h1R0FRWllFL2ZnTkFYZzN3SURBUUFCJyxcbiAgICBqd2tfa2lkOiAncmVORDlJQUk1aGoycGU4VWZLbTJYNnItU2pXMXY3czIzb0MzX041V1BpUSdcbiAgfSxcbiAgQ1VSUkVOVDoge1xuICAgIHBlbTogJ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBL1BDM2YrOFhPczZ5d2F5MkZoUExkWnJXVTY3UklxRkFDU1BKMEE0cS9lSjhHbEdYRGo4Y3hIY0pCSnl2VHhFVS9ydHRTZTNmNDRaZnJ2d2xEVWJnQW1UaTJ6WUVEckJSSHIrTG1SNnFveXZjekxOWmtpTW1KWnlnZGVPTVQ4N2dQeDFmYjhoaEZBWFFrT0w4ZEhLaUJaK3M0SGxzOHl1NWVNdUJoamgraFVZeEVRV3cwaWxEZ2FYQ2FHUmpvb0hQU1U2K0krUWJtNzNNdUNiQkF5elNJQUdES3l5RDUwS3g5WjlDYzBpKzZaZlh3V1UvMlNkYTd1NFU0UjJCL1BraEF5MGZJam43a01hdzlzZ3BkUUhIeHlneFE4eTdQZHVOZ0RCRi9DMXpPZUtKdVJhM1FHb01YWTlrbi9PVkJ3blpHN2JROUVuejNSblRrTTNxMG5mOUpRSURBUUFCJyxcbiAgICBqd2tfa2lkOiAnLU5JSkU0UlE4TllXck9PaDVfSnlHS0ZBb2JmWTVfb0NLbzFNck5Yb1FPZydcbiAgfSxcbiAgUEVORElORzoge1xuICAgIHBlbTogJ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBemVXQXQyYVJpWDU3dkRkNzhPd0YrODNJZEVJMG1XaDA1aFh2QXpRWE1xdCtRUjQ5aGlJV2pKdFloMUIzc1l2YnA5QldDOHlvK0JsV1d0c0k1ZnU1bUNYc0JCcC9RL3NnZkFyRXNqaStkV0VYYyt4R1JOM2hwdGI5dFQrc2FiSVdtZDZReXc0ZFlDa3NyQnpKdlNMTytIaTEwT3RkMk50elliQXFqWjZzb2FhQ2xTbnJPaXc5K0o0L0dGSHVZNWdPdzhQMHVhTWNsSTVzRExHTitHL2F5R3BVSzd4ZWdmRUFkOVZCNm1oZGdXb1lFQVQ2eUVEbkZ0MEJ3dlRPWVQ2VEkvNXY2c2NSRTdCeXdzcTVWMk16NVZaZTQzUE9jU3Qxbjd2SVo5Y1hYSFNHVzhKUHYxS0tjbmlIc3hJYzNGYzc0T2pjRWJxV0t3NDlrVkdDRTNheWZRSURBUUFCJyxcbiAgICBqd2tfa2lkOiAnYkh5alBZQjNBZklJOG9fWDN0R2tPQ1Z6VGhaelFOMlVLd0tWQ085RTlnWSdcbiAgfVxufVxuXG5kZXNjcmliZSgnaGFuZGxlcnMva2V5cm90YXRlL2tleXJvdGF0ZS50ZXN0LnRzJywgKCkgPT4ge1xuICBjb25zdCBPTERfRU5WID0gcHJvY2Vzcy5lbnZcblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBqZXN0LnJlc2V0TW9kdWxlcygpXG4gICAga21zTW9jay5yZXNldCgpXG4gICAgczNNb2NrLnJlc2V0KClcbiAgICBwcm9jZXNzLmVudiA9IHsgLi4uT0xEX0VOViB9XG4gIH0pXG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBrbXNNb2NrLnJlc2V0KClcbiAgICBzM01vY2sucmVzZXQoKVxuICAgIHByb2Nlc3MuZW52ID0gT0xEX0VOVlxuICB9KVxuXG4gIHRlc3QoJ3Nob3VsZCBnZW5lcmF0ZSAmIHVwbG9hZCBjb3JyZWN0IEpXS1MgZmlsZSB0byBTMycsIGFzeW5jICgpID0+IHtcbiAgICBrbXNNb2NrXG4gICAgICAub24oR2V0UHVibGljS2V5Q29tbWFuZCwgeyBLZXlJZDogJ2FsaWFzL3N0cy9QUkVWSU9VUycgfSkucmVzb2x2ZXMoe1xuICAgICAgICBQdWJsaWNLZXk6IGJhc2U2NFRvQXJyYXlCdWZmZXIocHViS2V5cy5QUkVWSU9VUy5wZW0pXG4gICAgICB9KVxuICAgICAgLm9uKEdldFB1YmxpY0tleUNvbW1hbmQsIHsgS2V5SWQ6ICdhbGlhcy9zdHMvQ1VSUkVOVCcgfSkucmVzb2x2ZXMoe1xuICAgICAgICBQdWJsaWNLZXk6IGJhc2U2NFRvQXJyYXlCdWZmZXIocHViS2V5cy5DVVJSRU5ULnBlbSlcbiAgICAgIH0pXG4gICAgICAub24oR2V0UHVibGljS2V5Q29tbWFuZCwgeyBLZXlJZDogJ2FsaWFzL3N0cy9QRU5ESU5HJyB9KS5yZXNvbHZlcyh7XG4gICAgICAgIFB1YmxpY0tleTogYmFzZTY0VG9BcnJheUJ1ZmZlcihwdWJLZXlzLlBFTkRJTkcucGVtKVxuICAgICAgfSlcbiAgICAgIC5vbihEZXNjcmliZUtleUNvbW1hbmQsIHsgS2V5SWQ6ICdhbGlhcy9zdHMvUFJFVklPVVMnIH0pLnJlc29sdmVzKHtcbiAgICAgICAgS2V5TWV0YWRhdGE6IHtcbiAgICAgICAgICBLZXlJZDogJ2tleS0xJ1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLm9uKERlc2NyaWJlS2V5Q29tbWFuZCwgeyBLZXlJZDogJ2FsaWFzL3N0cy9DVVJSRU5UJyB9KS5yZXNvbHZlcyh7XG4gICAgICAgIEtleU1ldGFkYXRhOiB7XG4gICAgICAgICAgS2V5SWQ6ICdrZXktMidcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5vbihEZXNjcmliZUtleUNvbW1hbmQsIHsgS2V5SWQ6ICdhbGlhcy9zdHMvUEVORElORycgfSkucmVzb2x2ZXMoe1xuICAgICAgICBLZXlNZXRhZGF0YToge1xuICAgICAgICAgIEtleUlkOiAna2V5LTMnXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICBwcm9jZXNzLmVudi5TM19CVUNLRVQgPSAndGVzdC1idWNrZXQtbmFtZSdcbiAgICBwcm9jZXNzLmVudi5JU1NVRVIgPSAndGVzdC1pc3N1ZXIuY29tJ1xuXG4gICAgYXdhaXQgaGFuZGxlcih7IHN0ZXA6ICdnZW5lcmF0ZUFydGlmYWN0cycgfSlcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCB0YWdzUHJldmlvdXMgPSBrbXNNb2NrLmNhbGwoMikuYXJnc1swXS5pbnB1dC5UYWdzXG4gICAgZXhwZWN0KHRhZ3NQcmV2aW91c1swXS5UYWdLZXkpLnRvQmUoJ2p3a19raWQnKVxuICAgIGV4cGVjdCh0YWdzUHJldmlvdXNbMF0uVGFnVmFsdWUpLnRvQmUocHViS2V5cy5QUkVWSU9VUy5qd2tfa2lkKVxuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNvbnN0IHRhZ3NDdXJyZW50ID0ga21zTW9jay5jYWxsKDUpLmFyZ3NbMF0uaW5wdXQuVGFnc1xuICAgIGV4cGVjdCh0YWdzQ3VycmVudFswXS5UYWdLZXkpLnRvQmUoJ2p3a19raWQnKVxuICAgIGV4cGVjdCh0YWdzQ3VycmVudFswXS5UYWdWYWx1ZSkudG9CZShwdWJLZXlzLkNVUlJFTlQuandrX2tpZClcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCB0YWdzUGVuZGluZyA9IGttc01vY2suY2FsbCg4KS5hcmdzWzBdLmlucHV0LlRhZ3NcbiAgICBleHBlY3QodGFnc1BlbmRpbmdbMF0uVGFnS2V5KS50b0JlKCdqd2tfa2lkJylcbiAgICBleHBlY3QodGFnc1BlbmRpbmdbMF0uVGFnVmFsdWUpLnRvQmUocHViS2V5cy5QRU5ESU5HLmp3a19raWQpXG5cbiAgICAvLyBAdHMtaWdub3JlXG4gICAgY29uc3QgczNLZXkgPSBzM01vY2suY2FsbCgwKS5hcmdzWzBdLmlucHV0LktleVxuICAgIGV4cGVjdChzM0tleSkudG9CZSgnZGlzY292ZXJ5L2tleXMnKVxuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNvbnN0IHMzQnVja2V0ID0gczNNb2NrLmNhbGwoMCkuYXJnc1swXS5pbnB1dC5CdWNrZXRcbiAgICBleHBlY3QoczNCdWNrZXQpLnRvQmUoJ3Rlc3QtYnVja2V0LW5hbWUnKVxuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNvbnN0IHMzQm9keSA9IEpTT04ucGFyc2UoczNNb2NrLmNhbGwoMCkuYXJnc1swXS5pbnB1dC5Cb2R5LnRvU3RyaW5nKCkpXG4gICAgZXhwZWN0KHMzQm9keSkudG9FcXVhbCh7XG4gICAgICBrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBlOiAnQVFBQicsXG4gICAgICAgICAga2lkOiAncmVORDlJQUk1aGoycGU4VWZLbTJYNnItU2pXMXY3czIzb0MzX041V1BpUScsXG4gICAgICAgICAga3R5OiAnUlNBJyxcbiAgICAgICAgICBuOiAndDBPLWJpT3VBWUQ1RnJNMlI2ZEFsaU4xdjlIQTVYcHN1b0F0WFRuOE9WS3NMdnZCRkVoQkZsZ2h2U1hQcHU3MXZFX0pZcFVqMGxMN0o1NG9fUm1DejlaUkR6b2pMVTdhV0VZTTJzRUM5bk8ySVRkdThpdC1ycjNmYWE3MC03UEdXMDlvNGlGRC1tWFlVZ2FkWVQ4Vld4cktRM2VWX0xRclNNLTZfS1lsM0JobE5aTnh3anRiSEdXQWxkT2x6dnkxNEk1OUdVNVdfekRQZ09JV1NRQmJwUnZvSktUMnJ6T1pZRHRuN0M2MjE5N2hKWUFVN1FJWjRtT3pfaWExMGF5RkZJN3AyVW9na3UzdFk1Y3lZRXRTV0d6bFRMM0VpRXpTdnZzZlEwNzE3YkE1eWJiRHFDV3RTaGc4LUlvT3htYnk0SzlYN1h1R0FRWllFX2ZnTkFYZzN3JyxcbiAgICAgICAgICBhbGc6ICdSUzI1NicsXG4gICAgICAgICAgdXNlOiAnc2lnJ1xuICAgICAgICB9LCB7XG4gICAgICAgICAgZTogJ0FRQUInLFxuICAgICAgICAgIGtpZDogJy1OSUpFNFJROE5ZV3JPT2g1X0p5R0tGQW9iZlk1X29DS28xTXJOWG9RT2cnLFxuICAgICAgICAgIGt0eTogJ1JTQScsXG4gICAgICAgICAgbjogJ19QQzNmLThYT3M2eXdheTJGaFBMZFpyV1U2N1JJcUZBQ1NQSjBBNHFfZUo4R2xHWERqOGN4SGNKQkp5dlR4RVVfcnR0U2UzZjQ0WmZydndsRFViZ0FtVGkyellFRHJCUkhyLUxtUjZxb3l2Y3pMTlpraU1tSlp5Z2RlT01UODdnUHgxZmI4aGhGQVhRa09MOGRIS2lCWi1zNEhsczh5dTVlTXVCaGpoLWhVWXhFUVd3MGlsRGdhWENhR1Jqb29IUFNVNi1JLVFibTczTXVDYkJBeXpTSUFHREt5eUQ1MEt4OVo5Q2MwaS02WmZYd1dVXzJTZGE3dTRVNFIyQl9Qa2hBeTBmSWpuN2tNYXc5c2dwZFFISHh5Z3hROHk3UGR1TmdEQkZfQzF6T2VLSnVSYTNRR29NWFk5a25fT1ZCd25aRzdiUTlFbnozUm5Ua00zcTBuZjlKUScsXG4gICAgICAgICAgYWxnOiAnUlMyNTYnLFxuICAgICAgICAgIHVzZTogJ3NpZydcbiAgICAgICAgfSwge1xuICAgICAgICAgIGU6ICdBUUFCJyxcbiAgICAgICAgICBraWQ6ICdiSHlqUFlCM0FmSUk4b19YM3RHa09DVnpUaFp6UU4yVUt3S1ZDTzlFOWdZJyxcbiAgICAgICAgICBrdHk6ICdSU0EnLFxuICAgICAgICAgIG46ICd6ZVdBdDJhUmlYNTd2RGQ3OE93Ri04M0lkRUkwbVdoMDVoWHZBelFYTXF0LVFSNDloaUlXakp0WWgxQjNzWXZicDlCV0M4eW8tQmxXV3RzSTVmdTVtQ1hzQkJwX1Ffc2dmQXJFc2ppLWRXRVhjLXhHUk4zaHB0Yjl0VC1zYWJJV21kNlF5dzRkWUNrc3JCekp2U0xPLUhpMTBPdGQyTnR6WWJBcWpaNnNvYWFDbFNuck9pdzktSjRfR0ZIdVk1Z093OFAwdWFNY2xJNXNETEdOLUdfYXlHcFVLN3hlZ2ZFQWQ5VkI2bWhkZ1dvWUVBVDZ5RURuRnQwQnd2VE9ZVDZUSV81djZzY1JFN0J5d3NxNVYyTXo1VlplNDNQT2NTdDFuN3ZJWjljWFhIU0dXOEpQdjFLS2NuaUhzeEljM0ZjNzRPamNFYnFXS3c0OWtWR0NFM2F5ZlEnLFxuICAgICAgICAgIGFsZzogJ1JTMjU2JyxcbiAgICAgICAgICB1c2U6ICdzaWcnXG4gICAgICAgIH1dXG4gICAgfSlcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCBzM0tleU9wZW5pZENvbmZpZ3VyYXRpb24gPSBzM01vY2suY2FsbCgxKS5hcmdzWzBdLmlucHV0LktleVxuICAgIGV4cGVjdChzM0tleU9wZW5pZENvbmZpZ3VyYXRpb24pLnRvQmUoJy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uJylcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCBzM0JvZHlPcGVuaWRDb25maWd1cmF0aW9uID0gSlNPTi5wYXJzZShzM01vY2suY2FsbCgxKS5hcmdzWzBdLmlucHV0LkJvZHkudG9TdHJpbmcoKSlcbiAgICBleHBlY3QoczNCb2R5T3BlbmlkQ29uZmlndXJhdGlvbikudG9FcXVhbCh7XG4gICAgICBpc3N1ZXI6ICd0ZXN0LWlzc3Vlci5jb20nLFxuICAgICAgandrc191cmk6ICd0ZXN0LWlzc3Vlci5jb20vZGlzY292ZXJ5L2tleXMnLFxuICAgICAgcmVzcG9uc2VfdHlwZXNfc3VwcG9ydGVkOiBbXG4gICAgICAgICd0b2tlbidcbiAgICAgIF0sXG4gICAgICBpZF90b2tlbl9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkOiBbXG4gICAgICAgICdSUzI1NidcbiAgICAgIF0sXG4gICAgICBzY29wZXNfc3VwcG9ydGVkOiBbXG4gICAgICAgICdvcGVuaWQnXG4gICAgICBdLFxuICAgICAgdG9rZW5fZW5kcG9pbnRfYXV0aF9tZXRob2RzX3N1cHBvcnRlZDogW1xuICAgICAgICAnY2xpZW50X3NlY3JldF9iYXNpYydcbiAgICAgIF0sXG4gICAgICBjbGFpbXNfc3VwcG9ydGVkOiBbXG4gICAgICAgICdhdWQnLFxuICAgICAgICAnZXhwJyxcbiAgICAgICAgJ2lhdCcsXG4gICAgICAgICdpc3MnLFxuICAgICAgICAnc3ViJ1xuICAgICAgXVxuICAgIH0pXG4gIH0pXG59KVxuXG5mdW5jdGlvbiBiYXNlNjRUb0FycmF5QnVmZmVyIChiNjQ6IHN0cmluZykge1xuICBjb25zdCBieXRlU3RyaW5nID0gYXRvYihiNjQpXG4gIGNvbnN0IGJ5dGVBcnJheSA9IG5ldyBVaW50OEFycmF5KGJ5dGVTdHJpbmcubGVuZ3RoKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVTdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICBieXRlQXJyYXlbaV0gPSBieXRlU3RyaW5nLmNoYXJDb2RlQXQoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};