1import * as AWS from "@/AWS";
2import { KeyPair } from "@/AWS/EC2/KeyPair.ts";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as ec2 from "@distilled.cloud/aws/ec2";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import * as Redacted from "effect/Redacted";
9import { assertKeyPairGone } from "./Gone.ts";
10
11const { test } = Test.make({ providers: AWS.providers() });
12
13// Create a generated key pair, assert the private key is captured, verify it
14// exists out-of-band, then destroy it and confirm it is gone.
15test.provider(
16 "create generates a key pair and captures the private key",
17 (stack) =>
18 Effect.gen(function* () {
19 yield* stack.destroy();
20
21 const keyPair = yield* stack.deploy(
22 Effect.gen(function* () {
23 return yield* KeyPair("GeneratedKey", { keyType: "ed25519" });
24 }),
25 );
26
27 expect(keyPair.keyPairId).toMatch(/^key-/);
28 expect(keyPair.keyName).toBeTruthy();
29 expect(keyPair.keyType).toBe("ed25519");
30 expect(keyPair.keyFingerprint).toBeTruthy();
31 // AWS returns the private key exactly once, at create time.
32 expect(keyPair.privateKey).toBeDefined();
33 expect(Redacted.value(keyPair.privateKey!)).toContain("PRIVATE KEY");
34
35 // Verify out-of-band.
36 const described = yield* ec2.describeKeyPairs({
37 KeyPairIds: [keyPair.keyPairId],
38 });
39 expect(described.KeyPairs?.[0]?.KeyName).toBe(keyPair.keyName);
40 expect(described.KeyPairs?.[0]?.KeyType).toBe("ed25519");
41
42 yield* stack.destroy();
43
44 // Confirm deletion.
45 const after = yield* ec2
46 .describeKeyPairs({ KeyNames: [keyPair.keyName] })
47 .pipe(
48 Effect.catchTag("InvalidKeyPair.NotFound", () =>
49 Effect.succeed({ KeyPairs: [] }),
50 ),
51 );
52 expect(after.KeyPairs ?? []).toHaveLength(0);
53 }),
54 { tags: ["provider:aws", "provider:aws:ec2", "live"] },
55);
56
57// `list()` enumerates branded key pairs in the account.
58test.provider(
59 "list enumerates the deployed key pair",
60 (stack) =>
61 Effect.gen(function* () {
62 yield* stack.destroy();
63
64 const keyPair = yield* stack.deploy(
65 Effect.gen(function* () {
66 return yield* KeyPair("ListKey", {});
67 }),
68 );
69
70 const provider = yield* Provider.findProvider(KeyPair);
71 const all = yield* provider.list();
72 expect(all.some((k) => k.keyPairId === keyPair.keyPairId)).toBe(true);
73
74 yield* stack.destroy();
75
76 yield* assertKeyPairGone(keyPair.keyPairId);
77 }),
78 { tags: ["provider:aws", "provider:aws:ec2", "live"] },
79);