@intentius/chant-lexicon-aws 0.33.1 → 0.34.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.
@@ -0,0 +1,323 @@
1
+ /**
2
+ * What an AWS estate depends on but does not declare (#1273).
3
+ *
4
+ * `describeResources` is scoped to the stack. An instance placed in the
5
+ * account's default VPC routes through a route table nobody declared, so that
6
+ * table is never observed, never a node, and no fold can traverse to it. The
7
+ * answer used to be computed inside the lexicon and injected as an attribute —
8
+ * which is a conclusion no snapshot can record enough to recompute.
9
+ *
10
+ * This reports the resources instead, so the one graph fold derives the answer.
11
+ *
12
+ * The closure is bounded: start from the observed instances, follow the
13
+ * reference chain the catalog declares as meaningful — subnet, then route
14
+ * table, then gateway — and stop. Anything not reached from a declared resource
15
+ * along a declared reference is not a dependency, it is just the account.
16
+ */
17
+
18
+ import { applyAwsEndpointArgv } from "./components/cloud-executor";
19
+ import type { DependencyObservation, ResourceMetadata, IREdge } from "@intentius/chant/lexicon";
20
+
21
+ /** Cloud-shaped ids are stable across a redeploy and unique per account. */
22
+ const nodeId = (physicalId: string): string => physicalId;
23
+
24
+ /** One ingress permission as `describe-security-groups` returns it. */
25
+ interface RawIpPermission {
26
+ IpProtocol?: string;
27
+ FromPort?: number;
28
+ ToPort?: number;
29
+ IpRanges?: Array<{ CidrIp?: string }>;
30
+ Ipv6Ranges?: Array<{ CidrIpv6?: string }>;
31
+ UserIdGroupPairs?: Array<{ GroupId?: string }>;
32
+ }
33
+
34
+ /**
35
+ * Flatten `IpPermissions` into the CloudFormation-shaped rules the fold reads.
36
+ *
37
+ * The two AWS surfaces disagree about the same concept: a template's
38
+ * `SecurityGroupIngress` carries `CidrIp` flat on the rule, while
39
+ * `describe-security-groups` nests sources under `IpRanges[]`, `Ipv6Ranges[]`
40
+ * and `UserIdGroupPairs[]`, and one permission can hold several. Handing the
41
+ * describe shape to the fold unchanged yields a rule with no recognisable
42
+ * source, which `normalizeIngress` renders as `?` — an ingress rule that
43
+ * matches no CIDR query and quietly narrows the answer.
44
+ *
45
+ * One rule per source, because that is what the flat shape means.
46
+ */
47
+ export function toIngressRules(permissions: RawIpPermission[]): Array<Record<string, unknown>> {
48
+ const rules: Array<Record<string, unknown>> = [];
49
+ for (const permission of permissions) {
50
+ const base = {
51
+ IpProtocol: permission.IpProtocol ?? "-1",
52
+ ...(permission.FromPort != null ? { FromPort: permission.FromPort } : {}),
53
+ ...(permission.ToPort != null ? { ToPort: permission.ToPort } : {}),
54
+ };
55
+ for (const range of permission.IpRanges ?? []) {
56
+ if (range.CidrIp) rules.push({ ...base, CidrIp: range.CidrIp });
57
+ }
58
+ for (const range of permission.Ipv6Ranges ?? []) {
59
+ if (range.CidrIpv6) rules.push({ ...base, CidrIpv6: range.CidrIpv6 });
60
+ }
61
+ for (const pair of permission.UserIdGroupPairs ?? []) {
62
+ if (pair.GroupId) rules.push({ ...base, SourceSecurityGroupId: pair.GroupId });
63
+ }
64
+ }
65
+ return rules;
66
+ }
67
+
68
+ interface RawRouteTable {
69
+ RouteTableId?: string;
70
+ VpcId?: string;
71
+ Routes?: Array<{ GatewayId?: string; DestinationCidrBlock?: string }>;
72
+ Associations?: Array<{ SubnetId?: string; Main?: boolean }>;
73
+ }
74
+
75
+ /**
76
+ * Read the routing an observed estate depends on.
77
+ *
78
+ * Only the tables that actually serve an observed instance are reported: one
79
+ * reached by an explicit subnet association, or the VPC's main table standing in
80
+ * for a subnet with none. A route table serving nothing chant deployed is not a
81
+ * dependency of this estate.
82
+ */
83
+ export async function observeAwsDependencies(options: {
84
+ observed: Record<string, ResourceMetadata>;
85
+ region?: string;
86
+ }): Promise<DependencyObservation> {
87
+ const { getRuntime } = await import("@intentius/chant/runtime-adapter");
88
+ const rt = getRuntime();
89
+ const regionArgs = options.region ? ["--region", options.region] : [];
90
+ const run = (args: string[]) =>
91
+ rt.spawn(applyAwsEndpointArgv(["aws", ...args, ...regionArgs, "--output", "json"], process.env.AWS_ENDPOINT_URL));
92
+
93
+ const resources: Record<string, ResourceMetadata> = {};
94
+ const edges: IREdge[] = [];
95
+
96
+ // Roots: the instances this estate manages, and where each one sits. Placement
97
+ // comes from the live API rather than the template, because the declared side
98
+ // may only carry a parameter reference to a subnet it never modelled.
99
+ const instances = Object.entries(options.observed).filter(
100
+ ([, meta]) => meta.type === "AWS::EC2::Instance" && meta.physicalId,
101
+ );
102
+ if (instances.length === 0) return { resources: {}, edges: [] };
103
+
104
+ try {
105
+ const described = await run([
106
+ "ec2",
107
+ "describe-instances",
108
+ "--instance-ids",
109
+ ...instances.map(([, meta]) => meta.physicalId as string),
110
+ ]);
111
+ if (described.exitCode !== 0) return { resources: {}, edges: [] };
112
+
113
+ const placement = new Map<
114
+ string,
115
+ { subnetId?: string; vpcId?: string; securityGroupIds: string[]; launchTemplateId?: string }
116
+ >();
117
+ for (const reservation of (JSON.parse(described.stdout).Reservations ?? []) as Array<{
118
+ Instances?: Array<{
119
+ InstanceId: string;
120
+ SubnetId?: string;
121
+ VpcId?: string;
122
+ SecurityGroups?: Array<{ GroupId?: string }>;
123
+ LaunchTemplate?: { LaunchTemplateId?: string };
124
+ }>;
125
+ }>) {
126
+ for (const instance of reservation.Instances ?? []) {
127
+ placement.set(instance.InstanceId, {
128
+ subnetId: instance.SubnetId,
129
+ vpcId: instance.VpcId,
130
+ securityGroupIds: (instance.SecurityGroups ?? [])
131
+ .map((g) => g.GroupId)
132
+ .filter((id): id is string => typeof id === "string"),
133
+ ...(instance.LaunchTemplate?.LaunchTemplateId
134
+ ? { launchTemplateId: instance.LaunchTemplate.LaunchTemplateId }
135
+ : {}),
136
+ });
137
+ }
138
+ }
139
+
140
+ const tablesResult = await run(["ec2", "describe-route-tables"]);
141
+ if (tablesResult.exitCode !== 0) return { resources: {}, edges: [] };
142
+ const tables = (JSON.parse(tablesResult.stdout).RouteTables ?? []) as RawRouteTable[];
143
+
144
+ // Which table serves which subnet, and which is a VPC's main table — the
145
+ // two ways an instance's subnet resolves to routing.
146
+ const bySubnet = new Map<string, RawRouteTable>();
147
+ const mainByVpc = new Map<string, RawRouteTable>();
148
+ for (const table of tables) {
149
+ for (const association of table.Associations ?? []) {
150
+ if (association.SubnetId) bySubnet.set(association.SubnetId, table);
151
+ if (association.Main && table.VpcId) mainByVpc.set(table.VpcId, table);
152
+ }
153
+ }
154
+
155
+ // Security groups and launch templates the estate is guarded by (#1276).
156
+ // `effectiveIngress` resolved these from the declared graph alone, which is
157
+ // right until an instance sits in a group it did not declare — a shared
158
+ // group, one attached through someone else's launch template. Then the
159
+ // group is not a node, its rules are never read, and the instance reads as
160
+ // less exposed than it is. Under-reporting is the dangerous direction for a
161
+ // query whose whole purpose is finding what the internet can reach.
162
+ const declaredGroupIds = new Set(
163
+ Object.values(options.observed)
164
+ .filter((m) => m.type === "AWS::EC2::SecurityGroup" && m.physicalId)
165
+ .map((m) => m.physicalId as string),
166
+ );
167
+ const declaredTemplateIds = new Set(
168
+ Object.values(options.observed)
169
+ .filter((m) => m.type === "AWS::EC2::LaunchTemplate" && m.physicalId)
170
+ .map((m) => m.physicalId as string),
171
+ );
172
+ const groupsById = new Map<string, Record<string, unknown>>();
173
+ const wantedGroups = new Set<string>();
174
+ const templatesById = new Map<string, string[]>();
175
+
176
+ for (const [, meta] of instances) {
177
+ const where = placement.get(meta.physicalId as string);
178
+ if (!where) continue;
179
+ for (const id of where.securityGroupIds) if (!declaredGroupIds.has(id)) wantedGroups.add(id);
180
+ if (where.launchTemplateId && !declaredTemplateIds.has(where.launchTemplateId)) {
181
+ const versions = await run([
182
+ "ec2",
183
+ "describe-launch-template-versions",
184
+ "--launch-template-id",
185
+ where.launchTemplateId,
186
+ "--versions",
187
+ "$Latest",
188
+ ]);
189
+ if (versions.exitCode === 0) {
190
+ const templateGroups = (
191
+ (JSON.parse(versions.stdout).LaunchTemplateVersions ?? []) as Array<{
192
+ LaunchTemplateData?: { SecurityGroupIds?: string[] };
193
+ }>
194
+ ).flatMap((v) => v.LaunchTemplateData?.SecurityGroupIds ?? []);
195
+ templatesById.set(where.launchTemplateId, templateGroups);
196
+ for (const id of templateGroups) if (!declaredGroupIds.has(id)) wantedGroups.add(id);
197
+ }
198
+ }
199
+ }
200
+
201
+ if (wantedGroups.size > 0) {
202
+ const described = await run(["ec2", "describe-security-groups", "--group-ids", ...wantedGroups]);
203
+ if (described.exitCode === 0) {
204
+ for (const group of (JSON.parse(described.stdout).SecurityGroups ?? []) as Array<{
205
+ GroupId?: string;
206
+ VpcId?: string;
207
+ IpPermissions?: RawIpPermission[];
208
+ }>) {
209
+ if (!group.GroupId) continue;
210
+ groupsById.set(group.GroupId, {
211
+ GroupId: group.GroupId,
212
+ VpcId: group.VpcId,
213
+ SecurityGroupIngress: toIngressRules(group.IpPermissions ?? []),
214
+ });
215
+ }
216
+ }
217
+ }
218
+
219
+ const record = (
220
+ logicalId: string,
221
+ id: string,
222
+ type: string,
223
+ physicalId: string | undefined,
224
+ attrs: Record<string, unknown>,
225
+ ) => {
226
+ const existing = resources[id];
227
+ resources[id] = {
228
+ type,
229
+ status: "OBSERVED",
230
+ ...(physicalId ? { physicalId } : {}),
231
+ attributes: attrs,
232
+ ownership: "foreign",
233
+ referencedBy: [...new Set([...(existing?.referencedBy ?? []), logicalId])],
234
+ };
235
+ };
236
+
237
+ for (const [logicalId, meta] of instances) {
238
+ const where = placement.get(meta.physicalId as string);
239
+ if (!where) continue;
240
+
241
+ // Guarding first, and unconditionally: an instance with no internet route
242
+ // still has security groups, and `effectiveIngress` is asked about
243
+ // instances that are not internet-facing too.
244
+ for (const groupId of where.securityGroupIds) {
245
+ const attrs = groupsById.get(groupId);
246
+ if (!attrs) continue; // declared, or unreadable — either way not a dependency
247
+ record(logicalId, nodeId(groupId), "AWS::EC2::SecurityGroup", groupId, attrs);
248
+ edges.push({ from: logicalId, to: nodeId(groupId), kind: "ref", viaAttr: "SecurityGroupIds" });
249
+ }
250
+ const templateGroups = where.launchTemplateId ? templatesById.get(where.launchTemplateId) : undefined;
251
+ if (where.launchTemplateId && templateGroups) {
252
+ const templateNode = nodeId(where.launchTemplateId);
253
+ record(logicalId, templateNode, "AWS::EC2::LaunchTemplate", where.launchTemplateId, {
254
+ LaunchTemplateId: where.launchTemplateId,
255
+ LaunchTemplateData: { SecurityGroupIds: templateGroups },
256
+ });
257
+ edges.push({ from: logicalId, to: templateNode, kind: "ref", viaAttr: "LaunchTemplateId" });
258
+ for (const groupId of templateGroups) {
259
+ const attrs = groupsById.get(groupId);
260
+ if (!attrs) continue;
261
+ record(logicalId, nodeId(groupId), "AWS::EC2::SecurityGroup", groupId, attrs);
262
+ edges.push({ from: templateNode, to: nodeId(groupId), kind: "ref", viaAttr: "SecurityGroupIds" });
263
+ }
264
+ }
265
+
266
+ // Explicit subnet association first, else the VPC's main table — the two
267
+ // ways an instance's placement resolves to routing.
268
+ const table: RawRouteTable | undefined =
269
+ (where.subnetId ? bySubnet.get(where.subnetId) : undefined) ??
270
+ (where.vpcId ? mainByVpc.get(where.vpcId) : undefined);
271
+ if (!table?.RouteTableId) continue;
272
+
273
+ // Only routing that actually reaches the internet is worth reporting: an
274
+ // internal table adds a node and an edge and answers nothing.
275
+ const igwRoute = (table.Routes ?? []).find(
276
+ (route) =>
277
+ typeof route.GatewayId === "string" &&
278
+ route.GatewayId.startsWith("igw-") &&
279
+ (route.DestinationCidrBlock == null || route.DestinationCidrBlock === "0.0.0.0/0"),
280
+ );
281
+ if (!igwRoute?.GatewayId) continue;
282
+
283
+ const subnetNode = where.subnetId ? nodeId(where.subnetId) : undefined;
284
+ const tableNode = nodeId(table.RouteTableId);
285
+ const gatewayNode = nodeId(igwRoute.GatewayId);
286
+ const associationNode = `${tableNode}::assoc::${subnetNode ?? table.VpcId ?? "main"}`;
287
+ const routeNode = `${tableNode}::route::${gatewayNode}`;
288
+
289
+ if (subnetNode) record(logicalId, subnetNode, "AWS::EC2::Subnet", where.subnetId, { VpcId: where.vpcId });
290
+ record(logicalId, tableNode, "AWS::EC2::RouteTable", table.RouteTableId, { VpcId: table.VpcId });
291
+ record(logicalId, gatewayNode, "AWS::EC2::InternetGateway", igwRoute.GatewayId, {
292
+ InternetGatewayId: igwRoute.GatewayId,
293
+ });
294
+ record(logicalId, associationNode, "AWS::EC2::SubnetRouteTableAssociation", undefined, {
295
+ SubnetId: where.subnetId,
296
+ RouteTableId: table.RouteTableId,
297
+ });
298
+ record(logicalId, routeNode, "AWS::EC2::Route", undefined, {
299
+ RouteTableId: table.RouteTableId,
300
+ GatewayId: igwRoute.GatewayId,
301
+ DestinationCidrBlock: igwRoute.DestinationCidrBlock ?? "0.0.0.0/0",
302
+ });
303
+
304
+ // The chain enrichEffectiveTopology walks, reported explicitly rather
305
+ // than left to be reconstructed: an association and a route have no
306
+ // physical id of their own, so no identity index can resolve them.
307
+ if (subnetNode) {
308
+ edges.push({ from: logicalId, to: subnetNode, kind: "ref", viaAttr: "SubnetId" });
309
+ edges.push({ from: associationNode, to: subnetNode, kind: "ref", viaAttr: "SubnetId" });
310
+ }
311
+ edges.push({ from: associationNode, to: tableNode, kind: "ref", viaAttr: "RouteTableId" });
312
+ edges.push({ from: routeNode, to: tableNode, kind: "ref", viaAttr: "RouteTableId" });
313
+ edges.push({ from: routeNode, to: gatewayNode, kind: "ref", viaAttr: "GatewayId" });
314
+ }
315
+ } catch {
316
+ // Best-effort: the managed observation is complete and useful on its own,
317
+ // and failing it because an ambient dependency could not be read would
318
+ // trade a whole answer for a partial one.
319
+ return { resources: {}, edges: [] };
320
+ }
321
+
322
+ return { resources, edges };
323
+ }
@@ -16403,6 +16403,38 @@ export declare class Harness {
16403
16403
  readonly Version: string;
16404
16404
  }
16405
16405
 
16406
+ export declare class HarnessEndpoint {
16407
+ constructor(props: {
16408
+ /** The name of the endpoint. Must start with a letter and contain only alphanumeric characters and underscores. */
16409
+ EndpointName: string;
16410
+ /** The ID of the harness that the endpoint belongs to. */
16411
+ HarnessId: string;
16412
+ /** The Amazon Resource Name (ARN) of the endpoint. */
16413
+ Arn?: string;
16414
+ /** The timestamp when the endpoint was created. */
16415
+ CreatedAt?: string;
16416
+ /** The description of the endpoint. */
16417
+ Description?: string;
16418
+ /** The name of the harness that the endpoint belongs to. */
16419
+ HarnessName?: string;
16420
+ /** The harness version that the endpoint is currently serving. */
16421
+ LiveVersion?: string;
16422
+ Status?: HarnessEndpoint_HarnessEndpointStatus;
16423
+ /** Tags to apply to the harness endpoint resource. */
16424
+ Tags?: HarnessEndpoint_Tag[];
16425
+ /** The harness version that the endpoint points to and serves invocations from. */
16426
+ TargetVersion?: string;
16427
+ /** The timestamp when the endpoint was last updated. */
16428
+ UpdatedAt?: string;
16429
+ }, attributes?: CFResourceAttributes);
16430
+ readonly Arn: string;
16431
+ readonly CreatedAt: string;
16432
+ readonly HarnessName: string;
16433
+ readonly LiveVersion: string;
16434
+ readonly Status: HarnessEndpoint_HarnessEndpointStatus;
16435
+ readonly UpdatedAt: string;
16436
+ }
16437
+
16406
16438
  export declare class HealthCheck {
16407
16439
  constructor(props: {
16408
16440
  /** A complex type that contains information about the health check. */
@@ -32859,6 +32891,27 @@ export declare class ServiceProfile {
32859
32891
  readonly LoRaWAN_UlRatePolicy: string;
32860
32892
  }
32861
32893
 
32894
+ export declare class ServiceSetting {
32895
+ constructor(props: {
32896
+ /** The ID of the service setting, such as /ssm/parameter-store/high-throughput-enabled. */
32897
+ SettingId: string;
32898
+ /** The value of the service setting. */
32899
+ SettingValue: string;
32900
+ /** The ARN of the service setting. */
32901
+ Arn?: string;
32902
+ /** The last time the service setting was modified. */
32903
+ LastModifiedDate?: string;
32904
+ /** The ARN of the last modified user. */
32905
+ LastModifiedUser?: string;
32906
+ /** The status of the service setting. The value can be Default, Customized or PendingUpdate. */
32907
+ Status?: string;
32908
+ }, attributes?: CFResourceAttributes);
32909
+ readonly Arn: string;
32910
+ readonly LastModifiedDate: string;
32911
+ readonly LastModifiedUser: string;
32912
+ readonly Status: string;
32913
+ }
32914
+
32862
32915
  export declare class ServiceTemplate {
32863
32916
  constructor(props: {
32864
32917
  /** <p>The Amazon Resource Name (ARN) of the service template.</p> */
@@ -57089,7 +57142,7 @@ export declare class ContainerRecipe_EbsInstanceBlockDeviceSpecification {
57089
57142
  /** Use to override the device's volume size. */
57090
57143
  VolumeSize?: number;
57091
57144
  /** Use to override the device's volume type. */
57092
- VolumeType?: "gp2" | "gp3" | "io1" | "io2" | "sc1" | "st1" | "standard";
57145
+ VolumeType?: "gp2" | "gp3" | "gp3a" | "io1" | "io2" | "io2a" | "sc1" | "st1" | "standard";
57093
57146
  });
57094
57147
  }
57095
57148
 
@@ -75141,7 +75194,7 @@ export declare class GlobalTable_ReplicaSSESpecification {
75141
75194
 
75142
75195
  export declare class GlobalTable_ReplicaStreamSpecification {
75143
75196
  constructor(props: {
75144
- ResourcePolicy?: GlobalTable_ResourcePolicy;
75197
+ ResourcePolicy: GlobalTable_ResourcePolicy;
75145
75198
  });
75146
75199
  }
75147
75200
 
@@ -76693,6 +76746,13 @@ export declare class HarnessBedrockModelConfig {
76693
76746
  });
76694
76747
  }
76695
76748
 
76749
+ export declare class HarnessEndpoint_Tag {
76750
+ constructor(props: {
76751
+ Key: string;
76752
+ Value: string;
76753
+ });
76754
+ }
76755
+
76696
76756
  export declare class HarnessEnvironmentArtifact {
76697
76757
  constructor(props: {
76698
76758
  ContainerConfiguration?: Harness_ContainerConfiguration;
@@ -78724,7 +78784,7 @@ export declare class ImageRecipe_EbsInstanceBlockDeviceSpecification {
78724
78784
  /** Use to override the device's volume size. */
78725
78785
  VolumeSize?: number;
78726
78786
  /** Use to override the device's volume type. */
78727
- VolumeType?: "gp2" | "gp3" | "io1" | "io2" | "sc1" | "st1" | "standard";
78787
+ VolumeType?: "gp2" | "gp3" | "gp3a" | "io1" | "io2" | "io2a" | "sc1" | "st1" | "standard";
78728
78788
  });
78729
78789
  }
78730
78790
 
@@ -86435,7 +86495,9 @@ export declare class Listener_RedirectConfig {
86435
86495
 
86436
86496
  export declare class Listener_Tag {
86437
86497
  constructor(props: {
86498
+ /** The key of the tag. */
86438
86499
  Key: string;
86500
+ /** The value of the tag. */
86439
86501
  Value: string;
86440
86502
  });
86441
86503
  }
@@ -106283,7 +106345,7 @@ export declare class ReplicaSSESpecification {
106283
106345
 
106284
106346
  export declare class ReplicaStreamSpecification {
106285
106347
  constructor(props: {
106286
- ResourcePolicy?: GlobalTable_ResourcePolicy;
106348
+ ResourcePolicy: GlobalTable_ResourcePolicy;
106287
106349
  });
106288
106350
  }
106289
106351
 
@@ -112163,6 +112225,8 @@ export declare class Scraper_Destination {
112163
112225
  constructor(props: {
112164
112226
  /** Configuration for Amazon Managed Prometheus metrics destination */
112165
112227
  AmpConfiguration?: Record<string, unknown>;
112228
+ /** Configuration for CloudWatch metrics destination */
112229
+ CloudWatchConfiguration?: Record<string, unknown>;
112166
112230
  });
112167
112231
  }
112168
112232
 
@@ -130350,6 +130414,15 @@ export type Harness_HarnessStatus =
130350
130414
  | "UPDATE_FAILED"
130351
130415
  | "UPDATING";
130352
130416
 
130417
+ export type HarnessEndpoint_HarnessEndpointStatus =
130418
+ | "CREATE_FAILED"
130419
+ | "CREATING"
130420
+ | "DELETE_FAILED"
130421
+ | "DELETING"
130422
+ | "READY"
130423
+ | "UPDATE_FAILED"
130424
+ | "UPDATING";
130425
+
130353
130426
  export type HealthImagingDatastore_DatastoreStatus =
130354
130427
  | "ACTIVE"
130355
130428
  | "CREATE_FAILED"
@@ -640,6 +640,7 @@ export const GuardHook = createResource("AWS::CloudFormation::GuardHook", "aws",
640
640
  export const Guardrail = createResource("AWS::Bedrock::Guardrail", "aws", {"CreatedAt":"CreatedAt","FailureRecommendations":"FailureRecommendations","GuardrailArn":"GuardrailArn","GuardrailId":"GuardrailId","Status":"Status","StatusReasons":"StatusReasons","UpdatedAt":"UpdatedAt","Version":"Version"});
641
641
  export const GuardrailVersion = createResource("AWS::Bedrock::GuardrailVersion", "aws", {"GuardrailArn":"GuardrailArn","GuardrailId":"GuardrailId","Version":"Version"});
642
642
  export const Harness = createResource("AWS::BedrockAgentCore::Harness", "aws", {"Arn":"Arn","HarnessId":"HarnessId","Status":"Status","Version":"Version","CreatedAt":"CreatedAt","UpdatedAt":"UpdatedAt","Memory_ManagedMemoryConfiguration_Arn":"Memory.ManagedMemoryConfiguration.Arn","Environment_AgentCoreRuntimeEnvironment_AgentRuntimeArn":"Environment.AgentCoreRuntimeEnvironment.AgentRuntimeArn","Environment_AgentCoreRuntimeEnvironment_AgentRuntimeName":"Environment.AgentCoreRuntimeEnvironment.AgentRuntimeName","Environment_AgentCoreRuntimeEnvironment_AgentRuntimeId":"Environment.AgentCoreRuntimeEnvironment.AgentRuntimeId"});
643
+ export const HarnessEndpoint = createResource("AWS::BedrockAgentCore::HarnessEndpoint", "aws", {"Arn":"Arn","HarnessName":"HarnessName","Status":"Status","LiveVersion":"LiveVersion","CreatedAt":"CreatedAt","UpdatedAt":"UpdatedAt"});
643
644
  export const HealthCheck = createResource("AWS::Route53::HealthCheck", "aws", {"HealthCheckId":"HealthCheckId"});
644
645
  export const HealthImagingDatastore = createResource("AWS::HealthImaging::Datastore", "aws", {"DatastoreArn":"DatastoreArn","CreatedAt":"CreatedAt","UpdatedAt":"UpdatedAt","DatastoreId":"DatastoreId","DatastoreStatus":"DatastoreStatus"});
645
646
  export const HookDefaultVersion = createResource("AWS::CloudFormation::HookDefaultVersion", "aws", {"Arn":"Arn"});
@@ -1355,6 +1356,7 @@ export const ServiceNetworkServiceAssociation = createResource("AWS::VpcLattice:
1355
1356
  export const ServiceNetworkVpcAssociation = createResource("AWS::VpcLattice::ServiceNetworkVpcAssociation", "aws", {"Arn":"Arn","CreatedAt":"CreatedAt","Id":"Id","ServiceNetworkArn":"ServiceNetworkArn","ServiceNetworkId":"ServiceNetworkId","ServiceNetworkName":"ServiceNetworkName","Status":"Status","VpcId":"VpcId"});
1356
1357
  export const ServicePrincipalName = createResource("AWS::PCAConnectorAD::ServicePrincipalName", "aws", {});
1357
1358
  export const ServiceProfile = createResource("AWS::IoTWireless::ServiceProfile", "aws", {"Id":"Id","Arn":"Arn","LoRaWAN_UlRate":"LoRaWAN.UlRate","LoRaWAN_UlBucketSize":"LoRaWAN.UlBucketSize","LoRaWAN_UlRatePolicy":"LoRaWAN.UlRatePolicy","LoRaWAN_DlRate":"LoRaWAN.DlRate","LoRaWAN_DlBucketSize":"LoRaWAN.DlBucketSize","LoRaWAN_DlRatePolicy":"LoRaWAN.DlRatePolicy","LoRaWAN_DevStatusReqFreq":"LoRaWAN.DevStatusReqFreq","LoRaWAN_ReportDevStatusBattery":"LoRaWAN.ReportDevStatusBattery","LoRaWAN_ReportDevStatusMargin":"LoRaWAN.ReportDevStatusMargin","LoRaWAN_DrMin":"LoRaWAN.DrMin","LoRaWAN_DrMax":"LoRaWAN.DrMax","LoRaWAN_ChannelMask":"LoRaWAN.ChannelMask","LoRaWAN_HrAllowed":"LoRaWAN.HrAllowed","LoRaWAN_NwkGeoLoc":"LoRaWAN.NwkGeoLoc","LoRaWAN_TargetPer":"LoRaWAN.TargetPer","LoRaWAN_MinGwDiversity":"LoRaWAN.MinGwDiversity"});
1359
+ export const ServiceSetting = createResource("AWS::SSM::ServiceSetting", "aws", {"Status":"Status","LastModifiedDate":"LastModifiedDate","LastModifiedUser":"LastModifiedUser","Arn":"Arn"});
1358
1360
  export const ServiceTemplate = createResource("AWS::Proton::ServiceTemplate", "aws", {"Arn":"Arn"});
1359
1361
  export const SESConfigurationSet = createResource("AWS::SES::ConfigurationSet", "aws", {});
1360
1362
  export const SESConfigurationSetEventDestination = createResource("AWS::SES::ConfigurationSetEventDestination", "aws", {"Id":"Id"});
@@ -5495,6 +5497,7 @@ export const HarnessAgentCoreGatewayConfig = createProperty("AWS::BedrockAgentCo
5495
5497
  export const HarnessAgentCoreMemoryConfiguration = createProperty("AWS::BedrockAgentCore::Harness.HarnessAgentCoreMemoryConfiguration", "aws");
5496
5498
  export const HarnessAgentCoreRuntimeEnvironment = createProperty("AWS::BedrockAgentCore::Harness.HarnessAgentCoreRuntimeEnvironment", "aws");
5497
5499
  export const HarnessBedrockModelConfig = createProperty("AWS::BedrockAgentCore::Harness.HarnessBedrockModelConfig", "aws");
5500
+ export const HarnessEndpoint_Tag = createProperty("AWS::BedrockAgentCore::HarnessEndpoint.Tag", "aws");
5498
5501
  export const HarnessEnvironmentArtifact = createProperty("AWS::BedrockAgentCore::Harness.HarnessEnvironmentArtifact", "aws");
5499
5502
  export const HarnessEnvironmentProvider = createProperty("AWS::BedrockAgentCore::Harness.HarnessEnvironmentProvider", "aws");
5500
5503
  export const HarnessGeminiModelConfig = createProperty("AWS::BedrockAgentCore::Harness.HarnessGeminiModelConfig", "aws");
@@ -44553,6 +44553,67 @@
44553
44553
  "kind": "property",
44554
44554
  "lexicon": "aws"
44555
44555
  },
44556
+ "HarnessEndpoint": {
44557
+ "resourceType": "AWS::BedrockAgentCore::HarnessEndpoint",
44558
+ "kind": "resource",
44559
+ "lexicon": "aws",
44560
+ "attrs": {
44561
+ "Arn": "Arn",
44562
+ "HarnessName": "HarnessName",
44563
+ "Status": "Status",
44564
+ "LiveVersion": "LiveVersion",
44565
+ "CreatedAt": "CreatedAt",
44566
+ "UpdatedAt": "UpdatedAt"
44567
+ },
44568
+ "propertyConstraints": {
44569
+ "HarnessId": {
44570
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]{0,39}-[a-zA-Z0-9]{10}$"
44571
+ },
44572
+ "EndpointName": {
44573
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]{0,47}$"
44574
+ },
44575
+ "TargetVersion": {
44576
+ "pattern": "^([1-9][0-9]{0,4})$",
44577
+ "minLength": 1,
44578
+ "maxLength": 5
44579
+ },
44580
+ "LiveVersion": {
44581
+ "pattern": "^([1-9][0-9]{0,4})$",
44582
+ "minLength": 1,
44583
+ "maxLength": 5
44584
+ },
44585
+ "Description": {
44586
+ "minLength": 1,
44587
+ "maxLength": 256
44588
+ },
44589
+ "CreatedAt": {
44590
+ "format": "date-time"
44591
+ },
44592
+ "UpdatedAt": {
44593
+ "format": "date-time"
44594
+ }
44595
+ },
44596
+ "createOnly": [
44597
+ "HarnessId",
44598
+ "EndpointName"
44599
+ ],
44600
+ "writeOnly": [
44601
+ "TargetVersion"
44602
+ ],
44603
+ "primaryIdentifier": [
44604
+ "Arn"
44605
+ ],
44606
+ "tagging": {
44607
+ "taggable": true,
44608
+ "tagOnCreate": true,
44609
+ "tagUpdatable": true
44610
+ }
44611
+ },
44612
+ "HarnessEndpoint_Tag": {
44613
+ "resourceType": "AWS::BedrockAgentCore::HarnessEndpoint.Tag",
44614
+ "kind": "property",
44615
+ "lexicon": "aws"
44616
+ },
44556
44617
  "HarnessEnvironmentArtifact": {
44557
44618
  "resourceType": "AWS::BedrockAgentCore::Harness.HarnessEnvironmentArtifact",
44558
44619
  "kind": "property",
@@ -70884,7 +70945,7 @@
70884
70945
  "maxLength": 256
70885
70946
  },
70886
70947
  "FunctionName": {
70887
- "pattern": "^(arn:(aws[a-zA-Z-]*)?:lambda:)?((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\\$LATEST|[a-zA-Z0-9-_]+))?$",
70948
+ "pattern": "^(arn:(aws[a-zA-Z-]*)?:lambda:)?((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\\$LATEST(\\.PUBLISHED)?|[a-zA-Z0-9-_]+))?$",
70888
70949
  "minLength": 1,
70889
70950
  "maxLength": 140
70890
70951
  },
@@ -91147,6 +91208,36 @@
91147
91208
  "kind": "property",
91148
91209
  "lexicon": "aws"
91149
91210
  },
91211
+ "ServiceSetting": {
91212
+ "resourceType": "AWS::SSM::ServiceSetting",
91213
+ "kind": "resource",
91214
+ "lexicon": "aws",
91215
+ "attrs": {
91216
+ "Status": "Status",
91217
+ "LastModifiedDate": "LastModifiedDate",
91218
+ "LastModifiedUser": "LastModifiedUser",
91219
+ "Arn": "Arn"
91220
+ },
91221
+ "propertyConstraints": {
91222
+ "SettingId": {
91223
+ "minLength": 1,
91224
+ "maxLength": 1000
91225
+ },
91226
+ "SettingValue": {
91227
+ "minLength": 1,
91228
+ "maxLength": 4096
91229
+ },
91230
+ "LastModifiedDate": {
91231
+ "format": "date-time"
91232
+ }
91233
+ },
91234
+ "createOnly": [
91235
+ "SettingId"
91236
+ ],
91237
+ "primaryIdentifier": [
91238
+ "Arn"
91239
+ ]
91240
+ },
91150
91241
  "ServiceSoftwareOptions": {
91151
91242
  "resourceType": "AWS::OpenSearchService::Domain.ServiceSoftwareOptions",
91152
91243
  "kind": "property",