UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

590 lines 89.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable import/order */ const os = require("os"); const cdk_build_tools_1 = require("@aws-cdk/cdk-build-tools"); const cxapi = require("@aws-cdk/cx-api"); const AWS = require("aws-sdk"); const promptly = require("promptly"); const uuid = require("uuid"); const fake_sts_1 = require("./fake-sts"); const aws_auth_1 = require("../../lib/api/aws-auth"); const plugin_1 = require("../../lib/api/plugin"); const logging = require("../../lib/logging"); const util_1 = require("../util"); jest.mock('promptly', () => ({ prompt: jest.fn().mockResolvedValue('1234'), })); const defaultCredOptions = { ec2creds: false, containerCreds: false, }; let uid; let pluginQueried = false; beforeEach(() => { // Cache busters! // We prefix everything with UUIDs because: // // - We have a cache from account# -> credentials // - We have a cache from access key -> account uid = `(${uuid.v4()})`; logging.setLogLevel(logging.LogLevel.TRACE); plugin_1.PluginHost.instance.credentialProviderSources.splice(0); plugin_1.PluginHost.instance.credentialProviderSources.push({ isAvailable() { return Promise.resolve(true); }, canProvideCredentials(account) { return Promise.resolve(account === uniq('99999')); }, getProvider() { pluginQueried = true; return Promise.resolve(new AWS.Credentials({ accessKeyId: `${uid}plugin_key`, secretAccessKey: 'plugin_secret', sessionToken: 'plugin_token', })); }, name: 'test plugin', }); // Make sure these point to nonexistant files to start, if we don't call // prepare() then we don't accidentally want to fall back to system config. process.env.AWS_CONFIG_FILE = '/dev/null'; process.env.AWS_SHARED_CREDENTIALS_FILE = '/dev/null'; }); afterEach(() => { cdk_build_tools_1.bockfs.restore(); }); function uniq(account) { return `${uid}${account}`; } function env(account) { return cxapi.EnvironmentUtils.make(account, 'def'); } describe('with intercepted network calls', () => { // Most tests will use intercepted network calls, except one test that tests // that the right HTTP `Agent` is used. let fakeSts; beforeEach(() => { fakeSts = new fake_sts_1.FakeSts(); fakeSts.begin(); // Make sure the KeyID returned by the plugin is recognized fakeSts.registerUser(uniq('99999'), uniq('plugin_key')); }); afterEach(() => { fakeSts.restore(); }); // Set of tests where the CDK will not trigger assume-role // (the INI file might still do assume-role) describe('when CDK does not AssumeRole', () => { test('uses default credentials by default', async () => { // WHEN prepareCreds({ fakeSts, credentials: { default: { aws_access_key_id: 'access', $account: '11111', $fakeStsOptions: { partition: 'aws-here' } }, }, config: { default: { region: 'eu-bla-5' }, }, }); const provider = await providerFromProfile(undefined); // THEN expect(provider.defaultRegion).toEqual('eu-bla-5'); await expect(provider.defaultAccount()).resolves.toEqual({ accountId: uniq('11111'), partition: 'aws-here' }); // Ask for a different region const sdk = (await provider.forEnvironment({ ...env(uniq('11111')), region: 'rgn' }, aws_auth_1.Mode.ForReading)).sdk; expect(sdkConfig(sdk).credentials.accessKeyId).toEqual(uniq('access')); expect(sdk.currentRegion).toEqual('rgn'); }); test('throws if profile credentials are not for the right account', async () => { // WHEN prepareCreds({ fakeSts, config: { 'profile boo': { aws_access_key_id: 'access', $account: '11111' }, }, }); const provider = await providerFromProfile('boo'); await expect(provider.forEnvironment(env(uniq('some_account_#')), aws_auth_1.Mode.ForReading)).rejects.toThrow('Need to perform AWS calls'); }); test('use profile acct/region if agnostic env requested', async () => { // WHEN prepareCreds({ fakeSts, credentials: { default: { aws_access_key_id: 'access', $account: '11111' }, }, config: { default: { region: 'eu-bla-5' }, }, }); const provider = await providerFromProfile(undefined); // THEN const sdk = (await provider.forEnvironment(cxapi.EnvironmentUtils.make(cxapi.UNKNOWN_ACCOUNT, cxapi.UNKNOWN_REGION), aws_auth_1.Mode.ForReading)).sdk; expect(sdkConfig(sdk).credentials.accessKeyId).toEqual(uniq('access')); expect((await sdk.currentAccount()).accountId).toEqual(uniq('11111')); expect(sdk.currentRegion).toEqual('eu-bla-5'); }); test('passing profile skips EnvironmentCredentials', async () => { // GIVEN prepareCreds({ fakeSts, credentials: { foo: { aws_access_key_id: 'access', $account: '11111' }, }, }); const provider = await providerFromProfile('foo'); const environmentCredentialsPrototype = (new AWS.EnvironmentCredentials('AWS')).constructor.prototype; await (0, util_1.withMocked)(environmentCredentialsPrototype, 'refresh', async (refresh) => { refresh.mockImplementation((callback) => callback(new Error('This function should not have been called'))); // WHEN expect((await provider.defaultAccount())?.accountId).toEqual(uniq('11111')); expect(refresh).not.toHaveBeenCalled(); }); }); test('supports profile spread over config_file and credentials_file', async () => { // WHEN prepareCreds({ fakeSts, credentials: { foo: { aws_access_key_id: 'fooccess', $account: '22222' }, }, config: { 'default': { region: 'eu-bla-5' }, 'profile foo': { region: 'eu-west-1' }, }, }); const provider = await aws_auth_1.SdkProvider.withAwsCliCompatibleDefaults({ ...defaultCredOptions, profile: 'foo' }); // THEN expect(provider.defaultRegion).toEqual('eu-west-1'); await expect(provider.defaultAccount()).resolves.toEqual({ accountId: uniq('22222'), partition: 'aws' }); const sdk = (await provider.forEnvironment(env(uniq('22222')), aws_auth_1.Mode.ForReading)).sdk; expect(sdkConfig(sdk).credentials.accessKeyId).toEqual(uniq('fooccess')); }); test('supports profile only in config_file', async () => { // WHEN prepareCreds({ fakeSts, config: { 'default': { region: 'eu-bla-5' }, 'profile foo': { aws_access_key_id: 'fooccess', $account: '22222' }, }, }); const provider = await providerFromProfile('foo'); // THEN expect(provider.defaultRegion).toEqual('eu-bla-5'); // Fall back to default config await expect(provider.defaultAccount()).resolves.toEqual({ accountId: uniq('22222'), partition: 'aws' }); const sdk = (await provider.forEnvironment(env(uniq('22222')), aws_auth_1.Mode.ForReading)).sdk; expect(sdkConfig(sdk).credentials.accessKeyId).toEqual(uniq('fooccess')); }); test('can assume-role configured in config', async () => { // GIVEN prepareCreds({ fakeSts, credentials: { assumer: { aws_access_key_id: 'assumer', $account: '11111' }, }, config: { 'default': { region: 'eu-bla-5' }, 'profile assumer': { region: 'us-east-2' }, 'profile assumable': { role_arn: 'arn:aws:iam::66666:role/Assumable', source_profile: 'assumer', $account: '66666', $fakeStsOptions: { allowedAccounts: ['11111'] }, }, }, }); const provider = await providerFromProfile('assumable'); // WHEN const sdk = (await provider.forEnvironment(env(uniq('66666')), aws_auth_1.Mode.ForReading)).sdk; // THEN expect((await sdk.currentAccount()).accountId).toEqual(uniq('66666')); }); test('can assume role even if [default] profile is missing', async () => { // GIVEN prepareCreds({ fakeSts, credentials: { assumer: { aws_access_key_id: 'assumer', $account: '22222' }, assumable: { role_arn: 'arn:aws:iam::12356789012:role/Assumable', source_profile: 'assumer', $account: '22222' }, }, config: { 'profile assumable': { region: 'eu-bla-5' }, }, }); // WHEN const provider = await providerFromProfile('assumable'); // THEN expect((await provider.defaultAccount())?.accountId).toEqual(uniq('22222')); }); test('mfa_serial in profile will ask user for token', async () => { // GIVEN prepareCreds({ fakeSts, credentials: { assumer: { aws_access_key_id: 'assumer', $account: '66666' }, }, config: { 'default': { region: 'eu-bla-5' }, 'profile assumer': { region: 'us-east-2' }, 'profile mfa-role': { role_arn: 'arn:aws:iam::66666:role/Assumable', source_profile: 'assumer', mfa_serial: 'arn:aws:iam::account:mfa/user', $account: '66666', }, }, }); const provider = await providerFromProfile('mfa-role'); const promptlyMockCalls = promptly.prompt.mock.calls.length; // THEN const sdk = (await provider.forEnvironment(env(uniq('66666')), aws_auth_1.Mode.ForReading)).sdk; expect((await sdk.currentAccount()).accountId).toEqual(uniq('66666')); expect(fakeSts.assumedRoles[0]).toEqual(expect.objectContaining({ roleArn: 'arn:aws:iam::66666:role/Assumable', serialNumber: 'arn:aws:iam::account:mfa/user', tokenCode: '1234', })); // Mock response was set to fail to make sure we don't call STS // Make sure the MFA mock was called during this test expect(promptly.prompt.mock.calls.length).toBe(promptlyMockCalls + 1); }); }); // For DefaultSynthesis we will do an assume-role after having gotten base credentials describe('when CDK AssumeRoles', () => { beforeEach(() => { // All these tests share that 'arn:aws:role' is a role into account 88888 which can be assumed from 11111 fakeSts.registerRole(uniq('88888'), 'arn:aws:role', { allowedAccounts: [uniq('11111')] }); }); test('error we get from assuming a role is useful', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo' }, }, }); const provider = await providerFromProfile(undefined); // WHEN const promise = provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'doesnotexist.role.arn', }); // THEN - error message contains both a helpful hint and the underlying AssumeRole message await expect(promise).rejects.toThrow('(re)-bootstrap the environment'); await expect(promise).rejects.toThrow('doesnotexist.role.arn'); }); test('assuming a role sanitizes the username into the session name', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '11111' }, }, }); await (0, util_1.withMocked)(os, 'userInfo', async (userInfo) => { userInfo.mockReturnValue({ username: 'skål', uid: 1, gid: 1, homedir: '/here', shell: '/bin/sh' }); // WHEN const provider = await providerFromProfile(undefined); const sdk = (await provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'arn:aws:role' })).sdk; await sdk.currentAccount(); // THEN expect(fakeSts.assumedRoles[0]).toEqual(expect.objectContaining({ roleSessionName: 'aws-cdk-sk@l', })); }); }); test('assuming a role does not fail when OS username cannot be read', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '11111' }, }, }); await (0, util_1.withMocked)(os, 'userInfo', async (userInfo) => { userInfo.mockImplementation(() => { // SystemError thrown as documented: https://nodejs.org/docs/latest-v16.x/api/os.html#osuserinfooptions throw new Error('SystemError on Linux: uv_os_get_passwd returned ENOENT. See #19401 issue.'); }); // WHEN const provider = await providerFromProfile(undefined); const sdk = (await provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'arn:aws:role' })).sdk; await sdk.currentAccount(); // THEN expect(fakeSts.assumedRoles[0]).toEqual(expect.objectContaining({ roleSessionName: 'aws-cdk-noname', })); }); }); test('even if current credentials are for the wrong account, we will still use them to AssumeRole', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '11111' }, }, }); const provider = await providerFromProfile(undefined); // WHEN const sdk = (await provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'arn:aws:role' })).sdk; // THEN expect((await sdk.currentAccount()).accountId).toEqual(uniq('88888')); }); test('if AssumeRole fails but current credentials are for the right account, we will still use them', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '88888' }, }, }); const provider = await providerFromProfile(undefined); // WHEN - assumeRole fails because the role can only be assumed from account 11111 const sdk = (await provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'arn:aws:role' })).sdk; // THEN expect((await sdk.currentAccount()).accountId).toEqual(uniq('88888')); }); test('if AssumeRole fails because of ExpiredToken, then fail completely', async () => { // GIVEN prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '88888' }, }, }); const provider = await providerFromProfile(undefined); // WHEN - assumeRole fails with a specific error await expect(async () => { await provider.forEnvironment(env(uniq('88888')), aws_auth_1.Mode.ForReading, { assumeRoleArn: '<FAIL:ExpiredToken>' }); }).rejects.toThrow(/ExpiredToken/); }); }); describe('Plugins', () => { test('does not use plugins if current credentials are for expected account', async () => { prepareCreds({ fakeSts, config: { default: { aws_access_key_id: 'foo', $account: '11111' }, }, }); const provider = await providerFromProfile(undefined); await provider.forEnvironment(env(uniq('11111')), aws_auth_1.Mode.ForReading); expect(pluginQueried).toEqual(false); }); test('uses plugin for account 99999', async () => { const provider = await providerFromProfile(undefined); await provider.forEnvironment(env(uniq('99999')), aws_auth_1.Mode.ForReading); expect(pluginQueried).toEqual(true); }); test('can assume role with credentials from plugin', async () => { fakeSts.registerRole(uniq('99999'), 'arn:aws:iam::99999:role/Assumable'); const provider = await providerFromProfile(undefined); await provider.forEnvironment(env(uniq('99999')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'arn:aws:iam::99999:role/Assumable', }); expect(fakeSts.assumedRoles[0]).toEqual(expect.objectContaining({ roleArn: 'arn:aws:iam::99999:role/Assumable', })); expect(pluginQueried).toEqual(true); }); test('even if AssumeRole fails but current credentials are from a plugin, we will still use them', async () => { const provider = await providerFromProfile(undefined); const sdk = (await provider.forEnvironment(env(uniq('99999')), aws_auth_1.Mode.ForReading, { assumeRoleArn: 'does:not:exist' })).sdk; // THEN expect((await sdk.currentAccount()).accountId).toEqual(uniq('99999')); }); test('plugins are still queried even if current credentials are expired (or otherwise invalid)', async () => { // GIVEN process.env.AWS_ACCESS_KEY_ID = `${uid}akid`; process.env.AWS_SECRET_ACCESS_KEY = 'sekrit'; const provider = await providerFromProfile(undefined); // WHEN await provider.forEnvironment(env(uniq('99999')), aws_auth_1.Mode.ForReading); // THEN expect(pluginQueried).toEqual(true); }); }); describe('support for credential_source', () => { test('can assume role with ecs credentials', async () => { return (0, util_1.withMocked)(AWS.ECSCredentials.prototype, 'needsRefresh', async (needsRefresh) => { // GIVEN prepareCreds({ config: { 'profile ecs': { role_arn: 'arn:aws:iam::12356789012:role/Assumable', credential_source: 'EcsContainer', $account: '22222' }, }, }); const provider = await providerFromProfile('ecs'); // WHEN await provider.defaultAccount(); // THEN expect(needsRefresh).toHaveBeenCalled(); }); }); test('can assume role with ec2 credentials', async () => { return (0, util_1.withMocked)(AWS.EC2MetadataCredentials.prototype, 'needsRefresh', async (needsRefresh) => { // GIVEN prepareCreds({ config: { 'profile ecs': { role_arn: 'arn:aws:iam::12356789012:role/Assumable', credential_source: 'Ec2InstanceMetadata', $account: '22222' }, }, }); const provider = await providerFromProfile('ecs'); // WHEN await provider.defaultAccount(); // THEN expect(needsRefresh).toHaveBeenCalled(); }); }); test('can assume role with env credentials', async () => { return (0, util_1.withMocked)(AWS.EnvironmentCredentials.prototype, 'needsRefresh', async (needsRefresh) => { // GIVEN prepareCreds({ config: { 'profile ecs': { role_arn: 'arn:aws:iam::12356789012:role/Assumable', credential_source: 'Environment', $account: '22222' }, }, }); const provider = await providerFromProfile('ecs'); // WHEN await provider.defaultAccount(); // THEN expect(needsRefresh).toHaveBeenCalled(); }); }); test('assume fails with unsupported credential_source', async () => { // GIVEN prepareCreds({ config: { 'profile ecs': { role_arn: 'arn:aws:iam::12356789012:role/Assumable', credential_source: 'unsupported', $account: '22222' }, }, }); const provider = await providerFromProfile('ecs'); // WHEN const account = await provider.defaultAccount(); // THEN expect(account?.accountId).toEqual(undefined); }); }); test('defaultAccount returns undefined if STS call fails', async () => { // GIVEN process.env.AWS_ACCESS_KEY_ID = `${uid}akid`; process.env.AWS_SECRET_ACCESS_KEY = 'sekrit'; // WHEN const provider = await providerFromProfile(undefined); // THEN await expect(provider.defaultAccount()).resolves.toBe(undefined); }); test('defaultAccount returns undefined, event if STS call fails with ExpiredToken', async () => { // GIVEN process.env.AWS_ACCESS_KEY_ID = `${uid}'<FAIL:ExpiredToken>'`; process.env.AWS_SECRET_ACCESS_KEY = 'sekrit'; // WHEN const provider = await providerFromProfile(undefined); // THEN await expect(provider.defaultAccount()).resolves.toBe(undefined); }); }); test('even when using a profile to assume another profile, STS calls goes through the proxy', async () => { prepareCreds({ credentials: { assumer: { aws_access_key_id: 'assumer' }, }, config: { 'default': { region: 'eu-bla-5' }, 'profile assumable': { role_arn: 'arn:aws:iam::66666:role/Assumable', source_profile: 'assumer', $account: '66666' }, 'profile assumer': { region: 'us-east-2' }, }, }); // Messy mocking let called = false; jest.mock('proxy-agent', () => { // eslint-disable-next-line @typescript-eslint/no-require-imports class FakeAgent extends require('https').Agent { addRequest(_, __) { // FIXME: this error takes 6 seconds to be completely handled. It // might be retries in the SDK somewhere, or something about the Node // event loop. I've spent an hour trying to figure it out and I can't, // and I gave up. We'll just have to live with this until someone gets // inspired. const error = new Error('ABORTED BY TEST'); error.code = 'RequestAbortedError'; error.retryable = false; called = true; throw error; } } return { ProxyAgent: FakeAgent }; }); // WHEN const provider = await aws_auth_1.SdkProvider.withAwsCliCompatibleDefaults({ ...defaultCredOptions, profile: 'assumable', httpOptions: { proxyAddress: 'http://DOESNTMATTER/', }, }); await provider.defaultAccount(); // THEN -- the fake proxy agent got called, we don't care about the result expect(called).toEqual(true); }); test('default useragent is reasonable', () => { expect((0, aws_auth_1.defaultCliUserAgent)()).toContain('aws-cdk/'); }); /** * Use object hackery to get the credentials out of the SDK object */ function sdkConfig(sdk) { return sdk.config; } /** * Fixture for SDK auth for this test suite * * Has knowledge of the cache buster, will write proper fake config files and * register users and roles in FakeSts at the same time. */ function prepareCreds(options) { function convertSections(sections) { const ret = []; for (const [profile, user] of Object.entries(sections ?? {})) { ret.push(`[${profile}]`); if (isProfileRole(user)) { ret.push(`role_arn=${user.role_arn}`); if ('source_profile' in user) { ret.push(`source_profile=${user.source_profile}`); } if ('credential_source' in user) { ret.push(`credential_source=${user.credential_source}`); } if (user.mfa_serial) { ret.push(`mfa_serial=${user.mfa_serial}`); } options.fakeSts?.registerRole(uniq(user.$account ?? '00000'), user.role_arn, { ...user.$fakeStsOptions, allowedAccounts: user.$fakeStsOptions?.allowedAccounts?.map(uniq), }); } else { if (user.aws_access_key_id) { ret.push(`aws_access_key_id=${uniq(user.aws_access_key_id)}`); ret.push('aws_secret_access_key=secret'); options.fakeSts?.registerUser(uniq(user.$account ?? '00000'), uniq(user.aws_access_key_id), user.$fakeStsOptions); } } if (user.region) { ret.push(`region=${user.region}`); } } return ret.join('\n'); } (0, cdk_build_tools_1.bockfs)({ '/home/me/.bxt/credentials': convertSections(options.credentials), '/home/me/.bxt/config': convertSections(options.config), }); // Set environment variables that we want process.env.AWS_CONFIG_FILE = cdk_build_tools_1.bockfs.path('/home/me/.bxt/config'); process.env.AWS_SHARED_CREDENTIALS_FILE = cdk_build_tools_1.bockfs.path('/home/me/.bxt/credentials'); } function isProfileRole(x) { return 'role_arn' in x; } function providerFromProfile(profile) { return aws_auth_1.SdkProvider.withAwsCliCompatibleDefaults({ ...defaultCredOptions, profile }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLXByb3ZpZGVyLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZGstcHJvdmlkZXIudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQyx5QkFBeUI7QUFDekIsOERBQWtEO0FBQ2xELHlDQUF5QztBQUN6QywrQkFBK0I7QUFFL0IscUNBQXFDO0FBQ3JDLDZCQUE2QjtBQUM3Qix5Q0FBK0U7QUFDL0UscURBQTJGO0FBQzNGLGlEQUFrRDtBQUNsRCw2Q0FBNkM7QUFDN0Msa0NBQXFDO0FBRXJDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDM0IsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUM7Q0FDNUMsQ0FBQyxDQUFDLENBQUM7QUFFSixNQUFNLGtCQUFrQixHQUFHO0lBQ3pCLFFBQVEsRUFBRSxLQUFLO0lBQ2YsY0FBYyxFQUFFLEtBQUs7Q0FDdEIsQ0FBQztBQUVGLElBQUksR0FBVyxDQUFDO0FBQ2hCLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztBQUUxQixVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsaUJBQWlCO0lBQ2pCLDJDQUEyQztJQUMzQyxFQUFFO0lBQ0YsaURBQWlEO0lBQ2pELCtDQUErQztJQUMvQyxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUV2QixPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFNUMsbUJBQVUsQ0FBQyxRQUFRLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELG1CQUFVLENBQUMsUUFBUSxDQUFDLHlCQUF5QixDQUFDLElBQUksQ0FBQztRQUNqRCxXQUFXLEtBQUssT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FB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