| 1 | import type { Input } from "../../Input.ts"; |
| 2 | import type { PolicyStatement } from "../IAM/Policy.ts"; |
| 3 | import type { AliasName } from "./Alias.ts"; |
| 4 | import type { Key } from "./Key.ts"; |
| 5 | |
| 6 | /** |
| 7 | * The target of a KMS cryptographic binding: either a {@link Key} resource |
| 8 | * declared in the stack, or the alias name (`alias/...`) of a pre-existing |
| 9 | * key that is managed outside the stack. |
| 10 | * |
| 11 | * When an alias name is given, the runtime request identifies the key by that |
| 12 | * alias and the IAM policy is scoped with the `kms:RequestAlias` condition |
| 13 | * key, so the role can only use keys through that exact alias. |
| 14 | * |
| 15 | * @internal shared scaffolding for the KMS crypto bindings — not exported |
| 16 | * from the service index. |
| 17 | */ |
| 18 | export type KeyLike = Key | AliasName; |
| 19 | |
| 20 | /** |
| 21 | * Build the least-privilege IAM policy statement for a KMS crypto operation |
| 22 | * against a {@link KeyLike} target. |
| 23 | * |
| 24 | * - `Key` resource → `Resource` is the exact key ARN. |
| 25 | * - alias name → `Resource: "*"` constrained by the `kms:RequestAlias` |
| 26 | * condition, AWS's documented pattern for alias-scoped access. The runtime |
| 27 | * caller must (and does) address the key by that alias. |
| 28 | * |
| 29 | * @internal |
| 30 | */ |
| 31 | export const keyPolicyStatement = ( |
| 32 | action: `kms:${string}` | readonly `kms:${string}`[], |
| 33 | key: KeyLike, |
| 34 | ): Input<PolicyStatement> => |
| 35 | typeof key === "string" |
| 36 | ? { |
| 37 | Effect: "Allow", |
| 38 | Action: typeof action === "string" ? [action] : [...action], |
| 39 | Resource: ["*"], |
| 40 | Condition: { StringEquals: { "kms:RequestAlias": key } }, |
| 41 | } |
| 42 | : { |
| 43 | Effect: "Allow", |
| 44 | Action: typeof action === "string" ? [action] : [...action], |
| 45 | Resource: [key.keyArn], |
| 46 | }; |
| 47 | |
| 48 | /** Stable human-readable label for tracing spans. @internal */ |
| 49 | export const keyLabel = (key: KeyLike): string => |
| 50 | typeof key === "string" ? key : key.LogicalId; |