@fjall/components-infrastructure 33.1.0 → 35.0.0
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.
- package/dist/lib/app.js +2 -0
- package/dist/lib/config/aws/deployBoundarySingleton.d.ts +6 -0
- package/dist/lib/config/aws/deployBoundarySingleton.js +10 -2
- package/dist/lib/config/aws/identityCenter.js +2 -0
- package/dist/lib/config/aws/scpPreset.js +11 -1
- package/dist/lib/patterns/aws/bastionFactory.js +2 -1
- package/dist/lib/patterns/aws/cdn.d.ts +4 -1
- package/dist/lib/patterns/aws/clickhouseDatabase.js +2 -4
- package/dist/lib/patterns/aws/compute.d.ts +2 -2
- package/dist/lib/patterns/aws/computeEc2.d.ts +5 -18
- package/dist/lib/patterns/aws/computeEc2.js +9 -3
- package/dist/lib/patterns/aws/computeEcs.d.ts +4 -4
- package/dist/lib/patterns/aws/computeEcs.js +5 -9
- package/dist/lib/patterns/aws/computePropApplicability.js +1 -1
- package/dist/lib/patterns/aws/fivetranProxy.d.ts +8 -3
- package/dist/lib/patterns/aws/fivetranProxy.js +9 -6
- package/dist/lib/patterns/aws/interfaces/compute.d.ts +8 -0
- package/dist/lib/resources/aws/cdn/cloudFront.d.ts +16 -0
- package/dist/lib/resources/aws/cdn/cloudFront.js +52 -2
- package/dist/lib/resources/aws/compute/ec2.d.ts +33 -6
- package/dist/lib/resources/aws/compute/ec2.js +63 -14
- package/dist/lib/resources/aws/compute/ec2SshAccess.d.ts +80 -0
- package/dist/lib/resources/aws/compute/ec2SshAccess.js +166 -0
- package/dist/lib/resources/aws/compute/ecs.d.ts +11 -2
- package/dist/lib/resources/aws/compute/ecs.js +29 -6
- package/dist/lib/resources/aws/compute/lambda.d.ts +5 -0
- package/dist/lib/resources/aws/compute/lambda.js +9 -3
- package/dist/lib/resources/aws/database/dynamodb.js +5 -6
- package/dist/lib/resources/aws/iam/identityCenter/user.js +2 -0
- package/dist/lib/resources/aws/logging/accessLogBucket.d.ts +5 -3
- package/dist/lib/resources/aws/logging/accessLogBucket.js +6 -3
- package/dist/lib/resources/aws/messaging/sns.d.ts +17 -7
- package/dist/lib/resources/aws/messaging/sns.js +4 -4
- package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.js +3 -2
- package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +2 -1
- package/dist/lib/resources/aws/secrets/stackEncryptionKey.d.ts +17 -4
- package/dist/lib/resources/aws/secrets/stackEncryptionKey.js +20 -4
- package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +5 -0
- package/dist/lib/resources/aws/storage/bucketDeployment.js +7 -0
- package/dist/lib/resources/aws/storage/s3.d.ts +2 -1
- package/dist/lib/resources/aws/utilities/awsCustomResource.d.ts +9 -0
- package/dist/lib/resources/aws/utilities/awsCustomResource.js +16 -0
- package/dist/lib/resources/aws/utilities/customResource.js +2 -0
- package/dist/lib/resources/aws/utilities/customResourceProvider.d.ts +6 -0
- package/dist/lib/resources/aws/utilities/customResourceProvider.js +8 -0
- package/dist/lib/utils/deployTimeWriterMarkerAspect.d.ts +23 -0
- package/dist/lib/utils/deployTimeWriterMarkerAspect.js +35 -0
- package/dist/lib/utils/resourceTypeTags.d.ts +41 -0
- package/dist/lib/utils/resourceTypeTags.js +54 -0
- package/package.json +5 -4
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
2
|
import { CfnOutput } from "aws-cdk-lib";
|
|
3
3
|
import { Topic } from "aws-cdk-lib/aws-sns";
|
|
4
|
-
import { tierDefault } from "../../../utils/backupTierMapping.js";
|
|
5
4
|
import { StackEncryptionKey } from "../secrets/stackEncryptionKey.js";
|
|
6
5
|
import { toRemovalPolicy } from "./utils.js";
|
|
7
6
|
export class SNSTopic extends Construct {
|
|
@@ -11,10 +10,11 @@ export class SNSTopic extends Construct {
|
|
|
11
10
|
super(scope, id);
|
|
12
11
|
this.id = id;
|
|
13
12
|
const isFifo = props.fifo === true;
|
|
13
|
+
const encryptionOverride = props.encryption === undefined
|
|
14
|
+
? undefined
|
|
15
|
+
: props.encryption === "SSE_KMS";
|
|
14
16
|
const masterKey = props.masterKey ??
|
|
15
|
-
(
|
|
16
|
-
? StackEncryptionKey.of(this).forSnsServicePublishers()
|
|
17
|
-
: undefined);
|
|
17
|
+
StackEncryptionKey.forTier(this, props.appBackupTier, encryptionOverride)?.forSnsServicePublishers();
|
|
18
18
|
const topicName = props.topicName
|
|
19
19
|
? isFifo
|
|
20
20
|
? `${props.topicName}.fifo`
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
-
import { ArnFormat, Stack
|
|
2
|
+
import { ArnFormat, Stack } from "aws-cdk-lib";
|
|
3
3
|
import { AccountPrincipal, CompositePrincipal, PolicyDocument, PolicyStatement, Role } from "aws-cdk-lib/aws-iam";
|
|
4
4
|
import { applyCostAllocationTags } from "../../../utils/costAllocationTags.js";
|
|
5
|
+
import { applyResourceTypeTag, FJALL_RESOURCE_TYPES } from "../../../utils/resourceTypeTags.js";
|
|
5
6
|
export class VpcPeeringAccepterRole extends Construct {
|
|
6
7
|
role;
|
|
7
8
|
roleArn;
|
|
@@ -53,7 +54,7 @@ export class VpcPeeringAccepterRole extends Construct {
|
|
|
53
54
|
}
|
|
54
55
|
});
|
|
55
56
|
this.roleArn = this.role.roleArn;
|
|
56
|
-
|
|
57
|
+
applyResourceTypeTag(this, FJALL_RESOURCE_TYPES.vpcPeeringAccepter);
|
|
57
58
|
applyCostAllocationTags(this, {
|
|
58
59
|
service: "vpcPeeringAccepter",
|
|
59
60
|
domain: props.costAllocationDomain ?? props.localVpc.node.id,
|
|
@@ -4,6 +4,7 @@ import { CfnRoute, CfnVPCPeeringConnection, SubnetType } from "aws-cdk-lib/aws-e
|
|
|
4
4
|
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
5
5
|
import { AwsCustomResourcePolicy, PhysicalResourceId } from "aws-cdk-lib/custom-resources";
|
|
6
6
|
import { applyCostAllocationTags } from "../../../utils/costAllocationTags.js";
|
|
7
|
+
import { applyResourceTypeTag, FJALL_RESOURCE_TYPES } from "../../../utils/resourceTypeTags.js";
|
|
7
8
|
import { AwsCustomResource } from "../utilities/awsCustomResource.js";
|
|
8
9
|
import { CrossAccountReturnRoutes } from "./crossAccountReturnRoutes.js";
|
|
9
10
|
export class VpcPeeringConnection extends Construct {
|
|
@@ -92,7 +93,7 @@ export class VpcPeeringConnection extends Construct {
|
|
|
92
93
|
enableDns: enableDnsResolution
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
+
applyResourceTypeTag(this, FJALL_RESOURCE_TYPES.vpcPeering);
|
|
96
97
|
Tags.of(this).add("fjall:peering:peer-vpc", props.peerVpcId);
|
|
97
98
|
if (props.peerAccountId) {
|
|
98
99
|
Tags.of(this).add("fjall:peering:peer-account", props.peerAccountId);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IKey } from "aws-cdk-lib/aws-kms";
|
|
2
2
|
import type { Construct } from "constructs";
|
|
3
|
+
import { type BackupTier } from "../../../utils/backupTierMapping.js";
|
|
3
4
|
import { CustomerManagedKey } from "./kms.js";
|
|
4
5
|
/**
|
|
5
6
|
* The one customer-managed KMS key an enterprise-tier stack encrypts its
|
|
@@ -16,10 +17,12 @@ import { CustomerManagedKey } from "./kms.js";
|
|
|
16
17
|
* costs $1–3/month; a destroyed key would render the surviving table
|
|
17
18
|
* permanently unreadable after its 30-day pending window.
|
|
18
19
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Constructs reach it through [[forTier]] — the one place the tier's
|
|
21
|
+
* `customerManagedKeys` column is read. Grant-based consumers (DynamoDB,
|
|
22
|
+
* Lambda `environmentEncryption`, ECS Exec) then read `key` directly — the
|
|
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
|
|
23
26
|
* [[forSnsServicePublishers]]. Each admission is added once per stack.
|
|
24
27
|
*/
|
|
25
28
|
export declare class StackEncryptionKey extends CustomerManagedKey {
|
|
@@ -28,6 +31,16 @@ export declare class StackEncryptionKey extends CustomerManagedKey {
|
|
|
28
31
|
private constructor();
|
|
29
32
|
/** The stack's shared key, created on first use. */
|
|
30
33
|
static of(scope: Construct): StackEncryptionKey;
|
|
34
|
+
/**
|
|
35
|
+
* The stack's shared key when the tier's `customerManagedKeys` column says
|
|
36
|
+
* so, else `undefined` — the one place the column is read. A resource with
|
|
37
|
+
* its own encryption vocabulary (DynamoDB `encryption`, SNS `encryption`)
|
|
38
|
+
* passes the explicit choice as `override`; `undefined` lets the tier
|
|
39
|
+
* decide. The key is only created when the answer is yes, so an opt-out at
|
|
40
|
+
* enterprise mints nothing and an opt-in below enterprise mints the shared
|
|
41
|
+
* key rather than a per-resource one.
|
|
42
|
+
*/
|
|
43
|
+
static forTier(scope: Construct, tier: BackupTier | undefined, override?: boolean): StackEncryptionKey | undefined;
|
|
31
44
|
/**
|
|
32
45
|
* The key, with CloudWatch Logs admitted to it. The CDK `LogGroup` sets
|
|
33
46
|
* `KmsKeyId` but adds no key-policy statement, and without one the
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Stack } from "aws-cdk-lib";
|
|
2
2
|
import { PolicyStatement, ServicePrincipal } from "aws-cdk-lib/aws-iam";
|
|
3
|
+
import { tierDefault } from "../../../utils/backupTierMapping.js";
|
|
3
4
|
import { CustomerManagedKey } from "./kms.js";
|
|
4
5
|
const STACK_ENCRYPTION_KEY_ID = "FjallStackEncryptionKey";
|
|
5
6
|
/**
|
|
@@ -33,10 +34,12 @@ const SNS_SERVICE_PUBLISHERS = [
|
|
|
33
34
|
* costs $1–3/month; a destroyed key would render the surviving table
|
|
34
35
|
* permanently unreadable after its 30-day pending window.
|
|
35
36
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* Constructs reach it through [[forTier]] — the one place the tier's
|
|
38
|
+
* `customerManagedKeys` column is read. Grant-based consumers (DynamoDB,
|
|
39
|
+
* Lambda `environmentEncryption`, ECS Exec) then read `key` directly — the
|
|
40
|
+
* SDK/CDK grants they need ride the resource's own IAM path. Service-side
|
|
41
|
+
* encryptors need a resource-policy admission first: CloudWatch Logs through
|
|
42
|
+
* [[forLogGroups]], SNS service publishers through
|
|
40
43
|
* [[forSnsServicePublishers]]. Each admission is added once per stack.
|
|
41
44
|
*/
|
|
42
45
|
export class StackEncryptionKey extends CustomerManagedKey {
|
|
@@ -59,6 +62,19 @@ export class StackEncryptionKey extends CustomerManagedKey {
|
|
|
59
62
|
return existing;
|
|
60
63
|
return new StackEncryptionKey(stack);
|
|
61
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The stack's shared key when the tier's `customerManagedKeys` column says
|
|
67
|
+
* so, else `undefined` — the one place the column is read. A resource with
|
|
68
|
+
* its own encryption vocabulary (DynamoDB `encryption`, SNS `encryption`)
|
|
69
|
+
* passes the explicit choice as `override`; `undefined` lets the tier
|
|
70
|
+
* decide. The key is only created when the answer is yes, so an opt-out at
|
|
71
|
+
* enterprise mints nothing and an opt-in below enterprise mints the shared
|
|
72
|
+
* key rather than a per-resource one.
|
|
73
|
+
*/
|
|
74
|
+
static forTier(scope, tier, override) {
|
|
75
|
+
const onStackKey = override ?? tierDefault(tier, "customerManagedKeys");
|
|
76
|
+
return onStackKey ? StackEncryptionKey.of(scope) : undefined;
|
|
77
|
+
}
|
|
62
78
|
/**
|
|
63
79
|
* The key, with CloudWatch Logs admitted to it. The CDK `LogGroup` sets
|
|
64
80
|
* `KmsKeyId` but adds no key-policy statement, and without one the
|
|
@@ -8,6 +8,11 @@ import { type Construct } from "constructs";
|
|
|
8
8
|
* service-auto-created. Per the Wrapper Routing Discipline rule (generator
|
|
9
9
|
* standards) and the infrastructure wrapper-routing pattern (§ A3), `lib/{config,
|
|
10
10
|
* patterns}/` MUST instantiate this class rather than the raw CDK construct.
|
|
11
|
+
*
|
|
12
|
+
* The handler is a deploy-time writer: aws-cdk-lib hoists its function and
|
|
13
|
+
* execution role to the stack scope under an id that embeds a per-variant
|
|
14
|
+
* uuid (memory, VPC, ephemeral storage), so the role is marked through the
|
|
15
|
+
* public `handlerRole` seam rather than by construct id.
|
|
11
16
|
*/
|
|
12
17
|
export declare class BucketDeployment extends CdkBucketDeployment {
|
|
13
18
|
constructor(scope: Construct, id: string, props: BucketDeploymentProps);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BucketDeployment as CdkBucketDeployment } from "aws-cdk-lib/aws-s3-deployment";
|
|
2
|
+
import { markDeployTimeWriter } from "../../../utils/resourceTypeTags.js";
|
|
2
3
|
import { stackSingletonLogGroup } from "../logging/singletonLogGroup.js";
|
|
3
4
|
/**
|
|
4
5
|
* Routing-point wrapper for `aws-cdk-lib/aws-s3-deployment.BucketDeployment`.
|
|
@@ -8,6 +9,11 @@ import { stackSingletonLogGroup } from "../logging/singletonLogGroup.js";
|
|
|
8
9
|
* service-auto-created. Per the Wrapper Routing Discipline rule (generator
|
|
9
10
|
* standards) and the infrastructure wrapper-routing pattern (§ A3), `lib/{config,
|
|
10
11
|
* patterns}/` MUST instantiate this class rather than the raw CDK construct.
|
|
12
|
+
*
|
|
13
|
+
* The handler is a deploy-time writer: aws-cdk-lib hoists its function and
|
|
14
|
+
* execution role to the stack scope under an id that embeds a per-variant
|
|
15
|
+
* uuid (memory, VPC, ephemeral storage), so the role is marked through the
|
|
16
|
+
* public `handlerRole` seam rather than by construct id.
|
|
11
17
|
*/
|
|
12
18
|
export class BucketDeployment extends CdkBucketDeployment {
|
|
13
19
|
constructor(scope, id, props) {
|
|
@@ -19,5 +25,6 @@ export class BucketDeployment extends CdkBucketDeployment {
|
|
|
19
25
|
// site instantiates first.
|
|
20
26
|
logGroup: props.logGroup ?? stackSingletonLogGroup(scope, "BucketDeployment")
|
|
21
27
|
});
|
|
28
|
+
markDeployTimeWriter(this.handlerRole);
|
|
22
29
|
}
|
|
23
30
|
}
|
|
@@ -68,7 +68,8 @@ export interface S3BucketProps extends BucketProps {
|
|
|
68
68
|
* `S3_VERSIONING_DISABLED` finding `mitigated` rather than `open` on
|
|
69
69
|
* buckets whose contents are rebuilt, not kept. Constructs pass it for the
|
|
70
70
|
* buckets they own (Payload build output and ISR cache, ClickHouse cold
|
|
71
|
-
* tier); an author may pass it for a
|
|
71
|
+
* tier, the stack access-log bucket); an author may pass it for a
|
|
72
|
+
* disposable bucket of their own.
|
|
72
73
|
*/
|
|
73
74
|
versioningExemption?: S3VersioningExemption;
|
|
74
75
|
publicReadAccess?: boolean;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import * as customResource from "aws-cdk-lib/custom-resources";
|
|
2
2
|
import { type Construct } from "constructs";
|
|
3
|
+
/**
|
|
4
|
+
* The stack-scope construct id under which aws-cdk-lib hoists the one
|
|
5
|
+
* `AwsCustomResource` provider every site in a stack shares: the singleton's
|
|
6
|
+
* `lambdaPurpose` ("AWS") followed by its uuid with the hyphens stripped —
|
|
7
|
+
* `SingletonFunction.constructName`'s derivation, from the public
|
|
8
|
+
* `PROVIDER_FUNCTION_UUID`. Test fixtures address the hoisted function and
|
|
9
|
+
* its execution role by this prefix.
|
|
10
|
+
*/
|
|
11
|
+
export declare const AWS_CUSTOM_RESOURCE_PROVIDER_ID: string;
|
|
3
12
|
export declare class AwsCustomResource extends customResource.AwsCustomResource {
|
|
4
13
|
readonly response: string;
|
|
5
14
|
constructor(scope: Construct, id: string, props: customResource.AwsCustomResourceProps);
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { Stack } from "aws-cdk-lib";
|
|
1
2
|
import * as customResource from "aws-cdk-lib/custom-resources";
|
|
3
|
+
import { markDeployTimeWriter } from "../../../utils/resourceTypeTags.js";
|
|
2
4
|
import { stackSingletonLogGroup } from "../logging/singletonLogGroup.js";
|
|
5
|
+
/**
|
|
6
|
+
* The stack-scope construct id under which aws-cdk-lib hoists the one
|
|
7
|
+
* `AwsCustomResource` provider every site in a stack shares: the singleton's
|
|
8
|
+
* `lambdaPurpose` ("AWS") followed by its uuid with the hyphens stripped —
|
|
9
|
+
* `SingletonFunction.constructName`'s derivation, from the public
|
|
10
|
+
* `PROVIDER_FUNCTION_UUID`. Test fixtures address the hoisted function and
|
|
11
|
+
* its execution role by this prefix.
|
|
12
|
+
*/
|
|
13
|
+
export const AWS_CUSTOM_RESOURCE_PROVIDER_ID = `AWS${customResource.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
3
14
|
export class AwsCustomResource extends customResource.AwsCustomResource {
|
|
4
15
|
response;
|
|
5
16
|
constructor(scope, id, props) {
|
|
@@ -14,5 +25,10 @@ export class AwsCustomResource extends customResource.AwsCustomResource {
|
|
|
14
25
|
resources: customResource.AwsCustomResourcePolicy.ANY_RESOURCE
|
|
15
26
|
})
|
|
16
27
|
});
|
|
28
|
+
// aws-cdk-lib hoists the shared provider — and, unless the site passed
|
|
29
|
+
// `role`, its execution role — to the stack scope, out of reach of any
|
|
30
|
+
// tag on this construct. `findChild` throws if the hoist ever moves, so a
|
|
31
|
+
// CDK upgrade that would silently un-mark the role fails at synth.
|
|
32
|
+
markDeployTimeWriter(Stack.of(this).node.findChild(AWS_CUSTOM_RESOURCE_PROVIDER_ID));
|
|
17
33
|
}
|
|
18
34
|
}
|
|
@@ -5,6 +5,7 @@ import { Construct } from "constructs";
|
|
|
5
5
|
import { SingletonFunction, LambdaFunction } from "../compute/lambda.js";
|
|
6
6
|
import { DEFAULT_CUSTOM_RESOURCE_TIMEOUT_SECONDS } from "../compute/ecsConstants.js";
|
|
7
7
|
import { DEFAULT_FRAMEWORK_LOG_RETENTION, LogGroup } from "../logging/logGroup.js";
|
|
8
|
+
import { markDeployTimeWriter } from "../../../utils/resourceTypeTags.js";
|
|
8
9
|
export class CustomResource extends Construct {
|
|
9
10
|
response;
|
|
10
11
|
resource;
|
|
@@ -71,5 +72,6 @@ export class CustomResource extends Construct {
|
|
|
71
72
|
})
|
|
72
73
|
});
|
|
73
74
|
this.response = this.resource.getAtt("Response").toString();
|
|
75
|
+
markDeployTimeWriter(this);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Provider, type ProviderProps } from "aws-cdk-lib/custom-resources";
|
|
2
2
|
import { type Construct } from "constructs";
|
|
3
|
+
/**
|
|
4
|
+
* Routing-point wrapper for the custom-resource provider framework. The
|
|
5
|
+
* framework's onEvent/isComplete functions and their roles are deploy-time
|
|
6
|
+
* writers; the caller's own handler (`props.onEventHandler`) lives outside
|
|
7
|
+
* this scope and is the caller's to mark.
|
|
8
|
+
*/
|
|
3
9
|
export declare class CustomResourceProvider extends Provider {
|
|
4
10
|
constructor(scope: Construct, id: string, props: ProviderProps);
|
|
5
11
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Provider } from "aws-cdk-lib/custom-resources";
|
|
2
|
+
import { markDeployTimeWriter } from "../../../utils/resourceTypeTags.js";
|
|
3
|
+
/**
|
|
4
|
+
* Routing-point wrapper for the custom-resource provider framework. The
|
|
5
|
+
* framework's onEvent/isComplete functions and their roles are deploy-time
|
|
6
|
+
* writers; the caller's own handler (`props.onEventHandler`) lives outside
|
|
7
|
+
* this scope and is the caller's to mark.
|
|
8
|
+
*/
|
|
2
9
|
export class CustomResourceProvider extends Provider {
|
|
3
10
|
constructor(scope, id, props) {
|
|
4
11
|
super(scope, id, props);
|
|
12
|
+
markDeployTimeWriter(this);
|
|
5
13
|
}
|
|
6
14
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type IAspect } from "aws-cdk-lib";
|
|
2
|
+
import type { IConstruct } from "constructs";
|
|
3
|
+
/**
|
|
4
|
+
* Marks the execution roles aws-cdk-lib's lightweight custom-resource
|
|
5
|
+
* provider framework (`CustomResourceProviderBase`) renders as raw
|
|
6
|
+
* `AWS::IAM::Role` CfnResources: `Custom::VpcRestrictDefaultSG` under the
|
|
7
|
+
* `@aws-cdk/aws-ec2:restrictDefaultSecurityGroup` flag every scaffolded
|
|
8
|
+
* `cdk.json` sets, `Custom::CrossAccountZoneDelegation`, and whichever the
|
|
9
|
+
* next CDK release adds. Those roles have no tag manager, so `Tags.of()` —
|
|
10
|
+
* the wrappers' mechanism — never reaches them; this aspect writes the marker
|
|
11
|
+
* as a property override instead. Registered once per `App`, so every stack
|
|
12
|
+
* gets it without a per-construct site to forget.
|
|
13
|
+
*
|
|
14
|
+
* Recognised structurally, not by construct id: a `Role` CfnResource whose
|
|
15
|
+
* parent exposes the framework's `serviceToken` + `roleArn` pair. Prototype
|
|
16
|
+
* probing rather than `instanceof`, for the duplicate-aws-cdk-lib reason
|
|
17
|
+
* `logGroupHygiene` records. The full `Provider` framework exposes no
|
|
18
|
+
* `roleArn` and builds L2 roles, so it is not matched here — its wrappers tag
|
|
19
|
+
* it directly.
|
|
20
|
+
*/
|
|
21
|
+
export declare class DeployTimeWriterMarkerAspect implements IAspect {
|
|
22
|
+
visit(node: IConstruct): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CfnResource } from "aws-cdk-lib";
|
|
2
|
+
import { markDeployTimeWriterCfn } from "./resourceTypeTags.js";
|
|
3
|
+
/**
|
|
4
|
+
* Marks the execution roles aws-cdk-lib's lightweight custom-resource
|
|
5
|
+
* provider framework (`CustomResourceProviderBase`) renders as raw
|
|
6
|
+
* `AWS::IAM::Role` CfnResources: `Custom::VpcRestrictDefaultSG` under the
|
|
7
|
+
* `@aws-cdk/aws-ec2:restrictDefaultSecurityGroup` flag every scaffolded
|
|
8
|
+
* `cdk.json` sets, `Custom::CrossAccountZoneDelegation`, and whichever the
|
|
9
|
+
* next CDK release adds. Those roles have no tag manager, so `Tags.of()` —
|
|
10
|
+
* the wrappers' mechanism — never reaches them; this aspect writes the marker
|
|
11
|
+
* as a property override instead. Registered once per `App`, so every stack
|
|
12
|
+
* gets it without a per-construct site to forget.
|
|
13
|
+
*
|
|
14
|
+
* Recognised structurally, not by construct id: a `Role` CfnResource whose
|
|
15
|
+
* parent exposes the framework's `serviceToken` + `roleArn` pair. Prototype
|
|
16
|
+
* probing rather than `instanceof`, for the duplicate-aws-cdk-lib reason
|
|
17
|
+
* `logGroupHygiene` records. The full `Provider` framework exposes no
|
|
18
|
+
* `roleArn` and builds L2 roles, so it is not matched here — its wrappers tag
|
|
19
|
+
* it directly.
|
|
20
|
+
*/
|
|
21
|
+
export class DeployTimeWriterMarkerAspect {
|
|
22
|
+
visit(node) {
|
|
23
|
+
if (!CfnResource.isCfnResource(node) ||
|
|
24
|
+
node.cfnResourceType !== "AWS::IAM::Role") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const parent = node.node.scope;
|
|
28
|
+
if (parent === undefined || !isLightweightProvider(parent))
|
|
29
|
+
return;
|
|
30
|
+
markDeployTimeWriterCfn(node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function isLightweightProvider(construct) {
|
|
34
|
+
return "serviceToken" in construct && "roleArn" in construct;
|
|
35
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FJALL_RESOURCE_TYPE_TAG_KEY, FJALL_RESOURCE_TYPES, type FjallResourceType } from "@fjall/util/aws";
|
|
2
|
+
import { type CfnResource } from "aws-cdk-lib";
|
|
3
|
+
import type { IConstruct } from "constructs";
|
|
4
|
+
export { FJALL_RESOURCE_TYPE_TAG_KEY, FJALL_RESOURCE_TYPES, type FjallResourceType };
|
|
5
|
+
/**
|
|
6
|
+
* Stamp the `fjall:resource:type` marker on a construct subtree. The marker
|
|
7
|
+
* answers "what IS this resource" for resources whose physical name is
|
|
8
|
+
* CloudFormation-generated, so a consumer never has to pattern-match a name.
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyResourceTypeTag(scope: IConstruct, resourceType: FjallResourceType): void;
|
|
11
|
+
/**
|
|
12
|
+
* Mark a deploy-time-only writer subtree — the execution role CloudFormation
|
|
13
|
+
* assumes while driving a custom resource, plus the handler, the provider
|
|
14
|
+
* framework function and their log groups.
|
|
15
|
+
*
|
|
16
|
+
* Every writer producer in the library routes through one of two mechanisms,
|
|
17
|
+
* nothing stamping the key by hand:
|
|
18
|
+
*
|
|
19
|
+
* - this helper, called by each wrapper that constructs a writer: the shared
|
|
20
|
+
* `CustomResource` utility and the `CustomResourceProvider` wrapper (their
|
|
21
|
+
* own subtree), the `SingletonFunction`, `AwsCustomResource` and
|
|
22
|
+
* `BucketDeployment` wrappers (the function and role aws-cdk-lib hoists to
|
|
23
|
+
* the stack scope, out of reach of any tag on the wrapper itself), the
|
|
24
|
+
* identity-store user provider, and the Identity Centre ListInstances role;
|
|
25
|
+
* - `DeployTimeWriterMarkerAspect` (registered by `App`), for the execution
|
|
26
|
+
* roles aws-cdk-lib's lightweight provider framework renders as raw
|
|
27
|
+
* CfnResources — `Tags.of()` cannot reach those, so the marker goes on as a
|
|
28
|
+
* property override via `markDeployTimeWriterCfn`.
|
|
29
|
+
*
|
|
30
|
+
* The producer set is enumerated from source by
|
|
31
|
+
* `__tests__/deployTimeWriterCensus.test.ts`: a new construction of a CDK
|
|
32
|
+
* writer class fails that test until it names the mechanism that marks it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function markDeployTimeWriter(scope: IConstruct): void;
|
|
35
|
+
/**
|
|
36
|
+
* The raw-CfnResource twin of `markDeployTimeWriter`, for a role the
|
|
37
|
+
* lightweight `CustomResourceProviderBase` framework renders without a tag
|
|
38
|
+
* manager: the marker is written straight into the resource's `Tags`
|
|
39
|
+
* property. Called only by `DeployTimeWriterMarkerAspect`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function markDeployTimeWriterCfn(role: CfnResource): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { FJALL_RESOURCE_TYPE_TAG_KEY, FJALL_RESOURCE_TYPES } from "@fjall/util/aws";
|
|
2
|
+
import { Tags } from "aws-cdk-lib";
|
|
3
|
+
// Canonical home: @fjall/util (`util/src/aws/infraTags.ts`) — shared with the
|
|
4
|
+
// Quick-Create template's hand-written twin and the webapp posture exclusion.
|
|
5
|
+
// Re-exported here so construct-package consumers keep one import path.
|
|
6
|
+
export { FJALL_RESOURCE_TYPE_TAG_KEY, FJALL_RESOURCE_TYPES };
|
|
7
|
+
/**
|
|
8
|
+
* Stamp the `fjall:resource:type` marker on a construct subtree. The marker
|
|
9
|
+
* answers "what IS this resource" for resources whose physical name is
|
|
10
|
+
* CloudFormation-generated, so a consumer never has to pattern-match a name.
|
|
11
|
+
*/
|
|
12
|
+
export function applyResourceTypeTag(scope, resourceType) {
|
|
13
|
+
Tags.of(scope).add(FJALL_RESOURCE_TYPE_TAG_KEY, resourceType);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Mark a deploy-time-only writer subtree — the execution role CloudFormation
|
|
17
|
+
* assumes while driving a custom resource, plus the handler, the provider
|
|
18
|
+
* framework function and their log groups.
|
|
19
|
+
*
|
|
20
|
+
* Every writer producer in the library routes through one of two mechanisms,
|
|
21
|
+
* nothing stamping the key by hand:
|
|
22
|
+
*
|
|
23
|
+
* - this helper, called by each wrapper that constructs a writer: the shared
|
|
24
|
+
* `CustomResource` utility and the `CustomResourceProvider` wrapper (their
|
|
25
|
+
* own subtree), the `SingletonFunction`, `AwsCustomResource` and
|
|
26
|
+
* `BucketDeployment` wrappers (the function and role aws-cdk-lib hoists to
|
|
27
|
+
* the stack scope, out of reach of any tag on the wrapper itself), the
|
|
28
|
+
* identity-store user provider, and the Identity Centre ListInstances role;
|
|
29
|
+
* - `DeployTimeWriterMarkerAspect` (registered by `App`), for the execution
|
|
30
|
+
* roles aws-cdk-lib's lightweight provider framework renders as raw
|
|
31
|
+
* CfnResources — `Tags.of()` cannot reach those, so the marker goes on as a
|
|
32
|
+
* property override via `markDeployTimeWriterCfn`.
|
|
33
|
+
*
|
|
34
|
+
* The producer set is enumerated from source by
|
|
35
|
+
* `__tests__/deployTimeWriterCensus.test.ts`: a new construction of a CDK
|
|
36
|
+
* writer class fails that test until it names the mechanism that marks it.
|
|
37
|
+
*/
|
|
38
|
+
export function markDeployTimeWriter(scope) {
|
|
39
|
+
applyResourceTypeTag(scope, FJALL_RESOURCE_TYPES.deployTimeWriter);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The raw-CfnResource twin of `markDeployTimeWriter`, for a role the
|
|
43
|
+
* lightweight `CustomResourceProviderBase` framework renders without a tag
|
|
44
|
+
* manager: the marker is written straight into the resource's `Tags`
|
|
45
|
+
* property. Called only by `DeployTimeWriterMarkerAspect`.
|
|
46
|
+
*/
|
|
47
|
+
export function markDeployTimeWriterCfn(role) {
|
|
48
|
+
role.addPropertyOverride("Tags", [
|
|
49
|
+
{
|
|
50
|
+
Key: FJALL_RESOURCE_TYPE_TAG_KEY,
|
|
51
|
+
Value: FJALL_RESOURCE_TYPES.deployTimeWriter
|
|
52
|
+
}
|
|
53
|
+
]);
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/components-infrastructure",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "35.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"clean": "rm -rf ./dist",
|
|
40
40
|
"clean:node": "rm -rf ./node_modules",
|
|
41
41
|
"build:cert-gen-lambda": "node lib/lambda-assets/cert-generator/src/build.mjs",
|
|
42
|
-
"build": "
|
|
42
|
+
"build": "node ../../scripts/run-build.mjs --purpose=build -- npm run build:steps",
|
|
43
|
+
"build:steps": "npm run clean && npm run build:cert-gen-lambda && tsc && cp -r lib/layers dist/lib/layers && mkdir -p dist/lib/lambda-assets/cert-generator/asset && cp lib/lambda-assets/cert-generator/asset/index.js dist/lib/lambda-assets/cert-generator/asset/index.js && cp lib/lambda-assets/cert-generator/asset/package.json dist/lib/lambda-assets/cert-generator/asset/package.json && mkdir -p dist/lib/lambda-assets/identity-store-user/asset && cp lib/lambda-assets/identity-store-user/asset/index.js dist/lib/lambda-assets/identity-store-user/asset/index.js && cp lib/lambda-assets/identity-store-user/asset/package.json dist/lib/lambda-assets/identity-store-user/asset/package.json && mkdir -p dist/lib/lambda-assets/static-site-forms/asset && cp lib/lambda-assets/static-site-forms/asset/index.js dist/lib/lambda-assets/static-site-forms/asset/index.js && cp lib/lambda-assets/static-site-forms/asset/package.json dist/lib/lambda-assets/static-site-forms/asset/package.json && cp lib/resources/aws/compute/lifecycleHookLambda.source.cjs dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs && cp lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs && cp lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs && cp lib/patterns/aws/devSubstrate.waker.source.cjs dist/lib/patterns/aws/devSubstrate.waker.source.cjs && node ../../scripts/stamp-build.mjs",
|
|
43
44
|
"prepack": "node ../../scripts/check-dist-freshness.mjs",
|
|
44
45
|
"prepublishOnly": "node ../../scripts/audit-package-tarball.mjs",
|
|
45
46
|
"watch": "tsc -w",
|
|
@@ -79,8 +80,8 @@
|
|
|
79
80
|
},
|
|
80
81
|
"dependencies": {
|
|
81
82
|
"@aws-sdk/client-organizations": "^3.1098.0",
|
|
82
|
-
"@fjall/generator": "^
|
|
83
|
-
"@fjall/util": "^
|
|
83
|
+
"@fjall/generator": "^35.0.0",
|
|
84
|
+
"@fjall/util": "^35.0.0",
|
|
84
85
|
"constructs": "^10.7.2",
|
|
85
86
|
"zod": "^4.4.3"
|
|
86
87
|
},
|