From 4fe30e5035c1f02a535eba7dc9a6d7f2a28956be Mon Sep 17 00:00:00 2001
From: Ayush Shah <aayushshah896@gmail.com>
Date: Sun, 24 Dec 2023 11:08:53 +0530
Subject: [PATCH 1/3] fix keypair support for ec2

---
 packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
index e38d99f1354b9..b0fb5cf3ea592 100644
--- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
+++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
@@ -437,7 +437,7 @@ export class Instance extends Resource implements IInstance {
     // there is no need to configure them on the instance level
     this.instance = new CfnInstance(this, 'Resource', {
       imageId: imageConfig.imageId,
-      keyName: props.keyName,
+      keyName: props.keyPair?.keyPairName,
       instanceType: props.instanceType.toString(),
       subnetId: networkInterfaces ? undefined : subnet.subnetId,
       securityGroupIds: networkInterfaces ? undefined : securityGroupsToken,

From 4609f9d9c9e69a3e61a9cb46640e5f7609f78704 Mon Sep 17 00:00:00 2001
From: ayush-shah-1501 <aayushshah896@gmail.com>
Date: Mon, 25 Dec 2023 20:13:25 +0530
Subject: [PATCH 2/3] Fix: wrong parameter

---
 packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
index b0fb5cf3ea592..11f1725aa3820 100644
--- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
+++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
@@ -437,7 +437,7 @@ export class Instance extends Resource implements IInstance {
     // there is no need to configure them on the instance level
     this.instance = new CfnInstance(this, 'Resource', {
       imageId: imageConfig.imageId,
-      keyName: props.keyPair?.keyPairName,
+      keyName: props.keyPair?.keyPairName ?? props?.keyName,
       instanceType: props.instanceType.toString(),
       subnetId: networkInterfaces ? undefined : subnet.subnetId,
       securityGroupIds: networkInterfaces ? undefined : securityGroupsToken,

From f8cbdfae09a555772f157987b5be58a69d39b063 Mon Sep 17 00:00:00 2001
From: Kyle Laker <kyle@laker.email>
Date: Thu, 28 Dec 2023 20:28:28 -0500
Subject: [PATCH 3/3] Add additional tests for EC2 Instance Key Pair

---
 ...efaultTestDeployAssertF103D058.assets.json |   2 +-
 .../__entrypoint__.js                         | 147 ++++++++++++++++++
 .../index.js                                  |   0
 .../__entrypoint__.js                         | 147 ------------------
 .../aws-cdk-ec2-key-pair-1.assets.json        |  12 +-
 .../aws-cdk-ec2-key-pair-1.template.json      |   5 +-
 .../test/integ.key-pair.js.snapshot/cdk.out   |   2 +-
 .../integ.key-pair.js.snapshot/integ.json     |   2 +-
 .../integ.key-pair.js.snapshot/manifest.json  |   9 +-
 .../test/integ.key-pair.js.snapshot/tree.json |   5 +-
 packages/aws-cdk-lib/aws-ec2/lib/instance.ts  |   2 +-
 .../aws-ec2/lib/launch-template.ts            |   2 +-
 packages/aws-cdk-lib/aws-ec2/lib/nat.ts       |   2 +-
 .../aws-cdk-lib/aws-ec2/test/instance.test.ts |  20 +++
 14 files changed, 193 insertions(+), 164 deletions(-)
 create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js
 rename packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/{asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03 => asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292}/index.js (100%)
 delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js

diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json
index 25e7ca0bd298d..364588a780e55 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json
@@ -1,5 +1,5 @@
 {
-  "version": "35.0.0",
+  "version": "36.0.0",
   "files": {
     "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
       "source": {
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js
new file mode 100644
index 0000000000000..1e64dba70bdc0
--- /dev/null
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js
@@ -0,0 +1,147 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.withRetries = exports.handler = exports.external = void 0;
+const https = require("https");
+const url = require("url");
+// for unit tests
+exports.external = {
+    sendHttpRequest: defaultSendHttpRequest,
+    log: defaultLog,
+    includeStackTraces: true,
+    userHandlerIndex: './index',
+};
+const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED';
+const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID';
+async function handler(event, context) {
+    const sanitizedEvent = { ...event, ResponseURL: '...' };
+    exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2));
+    // ignore DELETE event when the physical resource ID is the marker that
+    // indicates that this DELETE is a subsequent DELETE to a failed CREATE
+    // operation.
+    if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) {
+        exports.external.log('ignoring DELETE event caused by a failed CREATE event');
+        await submitResponse('SUCCESS', event);
+        return;
+    }
+    try {
+        // invoke the user handler. this is intentionally inside the try-catch to
+        // ensure that if there is an error it's reported as a failure to
+        // cloudformation (otherwise cfn waits).
+        // eslint-disable-next-line @typescript-eslint/no-require-imports
+        const userHandler = require(exports.external.userHandlerIndex).handler;
+        const result = await userHandler(sanitizedEvent, context);
+        // validate user response and create the combined event
+        const responseEvent = renderResponse(event, result);
+        // submit to cfn as success
+        await submitResponse('SUCCESS', responseEvent);
+    }
+    catch (e) {
+        const resp = {
+            ...event,
+            Reason: exports.external.includeStackTraces ? e.stack : e.message,
+        };
+        if (!resp.PhysicalResourceId) {
+            // special case: if CREATE fails, which usually implies, we usually don't
+            // have a physical resource id. in this case, the subsequent DELETE
+            // operation does not have any meaning, and will likely fail as well. to
+            // address this, we use a marker so the provider framework can simply
+            // ignore the subsequent DELETE.
+            if (event.RequestType === 'Create') {
+                exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored');
+                resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER;
+            }
+            else {
+                // otherwise, if PhysicalResourceId is not specified, something is
+                // terribly wrong because all other events should have an ID.
+                exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`);
+            }
+        }
+        // this is an actual error, fail the activity altogether and exist.
+        await submitResponse('FAILED', resp);
+    }
+}
+exports.handler = handler;
+function renderResponse(cfnRequest, handlerResponse = {}) {
+    // if physical ID is not returned, we have some defaults for you based
+    // on the request type.
+    const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId;
+    // if we are in DELETE and physical ID was changed, it's an error.
+    if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) {
+        throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`);
+    }
+    // merge request event and result event (result prevails).
+    return {
+        ...cfnRequest,
+        ...handlerResponse,
+        PhysicalResourceId: physicalResourceId,
+    };
+}
+async function submitResponse(status, event) {
+    const json = {
+        Status: status,
+        Reason: event.Reason ?? status,
+        StackId: event.StackId,
+        RequestId: event.RequestId,
+        PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER,
+        LogicalResourceId: event.LogicalResourceId,
+        NoEcho: event.NoEcho,
+        Data: event.Data,
+    };
+    exports.external.log('submit response to cloudformation', json);
+    const responseBody = JSON.stringify(json);
+    const parsedUrl = url.parse(event.ResponseURL);
+    const req = {
+        hostname: parsedUrl.hostname,
+        path: parsedUrl.path,
+        method: 'PUT',
+        headers: {
+            'content-type': '',
+            'content-length': Buffer.byteLength(responseBody, 'utf8'),
+        },
+    };
+    const retryOptions = {
+        attempts: 5,
+        sleep: 1000,
+    };
+    await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody);
+}
+async function defaultSendHttpRequest(options, responseBody) {
+    return new Promise((resolve, reject) => {
+        try {
+            const request = https.request(options, _ => resolve());
+            request.on('error', reject);
+            request.write(responseBody);
+            request.end();
+        }
+        catch (e) {
+            reject(e);
+        }
+    });
+}
+function defaultLog(fmt, ...params) {
+    // eslint-disable-next-line no-console
+    console.log(fmt, ...params);
+}
+function withRetries(options, fn) {
+    return async (...xs) => {
+        let attempts = options.attempts;
+        let ms = options.sleep;
+        while (true) {
+            try {
+                return await fn(...xs);
+            }
+            catch (e) {
+                if (attempts-- <= 0) {
+                    throw e;
+                }
+                await sleep(Math.floor(Math.random() * ms));
+                ms *= 2;
+            }
+        }
+    };
+}
+exports.withRetries = withRetries;
+async function sleep(ms) {
+    return new Promise((ok) => setTimeout(ok, ms));
+}
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FB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SyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ==
\ No newline at end of file
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js
similarity index 100%
rename from packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/index.js
rename to packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js
deleted file mode 100644
index c83ecebaaadac..0000000000000
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js
+++ /dev/null
@@ -1,147 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.withRetries = exports.handler = exports.external = void 0;
-const https = require("https");
-const url = require("url");
-// for unit tests
-exports.external = {
-    sendHttpRequest: defaultSendHttpRequest,
-    log: defaultLog,
-    includeStackTraces: true,
-    userHandlerIndex: './index',
-};
-const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED';
-const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID';
-async function handler(event, context) {
-    const sanitizedEvent = { ...event, ResponseURL: '...' };
-    exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2));
-    // ignore DELETE event when the physical resource ID is the marker that
-    // indicates that this DELETE is a subsequent DELETE to a failed CREATE
-    // operation.
-    if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) {
-        exports.external.log('ignoring DELETE event caused by a failed CREATE event');
-        await submitResponse('SUCCESS', event);
-        return;
-    }
-    try {
-        // invoke the user handler. this is intentionally inside the try-catch to
-        // ensure that if there is an error it's reported as a failure to
-        // cloudformation (otherwise cfn waits).
-        // eslint-disable-next-line @typescript-eslint/no-require-imports
-        const userHandler = require(exports.external.userHandlerIndex).handler;
-        const result = await userHandler(sanitizedEvent, context);
-        // validate user response and create the combined event
-        const responseEvent = renderResponse(event, result);
-        // submit to cfn as success
-        await submitResponse('SUCCESS', responseEvent);
-    }
-    catch (e) {
-        const resp = {
-            ...event,
-            Reason: exports.external.includeStackTraces ? e.stack : e.message,
-        };
-        if (!resp.PhysicalResourceId) {
-            // special case: if CREATE fails, which usually implies, we usually don't
-            // have a physical resource id. in this case, the subsequent DELETE
-            // operation does not have any meaning, and will likely fail as well. to
-            // address this, we use a marker so the provider framework can simply
-            // ignore the subsequent DELETE.
-            if (event.RequestType === 'Create') {
-                exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored');
-                resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER;
-            }
-            else {
-                // otherwise, if PhysicalResourceId is not specified, something is
-                // terribly wrong because all other events should have an ID.
-                exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`);
-            }
-        }
-        // this is an actual error, fail the activity altogether and exist.
-        await submitResponse('FAILED', resp);
-    }
-}
-exports.handler = handler;
-function renderResponse(cfnRequest, handlerResponse = {}) {
-    // if physical ID is not returned, we have some defaults for you based
-    // on the request type.
-    const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId;
-    // if we are in DELETE and physical ID was changed, it's an error.
-    if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) {
-        throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`);
-    }
-    // merge request event and result event (result prevails).
-    return {
-        ...cfnRequest,
-        ...handlerResponse,
-        PhysicalResourceId: physicalResourceId,
-    };
-}
-async function submitResponse(status, event) {
-    const json = {
-        Status: status,
-        Reason: event.Reason ?? status,
-        StackId: event.StackId,
-        RequestId: event.RequestId,
-        PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER,
-        LogicalResourceId: event.LogicalResourceId,
-        NoEcho: event.NoEcho,
-        Data: event.Data,
-    };
-    exports.external.log('submit response to cloudformation', json);
-    const responseBody = JSON.stringify(json);
-    const parsedUrl = url.parse(event.ResponseURL);
-    const req = {
-        hostname: parsedUrl.hostname,
-        path: parsedUrl.path,
-        method: 'PUT',
-        headers: {
-            'content-type': '',
-            'content-length': Buffer.byteLength(responseBody, 'utf8'),
-        },
-    };
-    const retryOptions = {
-        attempts: 5,
-        sleep: 1000,
-    };
-    await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody);
-}
-async function defaultSendHttpRequest(options, responseBody) {
-    return new Promise((resolve, reject) => {
-        try {
-            const request = https.request(options, _ => resolve());
-            request.on('error', reject);
-            request.write(responseBody);
-            request.end();
-        }
-        catch (e) {
-            reject(e);
-        }
-    });
-}
-function defaultLog(fmt, ...params) {
-    // eslint-disable-next-line no-console
-    console.log(fmt, ...params);
-}
-function withRetries(options, fn) {
-    return async (...xs) => {
-        let attempts = options.attempts;
-        let ms = options.sleep;
-        while (true) {
-            try {
-                return await fn(...xs);
-            }
-            catch (e) {
-                if (attempts-- <= 0) {
-                    throw e;
-                }
-                await sleep(Math.floor(Math.random() * ms));
-                ms *= 2;
-            }
-        }
-    };
-}
-exports.withRetries = withRetries;
-async function sleep(ms) {
-    return new Promise((ok) => setTimeout(ok, ms));
-}
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFN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LE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ==
\ No newline at end of file
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json
index 2c8f5dc8b9a80..0a285e199ffc2 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json
@@ -1,20 +1,20 @@
 {
-  "version": "35.0.0",
+  "version": "36.0.0",
   "files": {
-    "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03": {
+    "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292": {
       "source": {
-        "path": "asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03",
+        "path": "asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292",
         "packaging": "zip"
       },
       "destinations": {
         "current_account-current_region": {
           "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
-          "objectKey": "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03.zip",
+          "objectKey": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip",
           "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
         }
       }
     },
-    "a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314": {
+    "8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3": {
       "source": {
         "path": "aws-cdk-ec2-key-pair-1.template.json",
         "packaging": "file"
@@ -22,7 +22,7 @@
       "destinations": {
         "current_account-current_region": {
           "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
-          "objectKey": "a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314.json",
+          "objectKey": "8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3.json",
           "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
         }
       }
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json
index 5ef53a1122263..35587df413651 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json
@@ -489,7 +489,7 @@
      "S3Bucket": {
       "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
      },
-     "S3Key": "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03.zip"
+     "S3Key": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip"
     },
     "Timeout": 900,
     "MemorySize": 128,
@@ -588,6 +588,9 @@
      "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter"
     },
     "InstanceType": "t3.micro",
+    "KeyName": {
+     "Ref": "TestKeyPair38B6CD21"
+    },
     "SecurityGroupIds": [
      {
       "Fn::GetAtt": [
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out
index c5cb2e5de6344..1f0068d32659a 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out
@@ -1 +1 @@
-{"version":"35.0.0"}
\ No newline at end of file
+{"version":"36.0.0"}
\ No newline at end of file
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json
index bb4e985790260..4dcce8053c150 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json
@@ -1,5 +1,5 @@
 {
-  "version": "35.0.0",
+  "version": "36.0.0",
   "testCases": {
     "KeyPairTest/DefaultTest": {
       "stacks": [
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json
index 4d7164db4e4eb..c176b681fa22b 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json
@@ -1,5 +1,5 @@
 {
-  "version": "35.0.0",
+  "version": "36.0.0",
   "artifacts": {
     "aws-cdk-ec2-key-pair-1.assets": {
       "type": "cdk:asset-manifest",
@@ -18,7 +18,7 @@
         "validateOnSynth": false,
         "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
         "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
-        "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314.json",
+        "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3.json",
         "requiresBootstrapStackVersion": 6,
         "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
         "additionalDependencies": [
@@ -217,7 +217,10 @@
         "/aws-cdk-ec2-key-pair-1/TestInstance/Resource": [
           {
             "type": "aws:cdk:logicalId",
-            "data": "TestInstance44016A9E"
+            "data": "TestInstance44016A9E",
+            "trace": [
+              "!!DESTRUCTIVE_CHANGES: WILL_REPLACE"
+            ]
           }
         ],
         "/aws-cdk-ec2-key-pair-1/SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [
diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json
index 64cc246f6004d..4c550ee2da1fb 100644
--- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json
+++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json
@@ -699,7 +699,7 @@
               }
             },
             "constructInfo": {
-              "fqn": "aws-cdk-lib.CustomResourceProvider",
+              "fqn": "aws-cdk-lib.CustomResourceProviderBase",
               "version": "0.0.0"
             }
           },
@@ -861,6 +861,9 @@
                       "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter"
                     },
                     "instanceType": "t3.micro",
+                    "keyName": {
+                      "Ref": "TestKeyPair38B6CD21"
+                    },
                     "securityGroupIds": [
                       {
                         "Fn::GetAtt": [
diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
index 11f1725aa3820..22691162731de 100644
--- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
+++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts
@@ -77,7 +77,7 @@ export interface InstanceProps {
    * Name of SSH keypair to grant access to instance
    *
    * @default - No SSH access will be possible.
-   * @deprecated - Use {@link keyPair} instead
+   * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
    */
   readonly keyName?: string;
 
diff --git a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts
index 9395afea35794..a245ea35fee2c 100644
--- a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts
+++ b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts
@@ -333,7 +333,7 @@ export interface LaunchTemplateProps {
    * Name of SSH keypair to grant access to instance
    *
    * @default - No SSH access will be possible.
-   * @deprecated - Use `keyPair` instead.
+   * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
    */
   readonly keyName?: string;
 
diff --git a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts
index b339b4e86fdc0..25c7c0b1d7f1f 100644
--- a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts
+++ b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts
@@ -172,7 +172,7 @@ export interface NatInstanceProps {
    * Name of SSH keypair to grant access to instance
    *
    * @default - No SSH access will be possible.
-   * @deprecated - Use `keyPair` instead.
+   * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
    */
   readonly keyName?: string;
 
diff --git a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts
index 8c902c1c51281..d188acae592b3 100644
--- a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts
+++ b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts
@@ -520,6 +520,26 @@ describe('instance', () => {
     })).toThrow('Cannot specify both of \'keyName\' and \'keyPair\'; prefer \'keyPair\'');
   });
 
+  it('correctly associates a key pair', () => {
+    // GIVEN
+    const keyPair = new KeyPair(stack, 'KeyPair', {
+      keyPairName: 'test-key-pair',
+    });
+
+    // WHEN
+    new Instance(stack, 'Instance', {
+      vpc,
+      instanceType: new InstanceType('t2.micro'),
+      machineImage: new AmazonLinuxImage(),
+      keyPair,
+    });
+
+    // THEN
+    Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', {
+      KeyName: stack.resolve(keyPair.keyPairName),
+    });
+  });
+
   describe('Detailed Monitoring', () => {
     test('instance with Detailed Monitoring enabled', () => {
       // WHEN