UNPKG

@pepperize/cdk-organizations

Version:

Manage AWS organizations, organizational units (OU), accounts and service control policies (SCP).

144 lines • 20.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = handler; const AWS = require("aws-sdk"); let organizationsClient; const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1"; /** * The isComplete handler is repeatedly invoked checking CreateAccountStatus until SUCCEEDED or FAILED. * @see https://docs.aws.amazon.com/cdk/api/v1/docs/custom-resources-readme.html#asynchronous-providers-iscomplete */ async function handler(event) { console.log(`Request of type ${event.RequestType} received`); if (!organizationsClient) { organizationsClient = new AWS.Organizations({ region: organizationsRegion }); } console.log("Payload: %j", event); let accountId; if (event.RequestType == "Create" || isLegacyPhysicalResourceId(event)) { const response = await organizationsClient // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeCreateAccountStatus-property .describeCreateAccountStatus({ CreateAccountRequestId: isLegacyPhysicalResourceId(event) ? event.PhysicalResourceId : event.Data?.CreateAccountStatusId, }) .promise(); if (response.CreateAccountStatus?.State == "IN_PROGRESS") { // @ts-ignore return { IsComplete: false, Data: {} }; } if (response.CreateAccountStatus?.State == "FAILED" && response.CreateAccountStatus?.FailureReason != "EMAIL_ALREADY_EXISTS") { throw new Error(`Failed ${event.RequestType} Account ${response.CreateAccountStatus?.AccountName}, reason: ${response.CreateAccountStatus?.FailureReason}`); } if (response.CreateAccountStatus?.FailureReason == "EMAIL_ALREADY_EXISTS" && event.ResourceProperties.ImportOnDuplicate) { const account = await findAccountByEmail(organizationsClient, event.ResourceProperties.Email); if (!account) { throw new Error(`Failed ${event.RequestType} Account ${response.CreateAccountStatus?.AccountName}, reason: ${response.CreateAccountStatus?.FailureReason}; could not find account in organization.`); } accountId = account.Id; } else if (response.CreateAccountStatus?.FailureReason == "EMAIL_ALREADY_EXISTS" && !event.ResourceProperties.ImportOnDuplicate) { throw new Error(`Failed ${event.RequestType} Account ${response.CreateAccountStatus?.AccountName}, reason: ${response.CreateAccountStatus?.FailureReason}.`); } else { // State == SUCCEEDED accountId = response.CreateAccountStatus?.AccountId; } } else { accountId = event.PhysicalResourceId; } const response = await organizationsClient // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeAccount-property .describeAccount({ AccountId: accountId }) .promise(); // On delete, update or create move account to destination parent await move(organizationsClient, accountId, event.ResourceProperties?.ParentId); // On delete close account if (event.RequestType == "Delete" && event.ResourceProperties?.RemovalPolicy == "destroy") { await close(organizationsClient, accountId); } return { IsComplete: true, // @ts-ignore PhysicalResourceId: accountId, Data: { ...event.ResourceProperties, ...event.Data, AccountId: accountId, AccountArn: response.Account?.Arn, AccountName: response.Account?.Name, Email: response.Account?.Email, }, }; } const findCurrentParent = async (client, id) => { const response = await client // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listParents-property .listParents({ ChildId: id, }) .promise(); if (response.Parents?.length) { return response.Parents[0]; } throw new Error(`Could not find parent for id '${id}'`); }; const move = async (client, accountId, destinationParentId) => { if (!destinationParentId) { return; } const currentParent = await findCurrentParent(organizationsClient, accountId); if (destinationParentId == currentParent.Id) { return; } await client // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#moveAccount-property .moveAccount({ AccountId: accountId, SourceParentId: currentParent.Id, DestinationParentId: destinationParentId, }) .promise(); }; /** * Before aws-cdk-lib 2.15.0 the physical resource was determined in the onEventHandler and therefor the physical resource id was the account's CreateAccountStatusId. */ const isLegacyPhysicalResourceId = (event) => { return /car-[a-z0-9]{8,32}/.test(event.PhysicalResourceId); }; const findAccountByEmail = async (client, email) => { let response = await client // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listAccounts-property .listAccounts() .promise(); for (const account of response.Accounts ?? []) { if (account.Email == email) { return account; } } while (response.NextToken) { response = await client // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listAccounts-property .listAccounts({ NextToken: response.NextToken }) .promise(); for (const account of response.Accounts ?? []) { if (account.Email == email) { return account; } } } return undefined; }; const close = async (client, accountId) => { await client // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#closeAccount-property .closeAccount({ AccountId: accountId, }); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXMtY29tcGxldGUtaGFuZGxlci5sYW1iZGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWNjb3VudC1wcm92aWRlci9pcy1jb21wbGV0ZS1oYW5kbGVyLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWNBLDBCQXdGQztBQWxHRCwrQkFBK0I7QUFHL0IsSUFBSSxtQkFBc0MsQ0FBQztBQUMzQyxNQUFNLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsNkJBQTZCLElBQUksV0FBVyxDQUFDO0FBRXJGOzs7R0FHRztBQUNJLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBd0I7SUFDcEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLFdBQVcsV0FBVyxDQUFDLENBQUM7SUFFN0QsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDekIsbUJBQW1CLEdBQUcsSUFBSSxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsTUFBTSxFQUFFLG1CQUFtQixFQUFFLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFbEMsSUFBSSxTQUFpQixDQUFDO0lBQ3RCLElBQUksS0FBSyxDQUFDLFdBQVcsSUFBSSxRQUFRLElBQUksMEJBQTBCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN2RSxNQUFNLFFBQVEsR0FBMEQsTUFBTSxtQkFBbUI7WUFDL0Ysa0hBQWtIO2FBQ2pILDJCQUEyQixDQUFDO1lBQzNCLHNCQUFzQixFQUFFLDBCQUEwQixDQUFDLEtBQUssQ0FBQztnQkFDdkQsQ0FBQyxDQUFDLEtBQUssQ0FBQyxrQkFBbUI7Z0JBQzNCLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLHFCQUFxQjtTQUN0QyxDQUFDO2FBQ0QsT0FBTyxFQUFFLENBQUM7UUFFYixJQUFJLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxL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LEdBQUcsS0FBSyxFQUFFLE1BQXFCLEVBQUUsS0FBYSxFQUE4QyxFQUFFO0lBQ3BILElBQUksUUFBUSxHQUF1QyxNQUFNLE1BQU07UUFDN0QsbUdBQW1HO1NBQ2xHLFlBQVksRUFBRTtTQUNkLE9BQU8sRUFBRSxDQUFDO0lBQ2IsS0FBSyxNQUFNLE9BQU8sSUFBSSxRQUFRLENBQUMsUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQzlDLElBQUksT0FBTyxDQUFDLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMzQixPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzFCLFFBQVEsR0FBRyxNQUFNLE1BQU07WUFDckIsbUdBQW1HO2FBQ2xHLFlBQVksQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7YUFDL0MsT0FBTyxFQUFFLENBQUM7UUFDYixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLENBQUM7WUFDOUMsSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUMzQixPQUFPLE9BQU8sQ0FBQztZQUNqQixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDLENBQUM7QUFFRixNQUFNLEtBQUssR0FBRyxLQUFLLEVBQUUsTUFBcUIsRUFBRSxTQUFpQixFQUFpQixFQUFFO0lBQzlFLE1BQU0sTUFBTTtRQUNWLG1HQUFtRztTQUNsRyxZQUFZLENBQUM7UUFDWixTQUFTLEVBQUUsU0FBUztLQUNyQixDQUFDLENBQUM7QUFDUCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDZGtDdXN0b21SZXNvdXJjZUlzQ29tcGxldGVFdmVudCBhcyBJc0NvbXBsZXRlUmVxdWVzdCxcbiAgQ2RrQ3VzdG9tUmVzb3VyY2VJc0NvbXBsZXRlUmVzcG9uc2UgYXMgSXNDb21wbGV0ZVJlc3BvbnNlLFxufSBmcm9tIFwiYXdzLWxhbWJkYVwiO1xuaW1wb3J0ICogYXMgQVdTIGZyb20gXCJhd3Mtc2RrXCI7XG5pbXBvcnQgeyBPcmdhbml6YXRpb25zIH0gZnJvbSBcImF3cy1zZGtcIjtcblxubGV0IG9yZ2FuaXphdGlvbnNDbGllbnQ6IEFXUy5Pcmdhbml6YXRpb25zO1xuY29uc3Qgb3JnYW5pemF0aW9uc1JlZ2lvbiA9IHByb2Nlc3MuZW52Lk9SR0FOSVpBVElPTlNfRU5EUE9JTlRfUkVHSU9OID8/IFwidXMtZWFzdC0xXCI7XG5cbi8qKlxuICogVGhlIGlzQ29tcGxldGUgaGFuZGxlciBpcyByZXBlYXRlZGx5IGludm9rZWQgY2hlY2tpbmcgQ3JlYXRlQWNjb3VudFN0YXR1cyB1bnRpbCBTVUNDRUVERUQgb3IgRkFJTEVELlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL2FwaS92MS9kb2NzL2N1c3RvbS1yZXNvdXJjZXMtcmVhZG1lLmh0bWwjYXN5bmNocm9ub3VzLXByb3ZpZGVycy1pc2NvbXBsZXRlXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBJc0NvbXBsZXRlUmVxdWVzdCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gIGNvbnNvbGUubG9nKGBSZXF1ZXN0IG9mIHR5cGUgJHtldmVudC5SZXF1ZXN0VHlwZX0gcmVjZWl2ZWRgKTtcblxuICBpZiAoIW9yZ2FuaXphdGlvbnNDbGllbnQpIHtcbiAgICBvcmdhbml6YXRpb25zQ2xpZW50ID0gbmV3IEFXUy5Pcmdhbml6YXRpb25zKHsgcmVnaW9uOiBvcmdhbml6YXRpb25zUmVnaW9uIH0pO1xuICB9XG5cbiAgY29uc29sZS5sb2coXCJQYXlsb2FkOiAlalwiLCBldmVudCk7XG5cbiAgbGV0IGFjY291bnRJZDogc3RyaW5nO1xuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT0gXCJDcmVhdGVcIiB8fCBpc0xlZ2FjeVBoeXNpY2FsUmVzb3VyY2VJZChldmVudCkpIHtcbiAgICBjb25zdCByZXNwb25zZTogQVdTLk9yZ2FuaXphdGlvbnMuRGVzY3JpYmVDcmVhdGVBY2NvdW50U3RhdHVzUmVzcG9uc2UgPSBhd2FpdCBvcmdhbml6YXRpb25zQ2xpZW50XG4gICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL09yZ2FuaXphdGlvbnMuaHRtbCNkZXNjcmliZUNyZWF0ZUFjY291bnRTdGF0dXMtcHJvcGVydHlcbiAgICAgIC5kZXNjcmliZUNyZWF0ZUFjY291bnRTdGF0dXMoe1xuICAgICAgICBDcmVhdGVBY2NvdW50UmVxdWVzdElkOiBpc0xlZ2FjeVBoeXNpY2FsUmVzb3VyY2VJZChldmVudClcbiAgICAgICAgICA/IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCFcbiAgICAgICAgICA6IGV2ZW50LkRhdGE/LkNyZWF0ZUFjY291bnRTdGF0dXNJZCxcbiAgICAgIH0pXG4gICAgICAucHJvbWlzZSgpO1xuXG4gICAgaWYgKHJlc3BvbnNlLkNyZWF0ZUFjY291bnRTdGF0dXM/LlN0YXRlID09IFwiSU5fUFJPR1JFU1NcIikge1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgcmV0dXJuIHsgSXNDb21wbGV0ZTogZmFsc2UsIERhdGE6IHt9IH07XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uU3RhdGUgPT0gXCJGQUlMRURcIiAmJlxuICAgICAgcmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uRmFpbHVyZVJlYXNvbiAhPSBcIkVNQUlMX0FMUkVBRFlfRVhJU1RTXCJcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCAke2V2ZW50LlJlcXVlc3RUeXBlfSBBY2NvdW50ICR7cmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uQWNjb3VudE5hbWV9LCByZWFzb246ICR7cmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uRmFpbHVyZVJlYXNvbn1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHJlc3BvbnNlLkNyZWF0ZUFjY291bnRTdGF0dXM/LkZhaWx1cmVSZWFzb24gPT0gXCJFTUFJTF9BTFJFQURZX0VYSVNUU1wiICYmXG4gICAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuSW1wb3J0T25EdXBsaWNhdGVcbiAgICApIHtcbiAgICAgIGNvbnN0IGFjY291bnQgPSBhd2FpdCBmaW5kQWNjb3VudEJ5RW1haWwob3JnYW5pemF0aW9uc0NsaWVudCwgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkVtYWlsKTtcblxuICAgICAgaWYgKCFhY2NvdW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRmFpbGVkICR7ZXZlbnQuUmVxdWVzdFR5cGV9IEFjY291bnQgJHtyZXNwb25zZS5DcmVhdGVBY2NvdW50U3RhdHVzPy5BY2NvdW50TmFtZX0sIHJlYXNvbjogJHtyZXNwb25zZS5DcmVhdGVBY2NvdW50U3RhdHVzPy5GYWlsdXJlUmVhc29ufTsgY291bGQgbm90IGZpbmQgYWNjb3VudCBpbiBvcmdhbml6YXRpb24uYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBhY2NvdW50SWQgPSBhY2NvdW50LklkITtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgcmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uRmFpbHVyZVJlYXNvbiA9PSBcIkVNQUlMX0FMUkVBRFlfRVhJU1RTXCIgJiZcbiAgICAgICFldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuSW1wb3J0T25EdXBsaWNhdGVcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCAke2V2ZW50LlJlcXVlc3RUeXBlfSBBY2NvdW50ICR7cmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uQWNjb3VudE5hbWV9LCByZWFzb246ICR7cmVzcG9uc2UuQ3JlYXRlQWNjb3VudFN0YXR1cz8uRmFpbHVyZVJlYXNvbn0uYFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU3RhdGUgPT0gU1VDQ0VFREVEXG4gICAgICBhY2NvdW50SWQgPSByZXNwb25zZS5DcmVhdGVBY2NvdW50U3RhdHVzPy5BY2NvdW50SWQhO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhY2NvdW50SWQgPSBldmVudC5QaHlzaWNhbFJlc291cmNlSWQhO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBvcmdhbml6YXRpb25zQ2xpZW50XG4gICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Pcmdhbml6YXRpb25zLmh0bWwjZGVzY3JpYmVBY2NvdW50LXByb3BlcnR5XG4gICAgLmRlc2NyaWJlQWNjb3VudCh7IEFjY291bnRJZDogYWNjb3VudElkIH0pXG4gICAgLnByb21pc2UoKTtcblxuICAvLyBPbiBkZWxldGUsIHVwZGF0ZSBvciBjcmVhdGUgbW92ZSBhY2NvdW50IHRvIGRlc3RpbmF0aW9uIHBhcmVudFxuICBhd2FpdCBtb3ZlKG9yZ2FuaXphdGlvbnNDbGllbnQsIGFjY291bnRJZCwgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzPy5QYXJlbnRJZCk7XG5cbiAgLy8gT24gZGVsZXRlIGNsb3NlIGFjY291bnRcbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09IFwiRGVsZXRlXCIgJiYgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzPy5SZW1vdmFsUG9saWN5ID09IFwiZGVzdHJveVwiKSB7XG4gICAgYXdhaXQgY2xvc2Uob3JnYW5pemF0aW9uc0NsaWVudCwgYWNjb3VudElkKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAvLyBAdHMtaWdub3JlXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBhY2NvdW50SWQsXG4gICAgRGF0YToge1xuICAgICAgLi4uZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLFxuICAgICAgLi4uZXZlbnQuRGF0YSxcbiAgICAgIEFjY291bnRJZDogYWNjb3VudElkLFxuICAgICAgQWNjb3VudEFybjogcmVzcG9uc2UuQWNjb3VudD8uQXJuLFxuICAgICAgQWNjb3VudE5hbWU6IHJlc3BvbnNlLkFjY291bnQ/Lk5hbWUsXG4gICAgICBFbWFpbDogcmVzcG9uc2UuQWNjb3VudD8uRW1haWwsXG4gICAgfSxcbiAgfTtcbn1cblxuY29uc3QgZmluZEN1cnJlbnRQYXJlbnQgPSBhc3luYyAoY2xpZW50OiBPcmdhbml6YXRpb25zLCBpZDogc3RyaW5nKTogUHJvbWlzZTxPcmdhbml6YXRpb25zLlBhcmVudD4gPT4ge1xuICBjb25zdCByZXNwb25zZTogT3JnYW5pemF0aW9ucy5MaXN0UGFyZW50c1Jlc3BvbnNlID0gYXdhaXQgY2xpZW50XG4gICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Pcmdhbml6YXRpb25zLmh0bWwjbGlzdFBhcmVudHMtcHJvcGVydHlcbiAgICAubGlzdFBhcmVudHMoe1xuICAgICAgQ2hpbGRJZDogaWQsXG4gICAgfSlcbiAgICAucHJvbWlzZSgpO1xuXG4gIGlmIChyZXNwb25zZS5QYXJlbnRzPy5sZW5ndGgpIHtcbiAgICByZXR1cm4gcmVzcG9uc2UuUGFyZW50c1swXTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgcGFyZW50IGZvciBpZCAnJHtpZH0nYCk7XG59O1xuXG5jb25zdCBtb3ZlID0gYXN5bmMgKFxuICBjbGllbnQ6IE9yZ2FuaXphdGlvbnMsXG4gIGFjY291bnRJZDogc3RyaW5nLFxuICBkZXN0aW5hdGlvblBhcmVudElkOiBzdHJpbmcgfCB1bmRlZmluZWRcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIWRlc3RpbmF0aW9uUGFyZW50SWQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjdXJyZW50UGFyZW50ID0gYXdhaXQgZmluZEN1cnJlbnRQYXJlbnQob3JnYW5pemF0aW9uc0NsaWVudCwgYWNjb3VudElkKTtcblxuICBpZiAoZGVzdGluYXRpb25QYXJlbnRJZCA9PSBjdXJyZW50UGFyZW50LklkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgYXdhaXQgY2xpZW50XG4gICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Pcmdhbml6YXRpb25zLmh0bWwjbW92ZUFjY291bnQtcHJvcGVydHlcbiAgICAubW92ZUFjY291bnQoe1xuICAgICAgQWNjb3VudElkOiBhY2NvdW50SWQsXG4gICAgICBTb3VyY2VQYXJlbnRJZDogY3VycmVudFBhcmVudC5JZCEsXG4gICAgICBEZXN0aW5hdGlvblBhcmVudElkOiBkZXN0aW5hdGlvblBhcmVudElkLFxuICAgIH0pXG4gICAgLnByb21pc2UoKTtcbn07XG5cbi8qKlxuICogQmVmb3JlIGF3cy1jZGstbGliIDIuMTUuMCB0aGUgcGh5c2ljYWwgcmVzb3VyY2Ugd2FzIGRldGVybWluZWQgaW4gdGhlIG9uRXZlbnRIYW5kbGVyIGFuZCB0aGVyZWZvciB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgaWQgd2FzIHRoZSBhY2NvdW50J3MgQ3JlYXRlQWNjb3VudFN0YXR1c0lkLlxuICovXG5jb25zdCBpc0xlZ2FjeVBoeXNpY2FsUmVzb3VyY2VJZCA9IChldmVudDogSXNDb21wbGV0ZVJlcXVlc3QpOiBib29sZWFuID0+IHtcbiAgcmV0dXJuIC9jYXItW2EtejAtOV17OCwzMn0vLnRlc3QoZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkISk7XG59O1xuXG5jb25zdCBmaW5kQWNjb3VudEJ5RW1haWwgPSBhc3luYyAoY2xpZW50OiBPcmdhbml6YXRpb25zLCBlbWFpbDogc3RyaW5nKTogUHJvbWlzZTxPcmdhbml6YXRpb25zLkFjY291bnQgfCB1bmRlZmluZWQ+ID0+IHtcbiAgbGV0IHJlc3BvbnNlOiBPcmdhbml6YXRpb25zLkxpc3RBY2NvdW50c1Jlc3BvbnNlID0gYXdhaXQgY2xpZW50XG4gICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Pcmdhbml6YXRpb25zLmh0bWwjbGlzdEFjY291bnRzLXByb3BlcnR5XG4gICAgLmxpc3RBY2NvdW50cygpXG4gICAgLnByb21pc2UoKTtcbiAgZm9yIChjb25zdCBhY2NvdW50IG9mIHJlc3BvbnNlLkFjY291bnRzID8/IFtdKSB7XG4gICAgaWYgKGFjY291bnQuRW1haWwgPT0gZW1haWwpIHtcbiAgICAgIHJldHVybiBhY2NvdW50O1xuICAgIH1cbiAgfVxuXG4gIHdoaWxlIChyZXNwb25zZS5OZXh0VG9rZW4pIHtcbiAgICByZXNwb25zZSA9IGF3YWl0IGNsaWVudFxuICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Pcmdhbml6YXRpb25zLmh0bWwjbGlzdEFjY291bnRzLXByb3BlcnR5XG4gICAgICAubGlzdEFjY291bnRzKHsgTmV4dFRva2VuOiByZXNwb25zZS5OZXh0VG9rZW4gfSlcbiAgICAgIC5wcm9taXNlKCk7XG4gICAgZm9yIChjb25zdCBhY2NvdW50IG9mIHJlc3BvbnNlLkFjY291bnRzID8/IFtdKSB7XG4gICAgICBpZiAoYWNjb3VudC5FbWFpbCA9PSBlbWFpbCkge1xuICAgICAgICByZXR1cm4gYWNjb3VudDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufTtcblxuY29uc3QgY2xvc2UgPSBhc3luYyAoY2xpZW50OiBPcmdhbml6YXRpb25zLCBhY2NvdW50SWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBhd2FpdCBjbGllbnRcbiAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL09yZ2FuaXphdGlvbnMuaHRtbCNjbG9zZUFjY291bnQtcHJvcGVydHlcbiAgICAuY2xvc2VBY2NvdW50KHtcbiAgICAgIEFjY291bnRJZDogYWNjb3VudElkLFxuICAgIH0pO1xufTtcbiJdfQ==