@fjall/components-infrastructure 39.0.0 → 39.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,10 +21,18 @@ import { CustomerManagedKey } from "./kms.js";
21
21
  * `customerManagedKeys` column is read. Grant-based consumers (DynamoDB,
22
22
  * Lambda `environmentEncryption`, ECS Exec) then read `key` directly — the
23
23
  * SDK/CDK grants they need ride the resource's own IAM path. Service-side
24
- * encryptors need a resource-policy admission first: CloudWatch Logs through
25
- * [[forLogGroups]], SNS service publishers through
26
- * [[forSnsServicePublishers]], SQS senders through
27
- * [[forSqsServicePublishers]]. Each admission is added once per stack.
24
+ * encryptors need a resource-policy admission first. SNS service publishers
25
+ * come through [[forSnsServicePublishers]] and SQS senders through
26
+ * [[forSqsServicePublishers]], each added once per stack.
27
+ *
28
+ * CloudWatch Logs is admitted when the key is created, whatever the stack's
29
+ * log groups do. Data a log group encrypted stays under the key after the
30
+ * group stops being keyed, and CloudWatch Logs needs the key to read it. Synth
31
+ * has no memory of the last deployment, so a statement added only while a
32
+ * group asks for it would be dropped on the first deploy with no keyed group.
33
+ * The key would stay, because a table, topic or queue still uses it, and the
34
+ * earlier events would become unreadable. [[forLogGroups]] names the intent at
35
+ * its call sites and adds nothing.
28
36
  *
29
37
  * A resource may also reach the key WITHOUT the tier, through [[of]]: an SQS
30
38
  * queue declaring `encryption: "SSE_KMS"` encrypts with the stack key at
@@ -42,7 +50,6 @@ import { CustomerManagedKey } from "./kms.js";
42
50
  * still needs.
43
51
  */
44
52
  export declare class StackEncryptionKey extends CustomerManagedKey {
45
- private logsAdmitted;
46
53
  private snsPublishersAdmitted;
47
54
  private sqsPublishersAdmitted;
48
55
  private constructor();
@@ -59,11 +66,12 @@ export declare class StackEncryptionKey extends CustomerManagedKey {
59
66
  */
60
67
  static forTier(scope: Construct, tier: BackupTier | undefined, override?: boolean): StackEncryptionKey | undefined;
61
68
  /**
62
- * The key, with CloudWatch Logs admitted to it. The CDK `LogGroup` sets
63
- * `KmsKeyId` but adds no key-policy statement, and without one the
64
- * service cannot encrypt the group and the stack fails to create. The
65
- * encryption-context condition confines the admission to log groups in
66
- * this account and region (the AWS-documented shape).
69
+ * The key, for a log group's `encryptionKey`. CloudWatch Logs is already
70
+ * admitted by the constructor: the CDK `LogGroup` sets `KmsKeyId` but adds
71
+ * no key-policy statement, and without one the service cannot encrypt the
72
+ * group and the stack fails to create. The encryption-context condition
73
+ * confines the admission to log groups in this account and Region (the
74
+ * AWS-documented shape).
67
75
  */
68
76
  forLogGroups(): IKey;
69
77
  /**
@@ -58,10 +58,18 @@ const SQS_SERVICE_PUBLISHERS = [
58
58
  * `customerManagedKeys` column is read. Grant-based consumers (DynamoDB,
59
59
  * Lambda `environmentEncryption`, ECS Exec) then read `key` directly — the
60
60
  * SDK/CDK grants they need ride the resource's own IAM path. Service-side
61
- * encryptors need a resource-policy admission first: CloudWatch Logs through
62
- * [[forLogGroups]], SNS service publishers through
63
- * [[forSnsServicePublishers]], SQS senders through
64
- * [[forSqsServicePublishers]]. Each admission is added once per stack.
61
+ * encryptors need a resource-policy admission first. SNS service publishers
62
+ * come through [[forSnsServicePublishers]] and SQS senders through
63
+ * [[forSqsServicePublishers]], each added once per stack.
64
+ *
65
+ * CloudWatch Logs is admitted when the key is created, whatever the stack's
66
+ * log groups do. Data a log group encrypted stays under the key after the
67
+ * group stops being keyed, and CloudWatch Logs needs the key to read it. Synth
68
+ * has no memory of the last deployment, so a statement added only while a
69
+ * group asks for it would be dropped on the first deploy with no keyed group.
70
+ * The key would stay, because a table, topic or queue still uses it, and the
71
+ * earlier events would become unreadable. [[forLogGroups]] names the intent at
72
+ * its call sites and adds nothing.
65
73
  *
66
74
  * A resource may also reach the key WITHOUT the tier, through [[of]]: an SQS
67
75
  * queue declaring `encryption: "SSE_KMS"` encrypts with the stack key at
@@ -79,7 +87,6 @@ const SQS_SERVICE_PUBLISHERS = [
79
87
  * still needs.
80
88
  */
81
89
  export class StackEncryptionKey extends CustomerManagedKey {
82
- logsAdmitted = false;
83
90
  snsPublishersAdmitted = false;
84
91
  sqsPublishersAdmitted = false;
85
92
  constructor(stack) {
@@ -91,6 +98,25 @@ export class StackEncryptionKey extends CustomerManagedKey {
91
98
  aliasName: ResourceNaming.stackEncryptionKeyAlias(stack.stackName),
92
99
  protects: "outlives-stack"
93
100
  });
101
+ this.key.addToResourcePolicy(new PolicyStatement({
102
+ sid: "AllowCloudWatchLogs",
103
+ principals: [
104
+ new ServicePrincipal(`logs.${stack.region}.amazonaws.com`)
105
+ ],
106
+ actions: [
107
+ "kms:Encrypt*",
108
+ "kms:Decrypt*",
109
+ "kms:ReEncrypt*",
110
+ "kms:GenerateDataKey*",
111
+ "kms:Describe*"
112
+ ],
113
+ resources: ["*"],
114
+ conditions: {
115
+ ArnLike: {
116
+ "kms:EncryptionContext:aws:logs:arn": `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:*`
117
+ }
118
+ }
119
+ }));
94
120
  }
95
121
  /** The stack's shared key, created on first use. */
96
122
  static of(scope) {
@@ -114,36 +140,14 @@ export class StackEncryptionKey extends CustomerManagedKey {
114
140
  return onStackKey ? StackEncryptionKey.of(scope) : undefined;
115
141
  }
116
142
  /**
117
- * The key, with CloudWatch Logs admitted to it. The CDK `LogGroup` sets
118
- * `KmsKeyId` but adds no key-policy statement, and without one the
119
- * service cannot encrypt the group and the stack fails to create. The
120
- * encryption-context condition confines the admission to log groups in
121
- * this account and region (the AWS-documented shape).
143
+ * The key, for a log group's `encryptionKey`. CloudWatch Logs is already
144
+ * admitted by the constructor: the CDK `LogGroup` sets `KmsKeyId` but adds
145
+ * no key-policy statement, and without one the service cannot encrypt the
146
+ * group and the stack fails to create. The encryption-context condition
147
+ * confines the admission to log groups in this account and Region (the
148
+ * AWS-documented shape).
122
149
  */
123
150
  forLogGroups() {
124
- if (!this.logsAdmitted) {
125
- const stack = Stack.of(this);
126
- this.key.addToResourcePolicy(new PolicyStatement({
127
- sid: "AllowCloudWatchLogs",
128
- principals: [
129
- new ServicePrincipal(`logs.${stack.region}.amazonaws.com`)
130
- ],
131
- actions: [
132
- "kms:Encrypt*",
133
- "kms:Decrypt*",
134
- "kms:ReEncrypt*",
135
- "kms:GenerateDataKey*",
136
- "kms:Describe*"
137
- ],
138
- resources: ["*"],
139
- conditions: {
140
- ArnLike: {
141
- "kms:EncryptionContext:aws:logs:arn": `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:*`
142
- }
143
- }
144
- }));
145
- this.logsAdmitted = true;
146
- }
147
151
  return this.key;
148
152
  }
149
153
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/components-infrastructure",
3
- "version": "39.0.0",
3
+ "version": "39.0.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fjall-tech/fjall.git",
@@ -80,8 +80,8 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@aws-sdk/client-organizations": "^3.1098.0",
83
- "@fjall/generator": "^39.0.0",
84
- "@fjall/util": "^39.0.0",
83
+ "@fjall/generator": "^39.0.1",
84
+ "@fjall/util": "^39.0.1",
85
85
  "constructs": "^10.7.2",
86
86
  "zod": "^4.4.3"
87
87
  },