IamAwsProvider.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var fs = _interopRequireWildcard(require("fs/promises"), true);
  6. var http = _interopRequireWildcard(require("http"), true);
  7. var https = _interopRequireWildcard(require("https"), true);
  8. var _url = require("url");
  9. var _CredentialProvider = require("./CredentialProvider.js");
  10. var _Credentials = require("./Credentials.js");
  11. var _helper = require("./internal/helper.js");
  12. var _request = require("./internal/request.js");
  13. var _response = require("./internal/response.js");
  14. function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
  15. class IamAwsProvider extends _CredentialProvider.CredentialProvider {
  16. accessExpiresAt = '';
  17. constructor({
  18. customEndpoint = undefined,
  19. transportAgent = undefined
  20. }) {
  21. super({
  22. accessKey: '',
  23. secretKey: ''
  24. });
  25. this.customEndpoint = customEndpoint;
  26. this.transportAgent = transportAgent;
  27. /**
  28. * Internal Tracking variables
  29. */
  30. this._credentials = null;
  31. }
  32. async getCredentials() {
  33. if (!this._credentials || this.isAboutToExpire()) {
  34. this._credentials = await this.fetchCredentials();
  35. }
  36. return this._credentials;
  37. }
  38. async fetchCredentials() {
  39. try {
  40. // check for IRSA (https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)
  41. const tokenFile = process.env.AWS_WEB_IDENTITY_TOKEN_FILE;
  42. if (tokenFile) {
  43. return await this.fetchCredentialsUsingTokenFile(tokenFile);
  44. }
  45. // try with IAM role for EC2 instances (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
  46. let tokenHeader = 'Authorization';
  47. let token = process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;
  48. const relativeUri = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
  49. const fullUri = process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI;
  50. let url;
  51. if (relativeUri) {
  52. url = new _url.URL(relativeUri, 'http://169.254.170.2');
  53. } else if (fullUri) {
  54. url = new _url.URL(fullUri);
  55. } else {
  56. token = await this.fetchImdsToken();
  57. tokenHeader = 'X-aws-ec2-metadata-token';
  58. url = await this.getIamRoleNamedUrl(token);
  59. }
  60. return this.requestCredentials(url, tokenHeader, token);
  61. } catch (err) {
  62. throw new Error(`Failed to get Credentials: ${err}`, {
  63. cause: err
  64. });
  65. }
  66. }
  67. async fetchCredentialsUsingTokenFile(tokenFile) {
  68. const token = await fs.readFile(tokenFile, {
  69. encoding: 'utf8'
  70. });
  71. const region = process.env.AWS_REGION;
  72. const stsEndpoint = new _url.URL(region ? `https://sts.${region}.amazonaws.com` : 'https://sts.amazonaws.com');
  73. const hostValue = stsEndpoint.hostname;
  74. const portValue = stsEndpoint.port;
  75. const qryParams = new _url.URLSearchParams({
  76. Action: 'AssumeRoleWithWebIdentity',
  77. Version: '2011-06-15'
  78. });
  79. const roleArn = process.env.AWS_ROLE_ARN;
  80. if (roleArn) {
  81. qryParams.set('RoleArn', roleArn);
  82. const roleSessionName = process.env.AWS_ROLE_SESSION_NAME;
  83. qryParams.set('RoleSessionName', roleSessionName ? roleSessionName : Date.now().toString());
  84. }
  85. qryParams.set('WebIdentityToken', token);
  86. qryParams.sort();
  87. const requestOptions = {
  88. hostname: hostValue,
  89. port: portValue,
  90. path: `${stsEndpoint.pathname}?${qryParams.toString()}`,
  91. protocol: stsEndpoint.protocol,
  92. method: 'POST',
  93. headers: {},
  94. agent: this.transportAgent
  95. };
  96. const transport = stsEndpoint.protocol === 'http:' ? http : https;
  97. const res = await (0, _request.request)(transport, requestOptions, null);
  98. const body = await (0, _response.readAsString)(res);
  99. const assumeRoleResponse = (0, _helper.parseXml)(body);
  100. const creds = assumeRoleResponse.AssumeRoleWithWebIdentityResponse.AssumeRoleWithWebIdentityResult.Credentials;
  101. this.accessExpiresAt = creds.Expiration;
  102. return new _Credentials.Credentials({
  103. accessKey: creds.AccessKeyId,
  104. secretKey: creds.SecretAccessKey,
  105. sessionToken: creds.SessionToken
  106. });
  107. }
  108. async fetchImdsToken() {
  109. const endpoint = this.customEndpoint ? this.customEndpoint : 'http://169.254.169.254';
  110. const url = new _url.URL('/latest/api/token', endpoint);
  111. const requestOptions = {
  112. hostname: url.hostname,
  113. port: url.port,
  114. path: `${url.pathname}${url.search}`,
  115. protocol: url.protocol,
  116. method: 'PUT',
  117. headers: {
  118. 'X-aws-ec2-metadata-token-ttl-seconds': '21600'
  119. },
  120. agent: this.transportAgent
  121. };
  122. const transport = url.protocol === 'http:' ? http : https;
  123. const res = await (0, _request.request)(transport, requestOptions, null);
  124. return await (0, _response.readAsString)(res);
  125. }
  126. async getIamRoleNamedUrl(token) {
  127. const endpoint = this.customEndpoint ? this.customEndpoint : 'http://169.254.169.254';
  128. const url = new _url.URL('latest/meta-data/iam/security-credentials/', endpoint);
  129. const roleName = await this.getIamRoleName(url, token);
  130. return new _url.URL(`${url.pathname}/${encodeURIComponent(roleName)}`, url.origin);
  131. }
  132. async getIamRoleName(url, token) {
  133. const requestOptions = {
  134. hostname: url.hostname,
  135. port: url.port,
  136. path: `${url.pathname}${url.search}`,
  137. protocol: url.protocol,
  138. method: 'GET',
  139. headers: {
  140. 'X-aws-ec2-metadata-token': token
  141. },
  142. agent: this.transportAgent
  143. };
  144. const transport = url.protocol === 'http:' ? http : https;
  145. const res = await (0, _request.request)(transport, requestOptions, null);
  146. const body = await (0, _response.readAsString)(res);
  147. const roleNames = body.split(/\r\n|[\n\r\u2028\u2029]/);
  148. if (roleNames.length === 0) {
  149. throw new Error(`No IAM roles attached to EC2 service ${url}`);
  150. }
  151. return roleNames[0];
  152. }
  153. async requestCredentials(url, tokenHeader, token) {
  154. const headers = {};
  155. if (token) {
  156. headers[tokenHeader] = token;
  157. }
  158. const requestOptions = {
  159. hostname: url.hostname,
  160. port: url.port,
  161. path: `${url.pathname}${url.search}`,
  162. protocol: url.protocol,
  163. method: 'GET',
  164. headers: headers,
  165. agent: this.transportAgent
  166. };
  167. const transport = url.protocol === 'http:' ? http : https;
  168. const res = await (0, _request.request)(transport, requestOptions, null);
  169. const body = await (0, _response.readAsString)(res);
  170. const ecsCredentials = JSON.parse(body);
  171. if (!ecsCredentials.Code || ecsCredentials.Code != 'Success') {
  172. throw new Error(`${url} failed with code ${ecsCredentials.Code} and message ${ecsCredentials.Message}`);
  173. }
  174. this.accessExpiresAt = ecsCredentials.Expiration;
  175. return new _Credentials.Credentials({
  176. accessKey: ecsCredentials.AccessKeyID,
  177. secretKey: ecsCredentials.SecretAccessKey,
  178. sessionToken: ecsCredentials.Token
  179. });
  180. }
  181. isAboutToExpire() {
  182. const expiresAt = new Date(this.accessExpiresAt);
  183. const provisionalExpiry = new Date(Date.now() + 1000 * 10); // 10 seconds leeway
  184. return provisionalExpiry > expiresAt;
  185. }
  186. }
  187. // deprecated default export, please use named exports.
  188. // keep for backward compatibility.
  189. // eslint-disable-next-line import/no-default-export
  190. exports.IamAwsProvider = IamAwsProvider;
  191. var _default = IamAwsProvider;
  192. exports.default = _default;
  193. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmcyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsImh0dHAiLCJodHRwcyIsIl91cmwiLCJfQ3JlZGVudGlhbFByb3ZpZGVyIiwiX0NyZWRlbnRpYWxzIiwiX2hlbHBlciIsIl9yZXF1ZXN0IiwiX3Jlc3BvbnNlIiwiZSIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJfX2VzTW9kdWxlIiwibyIsImkiLCJmIiwiX19wcm90b19fIiwiZGVmYXVsdCIsImhhcyIsImdldCIsInNldCIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiSWFtQXdzUHJvdmlkZXIiLCJDcmVkZW50aWFsUHJvdmlkZXIiLCJhY2Nlc3NFeHBpcmVzQXQiLCJjb25zdHJ1Y3RvciIsImN1c3RvbUVuZHBvaW50IiwidW5kZWZpbmVkIiwidHJhbnNwb3J0QWdlbnQiLCJhY2Nlc3NLZXkiLCJzZWNyZXRLZXkiLCJfY3JlZGVudGlhbHMiLCJnZXRDcmVkZW50aWFscyIsImlzQWJvdXRUb0V4cGlyZSIsImZldGNoQ3JlZGVudGlhbHMiLCJ0b2tlbkZpbGUiLCJwcm9jZXNzIiwiZW52IiwiQVdTX1dFQl9JREVOVElUWV9UT0tFTl9GSUxFIiwiZmV0Y2hDcmVkZW50aWFsc1VzaW5nVG9rZW5GaWxlIiwidG9rZW5IZWFkZXIiLCJ0b2tlbiIsIkFXU19DT05UQUlORVJfQVVUSE9SSVpBVElPTl9UT0tFTiIsInJlbGF0aXZlVXJpIiwiQVdTX0NPTlRBSU5FUl9DUkVERU5USUFMU19SRUxBVElWRV9VUkkiLCJmdWxsVXJpIiwiQVdTX0NPTlRBSU5FUl9DUkVERU5USUFMU19GVUxMX1VSSSIsInVybCIsIlVSTCIsImZldGNoSW1kc1Rva2VuIiwiZ2V0SWFtUm9sZU5hbWVkVXJsIiwicmVxdWVzdENyZWRlbnRpYWxzIiwiZXJyIiwiRXJyb3IiLCJjYXVzZSIsInJlYWRGaWxlIiwiZW5jb2RpbmciLCJyZWdpb24iLCJBV1NfUkVHSU9OIiwic3RzRW5kcG9pbnQiLCJob3N0VmFsdWUiLCJob3N0bmFtZSIsInBvcnRWYWx1ZSIsInBvcnQiLCJxcnlQYXJhbXMiLCJVUkxTZWFyY2hQYXJhbXMiLCJBY3Rpb24iLCJWZXJzaW9uIiwicm9sZUFybiIsIkFXU19ST0xFX0FSTiIsInJvbGVTZXNzaW9uTmFtZSIsIkFXU19ST0xFX1NFU1NJT05fTkFNRSIsIkRhdGUiLCJub3ciLCJ0b1N0cmluZyIsInNvcnQiLCJyZXF1ZXN0T3B0aW9ucyIsInBhdGgiLCJwYXRobmFtZSIsInByb3RvY29sIiwibWV0aG9kIiwiaGVhZGVycyIsImFnZW50IiwidHJhbnNwb3J0IiwicmVzIiwicmVxdWVzdCIsImJvZHkiLCJyZWFkQXNTdHJpbmciLCJhc3N1bWVSb2xlUmVzcG9uc2UiLCJwYXJzZVhtbCIsImNyZWRzIiwiQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3BvbnNlIiwiQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3VsdCIsIkNyZWRlbnRpYWxzIiwiRXhwaXJhdGlvbiIsIkFjY2Vzc0tleUlkIiwiU2VjcmV0QWNjZXNzS2V5Iiwic2Vzc2lvblRva2VuIiwiU2Vzc2lvblRva2VuIiwiZW5kcG9pbnQiLCJzZWFyY2giLCJyb2xlTmFtZSIsImdldElhbVJvbGVOYW1lIiwiZW5jb2RlVVJJQ29tcG9uZW50Iiwib3JpZ2luIiwicm9sZU5hbWVzIiwic3BsaXQiLCJsZW5ndGgiLCJlY3NDcmVkZW50aWFscyIsIkpTT04iLCJwYXJzZSIsIkNvZGUiLCJNZXNzYWdlIiwiQWNjZXNzS2V5SUQiLCJUb2tlbiIsImV4cGlyZXNBdCIsInByb3Zpc2lvbmFsRXhwaXJ5IiwiZXhwb3J0cyIsIl9kZWZhdWx0Il0sInNvdXJjZXMiOlsiSWFtQXdzUHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCAqIGFzIGh0dHAgZnJvbSAnbm9kZTpodHRwJ1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnbm9kZTpodHRwcydcbmltcG9ydCB7IFVSTCwgVVJMU2VhcmNoUGFyYW1zIH0gZnJvbSAnbm9kZTp1cmwnXG5cbmltcG9ydCB7IENyZWRlbnRpYWxQcm92aWRlciB9IGZyb20gJy4vQ3JlZGVudGlhbFByb3ZpZGVyLnRzJ1xuaW1wb3J0IHsgQ3JlZGVudGlhbHMgfSBmcm9tICcuL0NyZWRlbnRpYWxzLnRzJ1xuaW1wb3J0IHsgcGFyc2VYbWwgfSBmcm9tICcuL2ludGVybmFsL2hlbHBlci50cydcbmltcG9ydCB7IHJlcXVlc3QgfSBmcm9tICcuL2ludGVybmFsL3JlcXVlc3QudHMnXG5pbXBvcnQgeyByZWFkQXNTdHJpbmcgfSBmcm9tICcuL2ludGVybmFsL3Jlc3BvbnNlLnRzJ1xuXG5pbnRlcmZhY2UgQXNzdW1lUm9sZVJlc3BvbnNlIHtcbiAgQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3BvbnNlOiB7XG4gICAgQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3VsdDoge1xuICAgICAgQ3JlZGVudGlhbHM6IHtcbiAgICAgICAgQWNjZXNzS2V5SWQ6IHN0cmluZ1xuICAgICAgICBTZWNyZXRBY2Nlc3NLZXk6IHN0cmluZ1xuICAgICAgICBTZXNzaW9uVG9rZW46IHN0cmluZ1xuICAgICAgICBFeHBpcmF0aW9uOiBzdHJpbmdcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuaW50ZXJmYWNlIEVjc0NyZWRlbnRpYWxzIHtcbiAgQWNjZXNzS2V5SUQ6IHN0cmluZ1xuICBTZWNyZXRBY2Nlc3NLZXk6IHN0cmluZ1xuICBUb2tlbjogc3RyaW5nXG4gIEV4cGlyYXRpb246IHN0cmluZ1xuICBDb2RlOiBzdHJpbmdcbiAgTWVzc2FnZTogc3RyaW5nXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSWFtQXdzUHJvdmlkZXJPcHRpb25zIHtcbiAgY3VzdG9tRW5kcG9pbnQ/OiBzdHJpbmdcbiAgdHJhbnNwb3J0QWdlbnQ/OiBodHRwLkFnZW50XG59XG5cbmV4cG9ydCBjbGFzcyBJYW1Bd3NQcm92aWRlciBleHRlbmRzIENyZWRlbnRpYWxQcm92aWRlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY3VzdG9tRW5kcG9pbnQ/OiBzdHJpbmdcblxuICBwcml2YXRlIF9jcmVkZW50aWFsczogQ3JlZGVudGlhbHMgfCBudWxsXG4gIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNwb3J0QWdlbnQ/OiBodHRwLkFnZW50XG4gIHByaXZhdGUgYWNjZXNzRXhwaXJlc0F0ID0gJydcblxuICBjb25zdHJ1Y3Rvcih7IGN1c3RvbUVuZHBvaW50ID0gdW5kZWZpbmVkLCB0cmFuc3BvcnRBZ2VudCA9IHVuZGVmaW5lZCB9OiBJYW1Bd3NQcm92aWRlck9wdGlvbnMpIHtcbiAgICBzdXBlcih7IGFjY2Vzc0tleTogJycsIHNlY3JldEtleTogJycgfSlcblxuICAgIHRoaXMuY3VzdG9tRW5kcG9pbnQgPSBjdXN0b21FbmRwb2ludFxuICAgIHRoaXMudHJhbnNwb3J0QWdlbnQgPSB0cmFuc3BvcnRBZ2VudFxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWwgVHJhY2tpbmcgdmFyaWFibGVzXG4gICAgICovXG4gICAgdGhpcy5fY3JlZGVudGlhbHMgPSBudWxsXG4gIH1cblxuICBhc3luYyBnZXRDcmVkZW50aWFscygpOiBQcm9taXNlPENyZWRlbnRpYWxzPiB7XG4gICAgaWYgKCF0aGlzLl9jcmVkZW50aWFscyB8fCB0aGlzLmlzQWJvdXRUb0V4cGlyZSgpKSB7XG4gICAgICB0aGlzLl9jcmVkZW50aWFscyA9IGF3YWl0IHRoaXMuZmV0Y2hDcmVkZW50aWFscygpXG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jcmVkZW50aWFsc1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaENyZWRlbnRpYWxzKCk6IFByb21pc2U8Q3JlZGVudGlhbHM+IHtcbiAgICB0cnkge1xuICAgICAgLy8gY2hlY2sgZm9yIElSU0EgKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9la3MvbGF0ZXN0L3VzZXJndWlkZS9pYW0tcm9sZXMtZm9yLXNlcnZpY2UtYWNjb3VudHMuaHRtbClcbiAgICAgIGNvbnN0IHRva2VuRmlsZSA9IHByb2Nlc3MuZW52LkFXU19XRUJfSURFTlRJVFlfVE9LRU5fRklMRVxuICAgICAgaWYgKHRva2VuRmlsZSkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5mZXRjaENyZWRlbnRpYWxzVXNpbmdUb2tlbkZpbGUodG9rZW5GaWxlKVxuICAgICAgfVxuXG4gICAgICAvLyB0cnkgd2l0aCBJQU0gcm9sZSBmb3IgRUMyIGluc3RhbmNlcyAoaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0VDMi9sYXRlc3QvVXNlckd1aWRlL2lhbS1yb2xlcy1mb3ItYW1hem9uLWVjMi5odG1sKVxuICAgICAgbGV0IHRva2VuSGVhZGVyID0gJ0F1dGhvcml6YXRpb24nXG4gICAgICBsZXQgdG9rZW4gPSBwcm9jZXNzLmVudi5BV1NfQ09OVEFJTkVSX0FVVEhPUklaQVRJT05fVE9LRU5cbiAgICAgIGNvbnN0IHJlbGF0aXZlVXJpID0gcHJvY2Vzcy5lbnYuQVdTX0NPTlRBSU5FUl9DUkVERU5USUFMU19SRUxBVElWRV9VUklcbiAgICAgIGNvbnN0IGZ1bGxVcmkgPSBwcm9jZXNzLmVudi5BV1NfQ09OVEFJTkVSX0NSRURFTlRJQUxTX0ZVTExfVVJJXG4gICAgICBsZXQgdXJsOiBVUkxcbiAgICAgIGlmIChyZWxhdGl2ZVVyaSkge1xuICAgICAgICB1cmwgPSBuZXcgVVJMKHJlbGF0aXZlVXJpLCAnaHR0cDovLzE2OS4yNTQuMTcwLjInKVxuICAgICAgfSBlbHNlIGlmIChmdWxsVXJpKSB7XG4gICAgICAgIHVybCA9IG5ldyBVUkwoZnVsbFVyaSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRva2VuID0gYXdhaXQgdGhpcy5mZXRjaEltZHNUb2tlbigpXG4gICAgICAgIHRva2VuSGVhZGVyID0gJ1gtYXdzLWVjMi1tZXRhZGF0YS10b2tlbidcbiAgICAgICAgdXJsID0gYXdhaXQgdGhpcy5nZXRJYW1Sb2xlTmFtZWRVcmwodG9rZW4pXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLnJlcXVlc3RDcmVkZW50aWFscyh1cmwsIHRva2VuSGVhZGVyLCB0b2tlbilcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBDcmVkZW50aWFsczogJHtlcnJ9YCwgeyBjYXVzZTogZXJyIH0pXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaENyZWRlbnRpYWxzVXNpbmdUb2tlbkZpbGUodG9rZW5GaWxlOiBzdHJpbmcpOiBQcm9taXNlPENyZWRlbnRpYWxzPiB7XG4gICAgY29uc3QgdG9rZW4gPSBhd2FpdCBmcy5yZWFkRmlsZSh0b2tlbkZpbGUsIHsgZW5jb2Rpbmc6ICd1dGY4JyB9KVxuICAgIGNvbnN0IHJlZ2lvbiA9IHByb2Nlc3MuZW52LkFXU19SRUdJT05cbiAgICBjb25zdCBzdHNFbmRwb2ludCA9IG5ldyBVUkwocmVnaW9uID8gYGh0dHBzOi8vc3RzLiR7cmVnaW9ufS5hbWF6b25hd3MuY29tYCA6ICdodHRwczovL3N0cy5hbWF6b25hd3MuY29tJylcblxuICAgIGNvbnN0IGhvc3RWYWx1ZSA9IHN0c0VuZHBvaW50Lmhvc3RuYW1lXG4gICAgY29uc3QgcG9ydFZhbHVlID0gc3RzRW5kcG9pbnQucG9ydFxuICAgIGNvbnN0IHFyeVBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgQWN0aW9uOiAnQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eScsXG4gICAgICBWZXJzaW9uOiAnMjAxMS0wNi0xNScsXG4gICAgfSlcblxuICAgIGNvbnN0IHJvbGVBcm4gPSBwcm9jZXNzLmVudi5BV1NfUk9MRV9BUk5cbiAgICBpZiAocm9sZUFybikge1xuICAgICAgcXJ5UGFyYW1zLnNldCgnUm9sZUFybicsIHJvbGVBcm4pXG4gICAgICBjb25zdCByb2xlU2Vzc2lvbk5hbWUgPSBwcm9jZXNzLmVudi5BV1NfUk9MRV9TRVNTSU9OX05BTUVcbiAgICAgIHFyeVBhcmFtcy5zZXQoJ1JvbGVTZXNzaW9uTmFtZScsIHJvbGVTZXNzaW9uTmFtZSA/IHJvbGVTZXNzaW9uTmFtZSA6IERhdGUubm93KCkudG9TdHJpbmcoKSlcbiAgICB9XG5cbiAgICBxcnlQYXJhbXMuc2V0KCdXZWJJZGVudGl0eVRva2VuJywgdG9rZW4pXG4gICAgcXJ5UGFyYW1zLnNvcnQoKVxuXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICBob3N0bmFtZTogaG9zdFZhbHVlLFxuICAgICAgcG9ydDogcG9ydFZhbHVlLFxuICAgICAgcGF0aDogYCR7c3RzRW5kcG9pbnQucGF0aG5hbWV9PyR7cXJ5UGFyYW1zLnRvU3RyaW5nKCl9YCxcbiAgICAgIHByb3RvY29sOiBzdHNFbmRwb2ludC5wcm90b2NvbCxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge30sXG4gICAgICBhZ2VudDogdGhpcy50cmFuc3BvcnRBZ2VudCxcbiAgICB9IHNhdGlzZmllcyBodHRwLlJlcXVlc3RPcHRpb25zXG5cbiAgICBjb25zdCB0cmFuc3BvcnQgPSBzdHNFbmRwb2ludC5wcm90b2NvbCA9PT0gJ2h0dHA6JyA/IGh0dHAgOiBodHRwc1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHJlcXVlc3QodHJhbnNwb3J0LCByZXF1ZXN0T3B0aW9ucywgbnVsbClcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcblxuICAgIGNvbnN0IGFzc3VtZVJvbGVSZXNwb25zZTogQXNzdW1lUm9sZVJlc3BvbnNlID0gcGFyc2VYbWwoYm9keSlcbiAgICBjb25zdCBjcmVkcyA9IGFzc3VtZVJvbGVSZXNwb25zZS5Bc3N1bWVSb2xlV2l0aFdlYklkZW50aXR5UmVzcG9uc2UuQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3VsdC5DcmVkZW50aWFsc1xuICAgIHRoaXMuYWNjZXNzRXhwaXJlc0F0ID0gY3JlZHMuRXhwaXJhdGlvblxuICAgIHJldHVybiBuZXcgQ3JlZGVudGlhbHMoe1xuICAgICAgYWNjZXNzS2V5OiBjcmVkcy5BY2Nlc3NLZXlJZCxcbiAgICAgIHNlY3JldEtleTogY3JlZHMuU2VjcmV0QWNjZXNzS2V5LFxuICAgICAgc2Vzc2lvblRva2VuOiBjcmVkcy5TZXNzaW9uVG9rZW4sXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hJbWRzVG9rZW4oKSB7XG4gICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLmN1c3RvbUVuZHBvaW50ID8gdGhpcy5jdXN0b21FbmRwb2ludCA6ICdodHRwOi8vMTY5LjI1NC4xNjkuMjU0J1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoJy9sYXRlc3QvYXBpL3Rva2VuJywgZW5kcG9pbnQpXG5cbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICBwb3J0OiB1cmwucG9ydCxcbiAgICAgIHBhdGg6IGAke3VybC5wYXRobmFtZX0ke3VybC5zZWFyY2h9YCxcbiAgICAgIHByb3RvY29sOiB1cmwucHJvdG9jb2wsXG4gICAgICBtZXRob2Q6ICdQVVQnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnWC1hd3MtZWMyLW1ldGFkYXRhLXRva2VuLXR0bC1zZWNvbmRzJzogJzIxNjAwJyxcbiAgICAgIH0sXG4gICAgICBhZ2VudDogdGhpcy50cmFuc3BvcnRBZ2VudCxcbiAgICB9IHNhdGlzZmllcyBodHRwLlJlcXVlc3RPcHRpb25zXG5cbiAgICBjb25zdCB0cmFuc3BvcnQgPSB1cmwucHJvdG9jb2wgPT09ICdodHRwOicgPyBodHRwIDogaHR0cHNcbiAgICBjb25zdCByZXMgPSBhd2FpdCByZXF1ZXN0KHRyYW5zcG9ydCwgcmVxdWVzdE9wdGlvbnMsIG51bGwpXG4gICAgcmV0dXJuIGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldElhbVJvbGVOYW1lZFVybCh0b2tlbjogc3RyaW5nKSB7XG4gICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLmN1c3RvbUVuZHBvaW50ID8gdGhpcy5jdXN0b21FbmRwb2ludCA6ICdodHRwOi8vMTY5LjI1NC4xNjkuMjU0J1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoJ2xhdGVzdC9tZXRhLWRhdGEvaWFtL3NlY3VyaXR5LWNyZWRlbnRpYWxzLycsIGVuZHBvaW50KVxuXG4gICAgY29uc3Qgcm9sZU5hbWUgPSBhd2FpdCB0aGlzLmdldElhbVJvbGVOYW1lKHVybCwgdG9rZW4pXG4gICAgcmV0dXJuIG5ldyBVUkwoYCR7dXJsLnBhdGhuYW1lfS8ke2VuY29kZVVSSUNvbXBvbmVudChyb2xlTmFtZSl9YCwgdXJsLm9yaWdpbilcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0SWFtUm9sZU5hbWUodXJsOiBVUkwsIHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgaG9zdG5hbWU6IHVybC5ob3N0bmFtZSxcbiAgICAgIHBvcnQ6IHVybC5wb3J0LFxuICAgICAgcGF0aDogYCR7dXJsLnBhdGhuYW1lfSR7dXJsLnNlYXJjaH1gLFxuICAgICAgcHJvdG9jb2w6IHVybC5wcm90b2NvbCxcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdYLWF3cy1lYzItbWV0YWRhdGEtdG9rZW4nOiB0b2tlbixcbiAgICAgIH0sXG4gICAgICBhZ2VudDogdGhpcy50cmFuc3BvcnRBZ2VudCxcbiAgICB9IHNhdGlzZmllcyBodHRwLlJlcXVlc3RPcHRpb25zXG5cbiAgICBjb25zdCB0cmFuc3BvcnQgPSB1cmwucHJvdG9jb2wgPT09ICdodHRwOicgPyBodHRwIDogaHR0cHNcbiAgICBjb25zdCByZXMgPSBhd2FpdCByZXF1ZXN0KHRyYW5zcG9ydCwgcmVxdWVzdE9wdGlvbnMsIG51bGwpXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgY29uc3Qgcm9sZU5hbWVzID0gYm9keS5zcGxpdCgvXFxyXFxufFtcXG5cXHJcXHUyMDI4XFx1MjAyOV0vKVxuICAgIGlmIChyb2xlTmFtZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIElBTSByb2xlcyBhdHRhY2hlZCB0byBFQzIgc2VydmljZSAke3VybH1gKVxuICAgIH1cbiAgICByZXR1cm4gcm9sZU5hbWVzWzBdIGFzIHN0cmluZ1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXF1ZXN0Q3JlZGVudGlhbHModXJsOiBVUkwsIHRva2VuSGVhZGVyOiBzdHJpbmcsIHRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPENyZWRlbnRpYWxzPiB7XG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICBoZWFkZXJzW3Rva2VuSGVhZGVyXSA9IHRva2VuXG4gICAgfVxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgaG9zdG5hbWU6IHVybC5ob3N0bmFtZSxcbiAgICAgIHBvcnQ6IHVybC5wb3J0LFxuICAgICAgcGF0aDogYCR7dXJsLnBhdGhuYW1lfSR7dXJsLnNlYXJjaH1gLFxuICAgICAgcHJvdG9jb2w6IHVybC5wcm90b2NvbCxcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiBoZWFkZXJzLFxuICAgICAgYWdlbnQ6IHRoaXMudHJhbnNwb3J0QWdlbnQsXG4gICAgfSBzYXRpc2ZpZXMgaHR0cC5SZXF1ZXN0T3B0aW9uc1xuXG4gICAgY29uc3QgdHJhbnNwb3J0ID0gdXJsLnByb3RvY29sID09PSAnaHR0cDonID8gaHR0cCA6IGh0dHBzXG4gICAgY29uc3QgcmVzID0gYXdhaXQgcmVxdWVzdCh0cmFuc3BvcnQsIHJlcXVlc3RPcHRpb25zLCBudWxsKVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIGNvbnN0IGVjc0NyZWRlbnRpYWxzID0gSlNPTi5wYXJzZShib2R5KSBhcyBFY3NDcmVkZW50aWFsc1xuICAgIGlmICghZWNzQ3JlZGVudGlhbHMuQ29kZSB8fCBlY3NDcmVkZW50aWFscy5Db2RlICE9ICdTdWNjZXNzJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3VybH0gZmFpbGVkIHdpdGggY29kZSAke2Vjc0NyZWRlbnRpYWxzLkNvZGV9IGFuZCBtZXNzYWdlICR7ZWNzQ3JlZGVudGlhbHMuTWVzc2FnZX1gKVxuICAgIH1cblxuICAgIHRoaXMuYWNjZXNzRXhwaXJlc0F0ID0gZWNzQ3JlZGVudGlhbHMuRXhwaXJhdGlvblxuICAgIHJldHVybiBuZXcgQ3JlZGVudGlhbHMoe1xuICAgICAgYWNjZXNzS2V5OiBlY3NDcmVkZW50aWFscy5BY2Nlc3NLZXlJRCxcbiAgICAgIHNlY3JldEtleTogZWNzQ3JlZGVudGlhbHMuU2VjcmV0QWNjZXNzS2V5LFxuICAgICAgc2Vzc2lvblRva2VuOiBlY3NDcmVkZW50aWFscy5Ub2tlbixcbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSBpc0Fib3V0VG9FeHBpcmUoKSB7XG4gICAgY29uc3QgZXhwaXJlc0F0ID0gbmV3IERhdGUodGhpcy5hY2Nlc3NFeHBpcmVzQXQpXG4gICAgY29uc3QgcHJvdmlzaW9uYWxFeHBpcnkgPSBuZXcgRGF0ZShEYXRlLm5vdygpICsgMTAwMCAqIDEwKSAvLyAxMCBzZWNvbmRzIGxlZXdheVxuICAgIHJldHVybiBwcm92aXNpb25hbEV4cGlyeSA+IGV4cGlyZXNBdFxuICB9XG59XG5cbi8vIGRlcHJlY2F0ZWQgZGVmYXVsdCBleHBvcnQsIHBsZWFzZSB1c2UgbmFtZWQgZXhwb3J0cy5cbi8vIGtlZXAgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWRlZmF1bHQtZXhwb3J0XG5leHBvcnQgZGVmYXVsdCBJYW1Bd3NQcm92aWRlclxu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