@go-to-k/cdkd 0.290.29 → 0.290.31
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/{asg-provider-Dwnb3CES.js → asg-provider-DNzgk-BS.js} +3 -3
- package/dist/{asg-provider-Dwnb3CES.js.map → asg-provider-DNzgk-BS.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-Bcwb9_mO.js → deploy-engine-21iNqwR3.js} +289 -130
- package/dist/{deploy-engine-Bcwb9_mO.js.map → deploy-engine-21iNqwR3.js.map} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{logger-6LP1UiFA.js → logger-BjWM-UVj.js} +42 -2
- package/dist/logger-BjWM-UVj.js.map +1 -0
- package/dist/{program-PCCyP9-O.js → program-CnSaRdY9.js} +105 -31
- package/dist/{program-PCCyP9-O.js.map → program-CnSaRdY9.js.map} +1 -1
- package/dist/{version-snXN__f1.js → version-IwTfNQ-K.js} +2 -2
- package/dist/{version-snXN__f1.js.map → version-IwTfNQ-K.js.map} +1 -1
- package/package.json +1 -1
- package/dist/logger-6LP1UiFA.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as displayAwsMessage, E as truncateCodePoints, S as UNRENDERABLE, T as displaySafe, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS, y as withoutGeneratedFallbackName } from "./logger-BjWM-UVj.js";
|
|
2
2
|
import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-BoIxyCir.js";
|
|
3
|
-
import { t as getCdkdVersion } from "./version-
|
|
3
|
+
import { t as getCdkdVersion } from "./version-IwTfNQ-K.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -17109,7 +17109,8 @@ var DagBuilder = class {
|
|
|
17109
17109
|
resourceIds.forEach((logicalId) => {
|
|
17110
17110
|
const resource = this.parser.getResource(template, logicalId);
|
|
17111
17111
|
graph.setNode(logicalId, resource);
|
|
17112
|
-
|
|
17112
|
+
const typeText = resource?.Type == null ? "<no Type>" : displayIdent(resource.Type);
|
|
17113
|
+
this.logger.debug(`Added node: ${displayIdent(logicalId)} (${typeText})`);
|
|
17113
17114
|
});
|
|
17114
17115
|
this.logger.debug(`Total nodes: ${resourceIds.length}`);
|
|
17115
17116
|
const parameterNames = new Set(Object.keys(template.Parameters ?? {}));
|
|
@@ -17123,15 +17124,15 @@ var DagBuilder = class {
|
|
|
17123
17124
|
for (const depId of dependencies) {
|
|
17124
17125
|
if (skip?.has(depId)) {
|
|
17125
17126
|
relaxedEdgeCount++;
|
|
17126
|
-
this.logger.debug(`Skipped CDK-defensive DependsOn edge: ${depId} -> ${logicalId} (default; opt out with --no-aggressive-vpc-parallel)`);
|
|
17127
|
+
this.logger.debug(`Skipped CDK-defensive DependsOn edge: ${displayIdent(depId)} -> ${displayIdent(logicalId)} (default; opt out with --no-aggressive-vpc-parallel)`);
|
|
17127
17128
|
continue;
|
|
17128
17129
|
}
|
|
17129
17130
|
if (graph.hasNode(depId)) {
|
|
17130
17131
|
graph.setEdge(depId, logicalId);
|
|
17131
17132
|
edgeCount++;
|
|
17132
|
-
this.logger.debug(`Added edge: ${depId} -> ${logicalId}`);
|
|
17133
|
-
} else if (parameterNames.has(depId)) this.logger.debug(`Skipped Parameter reference: ${logicalId} -> ${depId}`);
|
|
17134
|
-
else this.logger.warn(`Resource ${logicalId} depends on ${depId}, but ${depId} not found in template`);
|
|
17133
|
+
this.logger.debug(`Added edge: ${displayIdent(depId)} -> ${displayIdent(logicalId)}`);
|
|
17134
|
+
} else if (parameterNames.has(depId)) this.logger.debug(`Skipped Parameter reference: ${displayIdent(logicalId)} -> ${displayIdent(depId)}`);
|
|
17135
|
+
else this.logger.warn(`Resource ${displayIdent(logicalId)} depends on ${displayIdent(depId)}, but ${displayIdent(depId)} not found in template`);
|
|
17135
17136
|
}
|
|
17136
17137
|
}
|
|
17137
17138
|
if (relaxedEdgeCount > 0) this.logger.info(`[DagBuilder] Relaxed ${relaxedEdgeCount} CDK-defensive DependsOn edge(s) (default; opt out with --no-aggressive-vpc-parallel)`);
|
|
@@ -17140,7 +17141,7 @@ var DagBuilder = class {
|
|
|
17140
17141
|
edgeCount += this.addLambdaVpcEdges(graph, template);
|
|
17141
17142
|
if (!alg.isAcyclic(graph)) {
|
|
17142
17143
|
const cycles = this.findCycles(graph);
|
|
17143
|
-
throw new DependencyError(`Circular dependency detected in template. Cycles: ${cycles.map((c) => c.join(" -> ")).join("; ")}`);
|
|
17144
|
+
throw new DependencyError(`Circular dependency detected in template. Cycles: ${cycles.map((c) => c.map((n) => displayIdent(n)).join(" -> ")).join("; ")}`);
|
|
17144
17145
|
}
|
|
17145
17146
|
return graph;
|
|
17146
17147
|
}
|
|
@@ -17172,9 +17173,9 @@ var DagBuilder = class {
|
|
|
17172
17173
|
});
|
|
17173
17174
|
if (readyNodes.length === 0) {
|
|
17174
17175
|
const remaining = graphCopy.nodes();
|
|
17175
|
-
throw new DependencyError(`Circular dependency detected. Remaining nodes: ${remaining.join(", ")}`);
|
|
17176
|
+
throw new DependencyError(`Circular dependency detected. Remaining nodes: ${remaining.map((n) => displayIdent(n)).join(", ")}`);
|
|
17176
17177
|
}
|
|
17177
|
-
this.logger.debug(`Level ${levelNum}: ${readyNodes.length} resources - ${readyNodes.join(", ")}`);
|
|
17178
|
+
this.logger.debug(`Level ${levelNum}: ${readyNodes.length} resources - ${readyNodes.map((n) => displayIdent(n)).join(", ")}`);
|
|
17178
17179
|
levels.push(readyNodes);
|
|
17179
17180
|
readyNodes.forEach((node) => {
|
|
17180
17181
|
graphCopy.removeNode(node);
|
|
@@ -17291,7 +17292,7 @@ var DagBuilder = class {
|
|
|
17291
17292
|
if (graph.hasEdge(policyId, logicalId)) continue;
|
|
17292
17293
|
graph.setEdge(policyId, logicalId);
|
|
17293
17294
|
added++;
|
|
17294
|
-
this.logger.debug(`Added implicit edge (custom resource policy): ${policyId} -> ${logicalId}`);
|
|
17295
|
+
this.logger.debug(`Added implicit edge (custom resource policy): ${displayIdent(policyId)} -> ${displayIdent(logicalId)}`);
|
|
17295
17296
|
}
|
|
17296
17297
|
}
|
|
17297
17298
|
if (added > 0) this.logger.debug(`Added ${added} implicit edges for custom resource policies`);
|
|
@@ -17322,7 +17323,7 @@ var DagBuilder = class {
|
|
|
17322
17323
|
if (graph.hasEdge(depId, dependentId)) continue;
|
|
17323
17324
|
graph.setEdge(depId, dependentId);
|
|
17324
17325
|
added++;
|
|
17325
|
-
this.logger.debug(`Added implicit edge (lambda vpc): ${depId} -> ${dependentId}`);
|
|
17326
|
+
this.logger.debug(`Added implicit edge (lambda vpc): ${displayIdent(depId)} -> ${displayIdent(dependentId)}`);
|
|
17326
17327
|
}
|
|
17327
17328
|
if (added > 0) this.logger.debug(`Added ${added} implicit edges for Lambda VpcConfig`);
|
|
17328
17329
|
return added;
|
|
@@ -20580,13 +20581,14 @@ const PROPERTY_COVERAGE_BY_TYPE = /* @__PURE__ */ new Map([
|
|
|
20580
20581
|
"FifoThroughputScope",
|
|
20581
20582
|
"FifoTopic",
|
|
20582
20583
|
"KmsMasterKeyId",
|
|
20584
|
+
"MaximumMessageSize",
|
|
20583
20585
|
"SignatureVersion",
|
|
20584
20586
|
"Subscription",
|
|
20585
20587
|
"Tags",
|
|
20586
20588
|
"TopicName",
|
|
20587
20589
|
"TracingConfig"
|
|
20588
20590
|
]),
|
|
20589
|
-
silentDrop: /* @__PURE__ */ new Map(
|
|
20591
|
+
silentDrop: /* @__PURE__ */ new Map(),
|
|
20590
20592
|
createOnlyDrops: /* @__PURE__ */ new Set()
|
|
20591
20593
|
}],
|
|
20592
20594
|
["AWS::SNS::TopicPolicy", {
|
|
@@ -23136,7 +23138,8 @@ async function assumeRoleForCrossAccountStateRead(roleArn) {
|
|
|
23136
23138
|
}
|
|
23137
23139
|
const promise = (async () => {
|
|
23138
23140
|
const logger = getLogger().child("role-arn");
|
|
23139
|
-
|
|
23141
|
+
const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
|
|
23142
|
+
logger.debug(`Assuming role for cross-account state read: ${displayRoleArn}`);
|
|
23140
23143
|
const sts = new STSClient({ ...awsClientDefaults() });
|
|
23141
23144
|
try {
|
|
23142
23145
|
let response;
|
|
@@ -23147,13 +23150,13 @@ async function assumeRoleForCrossAccountStateRead(roleArn) {
|
|
|
23147
23150
|
DurationSeconds: 3600
|
|
23148
23151
|
}));
|
|
23149
23152
|
} catch (err) {
|
|
23150
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
23151
|
-
throw new Error(`AssumeRole into ${
|
|
23153
|
+
const message = displayAwsMessage(err instanceof Error ? err.message : String(err));
|
|
23154
|
+
throw new Error(`AssumeRole into ${displayRoleArn} failed: ${message}. If this is a trust-policy issue, the producer's role must allow sts:AssumeRole from the consumer's principal. See https://github.com/go-to-k/cdkd/blob/main/docs/cross-stack-references.md for the trust-policy template.`, { cause: err instanceof Error ? err : void 0 });
|
|
23152
23155
|
}
|
|
23153
|
-
if (!response.Credentials) throw new Error(`AssumeRole for cross-account Fn::GetStackOutput returned no credentials (RoleArn=${
|
|
23156
|
+
if (!response.Credentials) throw new Error(`AssumeRole for cross-account Fn::GetStackOutput returned no credentials (RoleArn=${displayRoleArn})`);
|
|
23154
23157
|
const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
|
|
23155
|
-
if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing required credentials fields for cross-account state read (RoleArn=${
|
|
23156
|
-
logger.info(`Assumed role for cross-account state read: ${
|
|
23158
|
+
if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing required credentials fields for cross-account state read (RoleArn=${displayRoleArn})`);
|
|
23159
|
+
logger.info(`Assumed role for cross-account state read: ${displayRoleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
|
|
23157
23160
|
return {
|
|
23158
23161
|
accessKeyId: AccessKeyId,
|
|
23159
23162
|
secretAccessKey: SecretAccessKey,
|
|
@@ -23261,18 +23264,23 @@ async function applyRoleArnIfSet(opts) {
|
|
|
23261
23264
|
if (!roleArn) return;
|
|
23262
23265
|
if (getAssumedRoleCredentials() !== void 0) throw new Error(SECOND_ROLE_PUBLISH_REFUSAL);
|
|
23263
23266
|
const logger = getLogger().child("role-arn");
|
|
23264
|
-
const displayRoleArn =
|
|
23267
|
+
const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
|
|
23265
23268
|
logger.debug(`Assuming role ${displayRoleArn}...`);
|
|
23266
23269
|
const sts = new STSClient({
|
|
23267
23270
|
...awsClientDefaults({ ignoreAssumedRole: true }),
|
|
23268
23271
|
...opts.region && { region: opts.region }
|
|
23269
23272
|
});
|
|
23270
23273
|
try {
|
|
23271
|
-
|
|
23272
|
-
|
|
23273
|
-
|
|
23274
|
-
|
|
23275
|
-
|
|
23274
|
+
let response;
|
|
23275
|
+
try {
|
|
23276
|
+
response = await sts.send(new AssumeRoleCommand({
|
|
23277
|
+
RoleArn: roleArn,
|
|
23278
|
+
RoleSessionName: `cdkd-${Date.now()}`,
|
|
23279
|
+
DurationSeconds: 3600
|
|
23280
|
+
}));
|
|
23281
|
+
} catch (err) {
|
|
23282
|
+
throw new Error(`AssumeRole for ${displayRoleArn} failed: ${displayAwsMessage(err instanceof Error ? err.message : String(err))}`, { cause: err instanceof Error ? err : void 0 });
|
|
23283
|
+
}
|
|
23276
23284
|
if (!response.Credentials) throw new Error(`AssumeRole returned no credentials for role ${displayRoleArn}`);
|
|
23277
23285
|
const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
|
|
23278
23286
|
if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing credentials fields for role ${displayRoleArn}`);
|
|
@@ -27181,14 +27189,14 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27181
27189
|
if (!targetRegion) return ambient;
|
|
27182
27190
|
const target = canonicalizeRegion(targetRegion);
|
|
27183
27191
|
const loggedTarget = targetLogText ?? (targetRegion === this.explicitRegion ? this.explicitRegionLogText : void 0) ?? target;
|
|
27184
|
-
if (!isClientSafeRegion(target)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to build AWS clients for the region '${stripControlChars(loggedTarget).slice(0, 64)}': it is not a valid AWS region name, and a region is substituted into the AWS service hostname.`));
|
|
27192
|
+
if (!isClientSafeRegion(target)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to build AWS clients for the region '${displaySafe(stripControlChars(loggedTarget)).slice(0, 64)}': it is not a valid AWS region name, and a region is substituted into the AWS service hostname.`));
|
|
27185
27193
|
if (typeof ambient.withRegion !== "function") return ambient;
|
|
27186
27194
|
const cached = this.regionScopedClients.get(target);
|
|
27187
27195
|
if (cached) return cached;
|
|
27188
27196
|
if (canonicalizeRegion(ambient.configuredRegion) === target) return ambient;
|
|
27189
27197
|
const scoped = ambient.withRegion(target);
|
|
27190
27198
|
this.regionScopedClients.set(target, scoped);
|
|
27191
|
-
this.logger.debug(`Using region-scoped AWS clients for ${loggedTarget}`);
|
|
27199
|
+
this.logger.debug(`Using region-scoped AWS clients for ${displaySafe(loggedTarget)}`);
|
|
27192
27200
|
return scoped;
|
|
27193
27201
|
}
|
|
27194
27202
|
/**
|
|
@@ -27254,7 +27262,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27254
27262
|
*/
|
|
27255
27263
|
async resolveParameters(template, userParameters, options) {
|
|
27256
27264
|
const inheritedSecrets = options?.inheritedSecrets;
|
|
27257
|
-
const maskInherited = (text) =>
|
|
27265
|
+
const maskInherited = (text) => {
|
|
27266
|
+
const mask = (value) => inheritedSecrets && inheritedSecrets.size > 0 ? maskSecretsInText(value, inheritedSecrets) : value;
|
|
27267
|
+
return displaySafe(mask(stripControlChars(mask(text))));
|
|
27268
|
+
};
|
|
27258
27269
|
const inheritedLogContext = {
|
|
27259
27270
|
template,
|
|
27260
27271
|
resources: {},
|
|
@@ -27359,7 +27370,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27359
27370
|
for (const name of Object.keys(templateConditions)) try {
|
|
27360
27371
|
await withSharedDrainBudget(() => evaluateByName(name));
|
|
27361
27372
|
} catch (error) {
|
|
27362
|
-
this.logger.warn(this.
|
|
27373
|
+
this.logger.warn(this.displayMasked(`Failed to evaluate condition ${name}: ${error instanceof Error ? error.message : String(error)}, assuming false`, maskingContext));
|
|
27363
27374
|
conditions[name] = false;
|
|
27364
27375
|
inProgress.delete(name);
|
|
27365
27376
|
}
|
|
@@ -27647,7 +27658,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27647
27658
|
const value = context.parameters[logicalId];
|
|
27648
27659
|
const declared = context.template.Parameters;
|
|
27649
27660
|
const paramDef = declared != null && Object.hasOwn(declared, logicalId) ? declared[logicalId] : void 0;
|
|
27650
|
-
this.logger.debug(`Resolved Ref to parameter: ${logicalId} -> ${this.
|
|
27661
|
+
this.logger.debug(`Resolved Ref to parameter: ${logicalId} -> ${this.displayMasked(stringifyParameterForLog(paramDef, this.maskValueLeaves(value, context)), context)}`);
|
|
27651
27662
|
this.recordInheritedParameterSecrets(logicalId, value, context);
|
|
27652
27663
|
return value;
|
|
27653
27664
|
}
|
|
@@ -27657,10 +27668,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27657
27668
|
this.logger.debug(`Resolved Ref to pseudo parameter: ${logicalId} -> ${valueStr}`);
|
|
27658
27669
|
return pseudoValue;
|
|
27659
27670
|
}
|
|
27660
|
-
const
|
|
27671
|
+
const loggedLogicalId = this.displayMasked(logicalId, context);
|
|
27672
|
+
const notFoundMsg = `Ref ${loggedLogicalId} not found (not a resource, parameter, or pseudo parameter)`;
|
|
27661
27673
|
if (context.bestEffort) this.logger.debug(notFoundMsg);
|
|
27662
27674
|
else this.logger.warn(notFoundMsg);
|
|
27663
|
-
throw markNonRetryable(/* @__PURE__ */ new Error(`Ref ${
|
|
27675
|
+
throw markNonRetryable(/* @__PURE__ */ new Error(`Ref ${loggedLogicalId} not found`));
|
|
27664
27676
|
}
|
|
27665
27677
|
/**
|
|
27666
27678
|
* Resolve the value a CloudFormation `Ref` returns for a resource.
|
|
@@ -27820,11 +27832,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27820
27832
|
this.rejectPlaceholderArnAttribute(resource, attributeName, flatValue, logicalId, context);
|
|
27821
27833
|
if (resource.resourceType === "AWS::Route53::HostedZone" && attributeName === "NameServers" && typeof flatValue === "string") {
|
|
27822
27834
|
const nameServers = flatValue === "" ? [] : flatValue.split(",");
|
|
27823
|
-
this.logger.debug(`Normalized legacy Fn::GetAtt attribute: ${logicalId}.${this.
|
|
27835
|
+
this.logger.debug(`Normalized legacy Fn::GetAtt attribute: ${logicalId}.${this.displayMasked(attributeName, context)} -> ${this.displayMasked(stringifyAttributeForLog(attributeName, this.maskValueLeaves(nameServers, context)), context)}`);
|
|
27824
27836
|
return this.noteAttributeSecrecy(logicalId, attributeName, nameServers, context);
|
|
27825
27837
|
}
|
|
27826
|
-
this.logger.debug(`Resolved Fn::GetAtt from attributes: ${logicalId}.${this.
|
|
27827
|
-
if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) && carriesDynamicReference(flatValue)) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${this.
|
|
27838
|
+
this.logger.debug(`Resolved Fn::GetAtt from attributes: ${logicalId}.${this.displayMasked(attributeName, context)} -> ${this.displayMasked(stringifyAttributeForLog(attributeName, this.maskValueLeaves(flatValue, context)), context)}`);
|
|
27839
|
+
if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) && carriesDynamicReference(flatValue)) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${this.displayLeaf(attributeName, context)}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
|
|
27828
27840
|
return this.noteAttributeSecrecy(logicalId, attributeName, flatValue, context);
|
|
27829
27841
|
}
|
|
27830
27842
|
if (attributeName.includes(".")) {
|
|
@@ -27836,18 +27848,18 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27836
27848
|
break;
|
|
27837
27849
|
}
|
|
27838
27850
|
if (cursor !== void 0) {
|
|
27839
|
-
this.logger.debug(`Resolved Fn::GetAtt from nested attributes: ${logicalId}.${this.
|
|
27851
|
+
this.logger.debug(`Resolved Fn::GetAtt from nested attributes: ${logicalId}.${this.displayMasked(attributeName, context)} -> ${this.displayMasked(stringifyAttributeForLog(attributeName, this.maskValueLeaves(cursor, context)), context)}`);
|
|
27840
27852
|
return this.noteAttributeSecrecy(logicalId, attributeName, cursor, context);
|
|
27841
27853
|
}
|
|
27842
27854
|
}
|
|
27843
27855
|
}
|
|
27844
27856
|
if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)) {
|
|
27845
|
-
const declared = Object.keys(resource.attributes ?? {}).filter((k) => k.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)).sort().map((k) => this.
|
|
27857
|
+
const declared = Object.keys(resource.attributes ?? {}).filter((k) => k.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)).sort().map((k) => this.displayMasked(this.outputNameLogText(k, context), context));
|
|
27846
27858
|
const declaredText = declared.length > 0 ? declared.join(", ") : "(none)";
|
|
27847
|
-
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
27859
|
+
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}]: the nested stack '${logicalId}' declares no output named '${this.displayMasked(this.outputNameLogText(attributeName, context), context)}'. Its outputs are ${this.displayMasked(declaredText, context)}. Check the output name in the nested stack's template, and deploy the child stack again if you have just added it.`));
|
|
27848
27860
|
}
|
|
27849
27861
|
const value = await this.constructGuardedAttribute(resource, attributeName, context, logicalId);
|
|
27850
|
-
this.logger.debug(`Resolved Fn::GetAtt: ${logicalId}.${this.
|
|
27862
|
+
this.logger.debug(`Resolved Fn::GetAtt: ${logicalId}.${this.displayMasked(attributeName, context)} -> ${this.displayMasked(stringifyAttributeForLog(attributeName, this.maskValueLeaves(value, context)), context)}`);
|
|
27851
27863
|
return value;
|
|
27852
27864
|
}
|
|
27853
27865
|
/**
|
|
@@ -27898,7 +27910,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27898
27910
|
const declared = context.noEchoAttributeResources?.get(logicalId);
|
|
27899
27911
|
if ((declared === true || declared !== void 0 && declared.has(attributeName)) && context.recordedSecretValues) recordMaskOnlyValuesIn(value, context.recordedSecretValues);
|
|
27900
27912
|
if (context.redactedAttributeReads !== void 0 && carriesSecretMask(value)) {
|
|
27901
|
-
const maskedAttributeName = this.
|
|
27913
|
+
const maskedAttributeName = this.displayMasked(attributeName, context);
|
|
27902
27914
|
this.pushRedactedAttributeRead(context, {
|
|
27903
27915
|
kind: "attribute",
|
|
27904
27916
|
logicalId,
|
|
@@ -27940,7 +27952,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27940
27952
|
rejectPlaceholderArnAttribute(resource, attributeName, value, logicalId, context) {
|
|
27941
27953
|
if (!REF_RETURNS_ARN_FROM_STATE.get(resource.resourceType)?.includes(attributeName)) return;
|
|
27942
27954
|
if (typeof value !== "string" || !isPlaceholderArn(value)) return;
|
|
27943
|
-
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
27955
|
+
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resource.resourceType}: the recorded value "${stringifyValue(this.maskValueLeaves(value, context))}" is a placeholder written by a cdkd version older than issue #1681 — its region and account fields are literal wildcards, so it is not a usable ARN. Deploy the stack again so the resource's next update heals the record (cdkd now records the real ARN), or re-import the resource.`));
|
|
27944
27956
|
}
|
|
27945
27957
|
/**
|
|
27946
27958
|
* Construct resource attribute value based on resource type, refusing to
|
|
@@ -27985,7 +27997,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
27985
27997
|
async constructGuardedAttribute(resource, attributeName, context, logicalId) {
|
|
27986
27998
|
const accountInfo = await getAccountInfo(this.resolverRegion);
|
|
27987
27999
|
const value = await this.constructAttribute(resource, attributeName, context, logicalId, accountInfo);
|
|
27988
|
-
if (accountInfo.fabricated && embedsAccountId(value, accountInfo.accountId)) throw new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
28000
|
+
if (accountInfo.fabricated && embedsAccountId(value, accountInfo.accountId)) throw new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resource.resourceType}: STS did not report this deploy's account id, so cdkd would build the value from the placeholder account ${accountInfo.accountId} — structurally valid, naming a different account, and indistinguishable downstream from a real one. Fix the AWS credentials (or set AWS_ACCOUNT_ID to this deploy's account) and deploy again.`);
|
|
27989
28001
|
return value;
|
|
27990
28002
|
}
|
|
27991
28003
|
/**
|
|
@@ -28030,7 +28042,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28030
28042
|
const associations = (await ec2.send(new DescribeVpcsCommand({ VpcIds: [physicalId] }))).Vpcs?.[0]?.Ipv6CidrBlockAssociationSet || [];
|
|
28031
28043
|
const blocks = associations.filter((a) => a.Ipv6CidrBlockState?.State === "associated").map((a) => a.Ipv6CidrBlock);
|
|
28032
28044
|
if (blocks.length > 0) {
|
|
28033
|
-
this.logger.debug(`Resolved VPC Ipv6CidrBlocks for ${physicalId}: ${this.
|
|
28045
|
+
this.logger.debug(`Resolved VPC Ipv6CidrBlocks for ${physicalId}: ${this.displayMasked(JSON.stringify(this.maskValueLeaves(blocks, context)), context)}`);
|
|
28034
28046
|
return blocks;
|
|
28035
28047
|
}
|
|
28036
28048
|
if (associations.filter((a) => a.Ipv6CidrBlockState?.State === "associating").length === 0) {
|
|
@@ -28047,7 +28059,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28047
28059
|
return [];
|
|
28048
28060
|
}
|
|
28049
28061
|
case "DefaultSecurityGroup": {
|
|
28050
|
-
if (!/^vpc-[0-9a-f]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, DefaultSecurityGroup] for AWS::EC2::VPC: the state record's physical id "${
|
|
28062
|
+
if (!/^vpc-[0-9a-f]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, DefaultSecurityGroup] for AWS::EC2::VPC: the state record's physical id "${this.displayMasked(physicalId, context).slice(0, 64)}" is not a VPC id (vpc-<hex>), so cdkd will not use it as an EC2 filter value. Repair the record (cdkd import, or re-create the VPC) and deploy again.`));
|
|
28051
28063
|
const cachedGroupId = cachedVpcDefaultSecurityGroups[physicalId];
|
|
28052
28064
|
if (cachedGroupId !== void 0) return cachedGroupId;
|
|
28053
28065
|
let groupId;
|
|
@@ -28262,7 +28274,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28262
28274
|
if (resourceType === "AWS::EC2::SecurityGroup") switch (attributeName) {
|
|
28263
28275
|
case "GroupId": return physicalId;
|
|
28264
28276
|
case "VpcId": {
|
|
28265
|
-
if (!/^sg-[0-9a-f]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, VpcId] for AWS::EC2::SecurityGroup: the state record's physical id "${
|
|
28277
|
+
if (!/^sg-[0-9a-f]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, VpcId] for AWS::EC2::SecurityGroup: the state record's physical id "${this.displayMasked(physicalId, context).slice(0, 64)}" is not a security group id (sg-<hex>), so cdkd will not look it up. Repair the record (cdkd import, or re-create the security group) and deploy again.`));
|
|
28266
28278
|
const cachedVpcId = cachedSecurityGroupVpcIds[physicalId];
|
|
28267
28279
|
if (cachedVpcId !== void 0) return cachedVpcId;
|
|
28268
28280
|
let vpcId;
|
|
@@ -28356,7 +28368,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28356
28368
|
resourceType,
|
|
28357
28369
|
physicalId,
|
|
28358
28370
|
context,
|
|
28359
|
-
observed: `DescribeInstances reports no ${this.
|
|
28371
|
+
observed: `DescribeInstances reports no ${this.displayMasked(attributeName, context)} yet (${observedState})`,
|
|
28360
28372
|
remedy: settled ? "Check the instance in the console; a terminated or stopped instance has no such attribute to serve." : "Deploy without --no-wait so the instance is running before its attributes are read, or reference the attribute from a later deploy once it is."
|
|
28361
28373
|
});
|
|
28362
28374
|
}
|
|
@@ -28369,7 +28381,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28369
28381
|
const value = attributeName === "LatestVersionNumber" ? lt?.LatestVersionNumber : lt?.DefaultVersionNumber;
|
|
28370
28382
|
if (value !== void 0 && value !== null) return String(value);
|
|
28371
28383
|
} catch (err) {
|
|
28372
|
-
this.logger.warn(`DescribeLaunchTemplates(${physicalId}) failed for ${this.
|
|
28384
|
+
this.logger.warn(`DescribeLaunchTemplates(${physicalId}) failed for ${this.displayMasked(attributeName, context)}: ${this.displayMasked(err instanceof Error ? err.message : String(err), context)}`);
|
|
28373
28385
|
}
|
|
28374
28386
|
return attributeName === "LatestVersionNumber" ? "$Latest" : "$Default";
|
|
28375
28387
|
}
|
|
@@ -28379,7 +28391,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28379
28391
|
if (resourceType === "AWS::CloudFront::Distribution") switch (attributeName) {
|
|
28380
28392
|
case "Id": return physicalId;
|
|
28381
28393
|
case "DomainName": {
|
|
28382
|
-
if (!/^[A-Z0-9]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, DomainName] for AWS::CloudFront::Distribution: the state record's physical id "${
|
|
28394
|
+
if (!/^[A-Z0-9]+$/.test(physicalId)) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, DomainName] for AWS::CloudFront::Distribution: the state record's physical id "${this.displayMasked(physicalId, context).slice(0, 64)}" is not a distribution id (upper-case alphanumerics), so cdkd will not look it up. Repair the record (cdkd import, or re-create the distribution) and deploy again.`));
|
|
28383
28395
|
const cachedDomainName = cachedCloudFrontDomainNames[physicalId];
|
|
28384
28396
|
if (cachedDomainName !== void 0) return cachedDomainName;
|
|
28385
28397
|
let domainName;
|
|
@@ -28413,7 +28425,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28413
28425
|
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId, context);
|
|
28414
28426
|
}
|
|
28415
28427
|
if (resourceType === "AWS::RDS::DBProxy" || resourceType === "AWS::RDS::DBProxyEndpoint") {
|
|
28416
|
-
if (attributeName === "VpcId") throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
28428
|
+
if (attributeName === "VpcId") throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resourceType}: the state record holds no VpcId for it (the read-back that would have recorded it reported none), and the physical id "${this.displayMasked(physicalId, context)}" is a name, not a VPC id, so cdkd refuses to substitute it. Update the resource so its next deploy records the value, or reference the VPC directly.`));
|
|
28417
28429
|
return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId, context);
|
|
28418
28430
|
}
|
|
28419
28431
|
return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId, context);
|
|
@@ -28472,7 +28484,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28472
28484
|
*/
|
|
28473
28485
|
refuseUnservedAttribute(site) {
|
|
28474
28486
|
const { logicalId, attributeName, resourceType, physicalId, context, observed, remedy } = site;
|
|
28475
|
-
throw new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
28487
|
+
throw new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resourceType}: ${observed}. The physical id "${this.displayMasked(physicalId, context)}" is not a usable ${this.displayMasked(attributeName, context)}, so cdkd refuses to substitute it. ${remedy}`);
|
|
28476
28488
|
}
|
|
28477
28489
|
/**
|
|
28478
28490
|
* The `observed` clause of {@link refuseUnservedAttribute} for a live read
|
|
@@ -28484,7 +28496,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28484
28496
|
const name = displaySafe(err instanceof Error && err.name ? err.name : "Error", { asciiOnly: true }).slice(0, 64).trim() || "Error";
|
|
28485
28497
|
const status = err?.$metadata?.httpStatusCode;
|
|
28486
28498
|
const errorClass = typeof status === "number" && Number.isInteger(status) ? `${name}, HTTP ${status}` : name;
|
|
28487
|
-
this.logger.debug(`${read} failed (${errorClass}): ${this.
|
|
28499
|
+
this.logger.debug(`${read} failed (${errorClass}): ${this.displayMasked(err instanceof Error ? err.message : String(err), context)}`);
|
|
28488
28500
|
return `${read} failed (${errorClass}); re-run with --verbose for the AWS error text`;
|
|
28489
28501
|
}
|
|
28490
28502
|
/**
|
|
@@ -28519,11 +28531,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28519
28531
|
const expectsUrlShape = attributeName.endsWith("Url") && !/^https?:\/\//.test(physicalId);
|
|
28520
28532
|
if (expectsArnShape || expectsUrlShape) {
|
|
28521
28533
|
const expectedShape = expectsArnShape ? "an ARN (arn:...)" : "a URL (http(s)://...)";
|
|
28522
|
-
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
28534
|
+
throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resourceType}: attributes are not enriched for this resource type, and the physical ID fallback "${this.displayMasked(physicalId, context)}" is not ${expectedShape}. CloudFormation would return a different value here, so falling back to the physical ID would silently produce a wrong value (e.g. in stack Outputs). Avoid this Fn::GetAtt, or file an issue at https://github.com/go-to-k/cdkd/issues so cdkd can enrich ${resourceType}.${this.displayMasked(attributeName, context)}.`));
|
|
28523
28535
|
}
|
|
28524
|
-
if (this.strictGetAtt) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.
|
|
28536
|
+
if (this.strictGetAtt) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.displayMasked(attributeName, context)}] for ${resourceType}: attributes are not enriched for this resource type, and --strict-getatt rejects the physical ID fallback "${this.displayMasked(physicalId, context)}" (which may not be the value CloudFormation would return). Drop --strict-getatt to fall back with a warning, avoid this Fn::GetAtt, or file an issue at https://github.com/go-to-k/cdkd/issues so cdkd can enrich ${resourceType}.${this.displayMasked(attributeName, context)}.`));
|
|
28525
28537
|
this.physicalIdFallbackCount++;
|
|
28526
|
-
this.logger.warn(`Unknown attribute ${this.
|
|
28538
|
+
this.logger.warn(`Unknown attribute ${this.displayMasked(attributeName, context)} for resource type ${resourceType}, returning physical ID`);
|
|
28527
28539
|
return physicalId;
|
|
28528
28540
|
}
|
|
28529
28541
|
/**
|
|
@@ -28594,7 +28606,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28594
28606
|
complete
|
|
28595
28607
|
});
|
|
28596
28608
|
this.rememberLogTwin(context, result, twin);
|
|
28597
|
-
this.logger.debug(`Resolved Fn::Join: ${this.
|
|
28609
|
+
this.logger.debug(`Resolved Fn::Join: ${this.displayMasked(this.logTwinText(result, twin, context), context)}`);
|
|
28598
28610
|
return result;
|
|
28599
28611
|
}
|
|
28600
28612
|
/**
|
|
@@ -28799,13 +28811,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28799
28811
|
} catch (getAttError) {
|
|
28800
28812
|
if (getAttError instanceof IntrinsicResolutionRefusalError) throw getAttError;
|
|
28801
28813
|
this.rethrowStructuralSubFailure(varNameStr, getAttError, context);
|
|
28802
|
-
this.logger.warn(this.
|
|
28814
|
+
this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, getAttError), context));
|
|
28803
28815
|
replacement = match[0];
|
|
28804
28816
|
}
|
|
28805
28817
|
else {
|
|
28806
28818
|
if (refError instanceof IntrinsicResolutionRefusalError) throw refError;
|
|
28807
28819
|
this.rethrowStructuralSubFailure(varNameStr, refError, context);
|
|
28808
|
-
this.logger.warn(this.
|
|
28820
|
+
this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, refError), context));
|
|
28809
28821
|
replacement = match[0];
|
|
28810
28822
|
}
|
|
28811
28823
|
}
|
|
@@ -28843,7 +28855,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28843
28855
|
complete
|
|
28844
28856
|
});
|
|
28845
28857
|
this.rememberLogTwin(context, result, twin);
|
|
28846
|
-
this.logger.debug(`Resolved Fn::Sub: ${this.
|
|
28858
|
+
this.logger.debug(`Resolved Fn::Sub: ${this.displayMasked(this.logTwinText(result, twin, context), context)}`);
|
|
28847
28859
|
return result;
|
|
28848
28860
|
}
|
|
28849
28861
|
/**
|
|
@@ -29186,7 +29198,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29186
29198
|
return recovered;
|
|
29187
29199
|
}
|
|
29188
29200
|
if (context.redactedAttributeReads !== void 0) {
|
|
29189
|
-
const loggedOrigin = this.
|
|
29201
|
+
const loggedOrigin = this.displayMasked(origin, context);
|
|
29190
29202
|
this.pushRedactedAttributeRead(context, {
|
|
29191
29203
|
kind: "cross-stack",
|
|
29192
29204
|
display: loggedOrigin
|
|
@@ -29210,7 +29222,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29210
29222
|
}
|
|
29211
29223
|
return v;
|
|
29212
29224
|
};
|
|
29213
|
-
this.logger.debug(`Re-resolving dynamic reference(s) in ${this.
|
|
29225
|
+
this.logger.debug(`Re-resolving dynamic reference(s) in ${this.displayMasked(origin, context)}`);
|
|
29214
29226
|
const reresolved = await walk(value);
|
|
29215
29227
|
if (sourceKey !== void 0 && typeof value === "string" && isSingleDynamicReferenceToken(value) && typeof reresolved === "string" && context.recordedSecretValues?.has(reresolved) === true && isSecretExpressionByVerdictOrSpelling(value)) recordCrossStackExpression(context.recordedSecretValues, sourceKey, value, reresolved);
|
|
29216
29228
|
return reresolved;
|
|
@@ -29280,7 +29292,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29280
29292
|
const target = canonicalizeRegion(producerRegion);
|
|
29281
29293
|
if (target === canonicalizeRegion(this.explicitRegion)) return this;
|
|
29282
29294
|
const regionText = producerRegionLogText !== void 0 ? canonicalizeRegion(producerRegionLogText) : this.regionLogText(producerRegion, context);
|
|
29283
|
-
const guestRegionText = this.
|
|
29295
|
+
const guestRegionText = this.displayMasked(regionText, context);
|
|
29284
29296
|
const cached = this.producerRegionResolvers.get(target);
|
|
29285
29297
|
if (cached) {
|
|
29286
29298
|
if (cached.explicitRegionLogText !== guestRegionText) cached.explicitRegionLogText = "***";
|
|
@@ -29306,20 +29318,20 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29306
29318
|
const exportName = await this.resolveValue(importValueArg, context);
|
|
29307
29319
|
if (typeof exportName !== "string") throw new Error(`Fn::ImportValue: export name must resolve to a string, got ${typeof exportName}`);
|
|
29308
29320
|
if (!context.stateBackend) throw new Error("Fn::ImportValue: state backend is required for cross-stack references");
|
|
29309
|
-
const loggedExportName = this.
|
|
29321
|
+
const loggedExportName = this.displayMasked(exportName, context);
|
|
29310
29322
|
this.logger.debug(`Resolving Fn::ImportValue: ${loggedExportName}`);
|
|
29311
29323
|
if (context.exportIndex) {
|
|
29312
29324
|
let entry;
|
|
29313
29325
|
try {
|
|
29314
29326
|
entry = await context.exportIndex.lookup(exportName);
|
|
29315
29327
|
} catch (err) {
|
|
29316
|
-
this.logger.warn(`Exports index lookup failed for '${loggedExportName}': ${this.
|
|
29328
|
+
this.logger.warn(`Exports index lookup failed for '${loggedExportName}': ${this.displayMasked(err instanceof Error ? err.message : String(err), context)}; falling back to state.json scan`);
|
|
29317
29329
|
entry = void 0;
|
|
29318
29330
|
}
|
|
29319
29331
|
if (entry && (!context.stackName || entry.producerStack !== context.stackName)) {
|
|
29320
29332
|
this.recordImport(context, exportName, entry.producerStack, entry.producerRegion);
|
|
29321
|
-
this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from index: ${this.
|
|
29322
|
-
return await this.reresolveCrossStackValue(entry.value, entry.producerRegion, context, `Fn::ImportValue '${this.
|
|
29333
|
+
this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from index: ${this.displayMasked(entry.producerStack, context)} / ${this.displayMasked(entry.producerRegion, context)}; ${carriesDynamicReference(entry.value) ? "redacted dynamic reference" : "literal value"})`);
|
|
29334
|
+
return await this.reresolveCrossStackValue(entry.value, entry.producerRegion, context, `Fn::ImportValue '${this.displayLeaf(exportName, context)}' (producer ${this.displayLeaf(entry.producerStack, context)} / ${this.displayLeaf(entry.producerRegion, context)})`, sourceKey, {
|
|
29323
29335
|
stackName: entry.producerStack,
|
|
29324
29336
|
region: entry.producerRegion,
|
|
29325
29337
|
outputKey: exportName
|
|
@@ -29332,30 +29344,30 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29332
29344
|
for (const ref of allStacks) {
|
|
29333
29345
|
const { stackName: refStack, region: refRegion } = ref;
|
|
29334
29346
|
if (context.stackName && refStack === context.stackName) {
|
|
29335
|
-
this.logger.debug(`Skipping current stack: ${this.
|
|
29347
|
+
this.logger.debug(`Skipping current stack: ${this.displayMasked(refStack, context)}`);
|
|
29336
29348
|
continue;
|
|
29337
29349
|
}
|
|
29338
29350
|
try {
|
|
29339
29351
|
const lookupRegion = refRegion ?? this.resolverRegion ?? "";
|
|
29340
29352
|
if (!lookupRegion) {
|
|
29341
|
-
this.logger.debug(`No region available for stack '${this.
|
|
29353
|
+
this.logger.debug(`No region available for stack '${this.displayMasked(refStack, context)}' — skipping (cdkd cannot read state without a region)`);
|
|
29342
29354
|
continue;
|
|
29343
29355
|
}
|
|
29344
29356
|
const stateData = await context.stateBackend.getState(refStack, lookupRegion);
|
|
29345
29357
|
if (!stateData) {
|
|
29346
|
-
this.logger.debug(`No state found for stack: ${this.
|
|
29358
|
+
this.logger.debug(`No state found for stack: ${this.displayMasked(refStack, context)} (${this.displayMasked(lookupRegion, context)})`);
|
|
29347
29359
|
continue;
|
|
29348
29360
|
}
|
|
29349
29361
|
const { state } = stateData;
|
|
29350
29362
|
if (importableOutputKeys(state).includes(exportName)) {
|
|
29351
29363
|
const value = state.outputs[exportName];
|
|
29352
|
-
this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from stack: ${this.
|
|
29364
|
+
this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from stack: ${this.displayMasked(refStack, context)} / ${this.displayMasked(lookupRegion, context)}; ${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
|
|
29353
29365
|
if (context.exportIndex) context.exportIndex.patchEntry(exportName, {
|
|
29354
29366
|
value,
|
|
29355
29367
|
producerStack: refStack,
|
|
29356
29368
|
producerRegion: lookupRegion
|
|
29357
29369
|
}).catch((err) => {
|
|
29358
|
-
this.logger.debug(`Failed to patch exports index for '${this.
|
|
29370
|
+
this.logger.debug(`Failed to patch exports index for '${this.displayMasked(exportName, context)}': ${this.displayMasked(err instanceof Error ? err.message : String(err), context)}`);
|
|
29359
29371
|
});
|
|
29360
29372
|
this.recordImport(context, exportName, refStack, lookupRegion);
|
|
29361
29373
|
found = {
|
|
@@ -29366,11 +29378,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29366
29378
|
break;
|
|
29367
29379
|
}
|
|
29368
29380
|
} catch (error) {
|
|
29369
|
-
this.logger.warn(`Failed to read state for stack ${this.
|
|
29381
|
+
this.logger.warn(`Failed to read state for stack ${this.displayMasked(refStack, context)}: ${this.displayMasked(error instanceof Error ? error.message : String(error), context)}`);
|
|
29370
29382
|
continue;
|
|
29371
29383
|
}
|
|
29372
29384
|
}
|
|
29373
|
-
if (found) return await this.reresolveCrossStackValue(found.value, found.lookupRegion, context, `Fn::ImportValue '${this.
|
|
29385
|
+
if (found) return await this.reresolveCrossStackValue(found.value, found.lookupRegion, context, `Fn::ImportValue '${this.displayLeaf(exportName, context)}' (producer ${this.displayLeaf(found.refStack, context)} / ${this.displayLeaf(found.lookupRegion, context)})`, sourceKey, {
|
|
29374
29386
|
stackName: found.refStack,
|
|
29375
29387
|
region: found.lookupRegion,
|
|
29376
29388
|
outputKey: exportName
|
|
@@ -29413,7 +29425,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29413
29425
|
};
|
|
29414
29426
|
return;
|
|
29415
29427
|
} catch (error) {
|
|
29416
|
-
this.logger.warn(`Fn::ImportValue: CloudFormation ListExports fallback failed for export '${this.
|
|
29428
|
+
this.logger.warn(`Fn::ImportValue: CloudFormation ListExports fallback failed for export '${this.displayMasked(exportName, context)}' (region ${this.resolverRegion}): ${this.displayMasked(error instanceof Error ? error.message : String(error), context)}. Grant cloudformation:ListExports to resolve exports from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
|
|
29417
29429
|
return;
|
|
29418
29430
|
}
|
|
29419
29431
|
}
|
|
@@ -29435,7 +29447,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29435
29447
|
* `OutputName` is the overwhelmingly common cause, and the list is what makes
|
|
29436
29448
|
* the error actionable.
|
|
29437
29449
|
*
|
|
29438
|
-
* `
|
|
29450
|
+
* `maskSecretsRaw` reads the consumer pass's log twin first (issue #3150),
|
|
29439
29451
|
* so a key equal to a name this pass assembled around a short secret is
|
|
29440
29452
|
* masked. Residual, stated rather than hidden: the needles and twins belong to the
|
|
29441
29453
|
* CONSUMER's resolution, so a plaintext sitting in a PRODUCER key that this
|
|
@@ -29445,7 +29457,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29445
29457
|
describeAvailableOutputs(keys, context) {
|
|
29446
29458
|
if (keys.length === 0) return "(none)";
|
|
29447
29459
|
const shown = keys.slice(0, MAX_LISTED_AVAILABLE_OUTPUTS);
|
|
29448
|
-
const rendered = shown.map((k) => this.
|
|
29460
|
+
const rendered = shown.map((k) => this.displayMasked(k, context)).join(", ");
|
|
29449
29461
|
const hidden = keys.length - shown.length;
|
|
29450
29462
|
return hidden > 0 ? `${rendered} (+${hidden} more)` : rendered;
|
|
29451
29463
|
}
|
|
@@ -29485,8 +29497,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29485
29497
|
return await fetch;
|
|
29486
29498
|
} catch (error) {
|
|
29487
29499
|
const message = error instanceof Error ? error.message : String(error);
|
|
29488
|
-
const cfnNameMask = this.positionalNameMask([[stackName, this.
|
|
29489
|
-
this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.
|
|
29500
|
+
const cfnNameMask = this.positionalNameMask([[stackName, this.displayMasked(stackName, context)], [region, this.displayMasked(loggedRegionText, context)]]);
|
|
29501
|
+
this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.displayMasked(stackName, context)}' (${this.displayMasked(loggedRegionText, context)}): ${displayAwsMessage(this.displayMasked(cfnNameMask ? cfnNameMask(message) : message, context))}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
|
|
29490
29502
|
return;
|
|
29491
29503
|
}
|
|
29492
29504
|
}
|
|
@@ -29596,7 +29608,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29596
29608
|
const resolvedRegion = await this.resolveValue(args["Region"], context);
|
|
29597
29609
|
if (typeof resolvedRegion !== "string" || resolvedRegion === "") throw new Error(`Fn::GetStackOutput: Region must resolve to a non-empty string, got ${typeof resolvedRegion}`);
|
|
29598
29610
|
const requestedRegion = canonicalizeRegion(resolvedRegion);
|
|
29599
|
-
if (!isClientSafeRegion(requestedRegion)) throw new Error(`Fn::GetStackOutput: '${this.
|
|
29611
|
+
if (!isClientSafeRegion(requestedRegion)) throw new Error(`Fn::GetStackOutput: '${this.displayMasked(this.logTextOfLeaf(resolvedRegion, context) !== resolvedRegion ? "***" : resolvedRegion, context).slice(0, 64)}' is not a valid AWS region name. The region selects both the AWS endpoint and the state-file key, so cdkd will not use it.`);
|
|
29600
29612
|
region = requestedRegion;
|
|
29601
29613
|
loggedRegionText = this.regionLogText(resolvedRegion, context);
|
|
29602
29614
|
}
|
|
@@ -29606,11 +29618,12 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29606
29618
|
if (typeof raw !== "string" || raw === "") throw new Error(`Fn::GetStackOutput: RoleArn must be a literal string in the template (no Ref / Fn::GetAtt / Fn::Sub allowed for cross-account references). Got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw}${typeof raw === "object" ? ` (intrinsic shape: ${JSON.stringify(raw).slice(0, 80)})` : ""}.`);
|
|
29607
29619
|
roleArn = raw;
|
|
29608
29620
|
}
|
|
29609
|
-
if (!roleArn && context.stackName && context.stackName === stackName && canonicalizeRegion(region) === canonicalizeRegion(this.resolverRegion)) throw new Error(`Fn::GetStackOutput: cannot reference own stack '${this.
|
|
29610
|
-
const loggedStackName = this.
|
|
29611
|
-
const loggedOutputName = this.
|
|
29612
|
-
const loggedRegion = this.
|
|
29613
|
-
|
|
29621
|
+
if (!roleArn && context.stackName && context.stackName === stackName && canonicalizeRegion(region) === canonicalizeRegion(this.resolverRegion)) throw new Error(`Fn::GetStackOutput: cannot reference own stack '${this.displayMasked(stackName, context)}' in the same region '${this.displayMasked(loggedRegionText, context)}'`);
|
|
29622
|
+
const loggedStackName = this.displayMasked(stackName, context);
|
|
29623
|
+
const loggedOutputName = this.displayMasked(outputName, context);
|
|
29624
|
+
const loggedRegion = this.displayMasked(loggedRegionText, context);
|
|
29625
|
+
const shownRoleArn = roleArn ? displayIdent(roleArn, { maxCodePoints: 613 }) : "";
|
|
29626
|
+
this.logger.debug(`Resolving Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${shownRoleArn}` : ""}`);
|
|
29614
29627
|
let stateData;
|
|
29615
29628
|
try {
|
|
29616
29629
|
stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
|
|
@@ -29630,7 +29643,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29630
29643
|
return value;
|
|
29631
29644
|
}
|
|
29632
29645
|
}
|
|
29633
|
-
throw new Error(`Fn::GetStackOutput: stack '${loggedStackName}' not found in region '${loggedRegion}'${roleArn ? ` (cross-account via ${
|
|
29646
|
+
throw new Error(`Fn::GetStackOutput: stack '${loggedStackName}' not found in region '${loggedRegion}'${roleArn ? ` (cross-account via ${shownRoleArn})` : ""}. ${!roleArn && this.cfnFallback ? "Searched cdkd state and CloudFormation stacks. Make sure the producer stack has been deployed (via cdkd or CloudFormation)." : `Make sure the producer stack has been deployed via cdkd.`}`);
|
|
29634
29647
|
}
|
|
29635
29648
|
if (!hasReadableOutputs(stateData.state)) throw markNonRetryable(new MalformedProducerRecordRefusalError(`Fn::GetStackOutput: the state record of producer stack '${loggedStackName}' (${loggedRegion}) has no readable 'outputs' map — the record is malformed or truncated. cdkd refuses to resolve from it rather than reading it as a map: 'Object.hasOwn' answers TRUE for '0' on a string and for an index on a list, so continuing would resolve ONE CHARACTER or element of the record as this reference's value and this deploy would send it to AWS. Inspect the producer's record with 'cdkd state show' --json, repair or remove it, then re-run.`));
|
|
29636
29649
|
const outputs = stateData.state.outputs ?? {};
|
|
@@ -29639,10 +29652,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29639
29652
|
throw new Error(`Fn::GetStackOutput: output '${loggedOutputName}' not found in stack '${loggedStackName}' (${loggedRegion}). Available outputs: ${available}`);
|
|
29640
29653
|
}
|
|
29641
29654
|
const value = outputs[outputName];
|
|
29642
|
-
this.logger.info(`Resolved Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${
|
|
29655
|
+
this.logger.info(`Resolved Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${shownRoleArn}` : ""} (${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
|
|
29643
29656
|
if (!roleArn) this.recordOutputRead(context, stackName, region, outputName);
|
|
29644
|
-
if (roleArn && !context.skipDynamicReferences && carriesDynamicReference(value)) throw markNonRetryable(new CrossAccountSecretRefusalError(`Fn::GetStackOutput: output '${loggedOutputName}' of stack '${loggedStackName}' (${loggedRegion}) is a redacted dynamic reference, and this is a CROSS-ACCOUNT reference (RoleArn ${
|
|
29645
|
-
return await this.reresolveCrossStackValue(value, region, context, `Fn::GetStackOutput '${this.
|
|
29657
|
+
if (roleArn && !context.skipDynamicReferences && carriesDynamicReference(value)) throw markNonRetryable(new CrossAccountSecretRefusalError(`Fn::GetStackOutput: output '${loggedOutputName}' of stack '${loggedStackName}' (${loggedRegion}) is a redacted dynamic reference, and this is a CROSS-ACCOUNT reference (RoleArn ${shownRoleArn}). cdkd will not resolve a producer account's secret with the consumer's credentials — a same-named secret in the consumer account would answer instead. Export a non-secret value (e.g. the secret's ARN) and resolve it in the consumer stack, or reference the producer stack from within its own account.`));
|
|
29658
|
+
return await this.reresolveCrossStackValue(value, region, context, `Fn::GetStackOutput '${this.displayLeaf(outputName, context)}' (producer ${this.displayLeaf(stackName, context)} / ${this.displayLeaf(loggedRegionText, context)})`, sourceKey, {
|
|
29646
29659
|
stackName,
|
|
29647
29660
|
region,
|
|
29648
29661
|
outputKey: outputName,
|
|
@@ -29698,7 +29711,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29698
29711
|
* own comment says why. What this clause is not is redundant against
|
|
29699
29712
|
* `raw !== masked`: `rememberLogTwin` has no empty-key guard and
|
|
29700
29713
|
* `splitLogTwins` registers every piece it produces, so `registeredLogTwin`
|
|
29701
|
-
* can answer `***` for the empty string and make `
|
|
29714
|
+
* can answer `***` for the empty string and make `maskSecretsRaw('')`
|
|
29702
29715
|
* differ from `''`. Neither call site can reach it — both refuse an empty
|
|
29703
29716
|
* name upstream — so it fences nothing measured today.
|
|
29704
29717
|
*
|
|
@@ -29794,7 +29807,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29794
29807
|
*/
|
|
29795
29808
|
async getCrossAccountStackState(roleArn, stackName, region, context) {
|
|
29796
29809
|
const parsed = parseIamRoleArn(roleArn);
|
|
29797
|
-
if (!parsed) throw new Error(`Fn::GetStackOutput: RoleArn '${roleArn}' is not a valid IAM role ARN. Expected shape: arn:<partition>:iam::<12-digit-account-id>:role/<role-name> (e.g. arn:aws:iam::123456789012:role/MyRole, arn:aws-us-gov:iam::...).`);
|
|
29810
|
+
if (!parsed) throw new Error(`Fn::GetStackOutput: RoleArn '${displayIdent(roleArn, { maxCodePoints: 613 })}' is not a valid IAM role ARN. Expected shape: arn:<partition>:iam::<12-digit-account-id>:role/<role-name> (e.g. arn:aws:iam::123456789012:role/MyRole, arn:aws-us-gov:iam::...).`);
|
|
29798
29811
|
const credentials = await assumeRoleForCrossAccountStateRead(roleArn);
|
|
29799
29812
|
const { bucket, region: bucketRegion } = await resolveCrossAccountStateBucket(parsed.accountId, credentials);
|
|
29800
29813
|
const prefix = context.stateBackend?.prefix ?? "cdkd";
|
|
@@ -29851,19 +29864,19 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29851
29864
|
}
|
|
29852
29865
|
if (!map) {
|
|
29853
29866
|
if (hasDefaultValue) return await resolveDefault();
|
|
29854
|
-
throw new Error(`Fn::FindInMap: mapping '${this.
|
|
29867
|
+
throw new Error(`Fn::FindInMap: mapping '${this.displayMasked(mapName, context)}' not found in Mappings section`);
|
|
29855
29868
|
}
|
|
29856
29869
|
const topLevel = Object.hasOwn(map, topLevelKey) ? map[topLevelKey] : void 0;
|
|
29857
29870
|
if (!topLevel || typeof topLevel !== "object") {
|
|
29858
29871
|
if (hasDefaultValue) return await resolveDefault();
|
|
29859
|
-
throw new Error(`Fn::FindInMap: top-level key '${this.
|
|
29872
|
+
throw new Error(`Fn::FindInMap: top-level key '${this.displayMasked(topLevelKey, context)}' not found in mapping '${this.displayMasked(mapName, context)}'`);
|
|
29860
29873
|
}
|
|
29861
29874
|
if (!Object.hasOwn(topLevel, secondLevelKey)) {
|
|
29862
29875
|
if (hasDefaultValue) return await resolveDefault();
|
|
29863
|
-
throw new Error(`Fn::FindInMap: second-level key '${this.
|
|
29876
|
+
throw new Error(`Fn::FindInMap: second-level key '${this.displayMasked(secondLevelKey, context)}' not found in mapping '${this.displayMasked(mapName, context)}' -> '${this.displayMasked(topLevelKey, context)}'`);
|
|
29864
29877
|
}
|
|
29865
29878
|
const result = topLevel[secondLevelKey];
|
|
29866
|
-
this.logger.debug(`Resolved Fn::FindInMap: ${this.
|
|
29879
|
+
this.logger.debug(`Resolved Fn::FindInMap: ${this.displayMasked(mapName, context)}.${this.displayMasked(topLevelKey, context)}.${this.displayMasked(secondLevelKey, context)} -> ${this.displayMasked(JSON.stringify(this.maskValueLeaves(result, context)), context)}`);
|
|
29867
29880
|
return result;
|
|
29868
29881
|
}
|
|
29869
29882
|
/**
|
|
@@ -29878,7 +29891,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29878
29891
|
const result = Buffer.from(resolvedValue).toString("base64");
|
|
29879
29892
|
const inputLogText = this.logTextOfLeaf(resolvedValue, context);
|
|
29880
29893
|
if (context.recordedSecretValues && (inputLogText !== resolvedValue || this.maskNeedlesForLog(resolvedValue, context) !== resolvedValue)) recordMaskOnlyValue(context.recordedSecretValues, result);
|
|
29881
|
-
this.logger.debug(`Resolved Fn::Base64: ${this.
|
|
29894
|
+
this.logger.debug(`Resolved Fn::Base64: ${this.displayMasked(inputLogText, context)} -> ${this.displayMasked(inputLogText !== resolvedValue ? "***" : result, context)}`);
|
|
29882
29895
|
return result;
|
|
29883
29896
|
}
|
|
29884
29897
|
/**
|
|
@@ -29910,7 +29923,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29910
29923
|
let loggedRegionText;
|
|
29911
29924
|
if (typeof resolvedValue === "string" && resolvedValue !== "") {
|
|
29912
29925
|
const requested = canonicalizeRegion(resolvedValue);
|
|
29913
|
-
if (!isClientSafeRegion(requested)) throw new Error(`Fn::GetAZs: '${this.
|
|
29926
|
+
if (!isClientSafeRegion(requested)) throw new Error(`Fn::GetAZs: '${this.displayMasked(this.logTextOfLeaf(resolvedValue, context) !== resolvedValue ? "***" : resolvedValue, context).slice(0, 64)}' is not a valid AWS region name. A region is substituted into the AWS service hostname, so cdkd will not build a client from it.`);
|
|
29914
29927
|
region = requested;
|
|
29915
29928
|
clientRegion = requested;
|
|
29916
29929
|
loggedRegionText = this.regionLogText(resolvedValue, context);
|
|
@@ -29920,10 +29933,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29920
29933
|
}
|
|
29921
29934
|
const cached = cachedAvailabilityZones[region];
|
|
29922
29935
|
if (cached) {
|
|
29923
|
-
this.logger.debug(`Resolved Fn::GetAZs from cache: ${this.
|
|
29936
|
+
this.logger.debug(`Resolved Fn::GetAZs from cache: ${this.displayMasked(loggedRegionText ?? region, context)} -> ${JSON.stringify(this.maskValueLeaves(cached, context))}`);
|
|
29924
29937
|
return cached;
|
|
29925
29938
|
}
|
|
29926
|
-
const ec2Client = this.clientsForRegion(clientRegion, loggedRegionText === void 0 ? void 0 : this.
|
|
29939
|
+
const ec2Client = this.clientsForRegion(clientRegion, loggedRegionText === void 0 ? void 0 : this.displayMasked(loggedRegionText, context)).ec2;
|
|
29927
29940
|
let azNames;
|
|
29928
29941
|
try {
|
|
29929
29942
|
azNames = ((await ec2Client.send(new DescribeAvailabilityZonesCommand({ Filters: [{
|
|
@@ -29934,11 +29947,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29934
29947
|
Values: ["available"]
|
|
29935
29948
|
}] }))).AvailabilityZones || []).map((az) => az.ZoneName).filter((name) => name !== void 0).sort();
|
|
29936
29949
|
} catch (error) {
|
|
29937
|
-
throw new Error(`Fn::GetAZs: failed to describe availability zones for region '${this.
|
|
29950
|
+
throw new Error(`Fn::GetAZs: failed to describe availability zones for region '${this.displayMasked(loggedRegionText ?? region, context)}': ${this.displayMasked(error instanceof Error ? error.message : String(error), context)}`);
|
|
29938
29951
|
}
|
|
29939
|
-
if (azNames.length === 0) throw new Error(`Fn::GetAZs: no availability zones returned for region '${this.
|
|
29952
|
+
if (azNames.length === 0) throw new Error(`Fn::GetAZs: no availability zones returned for region '${this.displayMasked(loggedRegionText ?? region, context)}'. Either the region is not enabled on this account (opt-in regions must be enabled before use), or the request was answered by a different region's endpoint.`);
|
|
29940
29953
|
cachedAvailabilityZones[region] = azNames;
|
|
29941
|
-
this.logger.debug(`Resolved Fn::GetAZs: ${this.
|
|
29954
|
+
this.logger.debug(`Resolved Fn::GetAZs: ${this.displayMasked(loggedRegionText ?? region, context)} -> ${JSON.stringify(this.maskValueLeaves(azNames, context))}`);
|
|
29942
29955
|
return azNames;
|
|
29943
29956
|
}
|
|
29944
29957
|
/**
|
|
@@ -29972,9 +29985,31 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29972
29985
|
* Results are cached to avoid repeated API calls.
|
|
29973
29986
|
*/
|
|
29974
29987
|
/**
|
|
29975
|
-
*
|
|
29976
|
-
* the secrets recorded on the resolution pass (GHSA fix). No-op when
|
|
29977
|
-
* recorded no secrets.
|
|
29988
|
+
* The SECRET answer alone: mask any resolved secret value out of `text`,
|
|
29989
|
+
* using the secrets recorded on the resolution pass (GHSA fix). No-op when
|
|
29990
|
+
* the pass recorded no secrets.
|
|
29991
|
+
*
|
|
29992
|
+
* ## NOT a display form, and the name says so
|
|
29993
|
+
*
|
|
29994
|
+
* This was `maskSecretsForLog` until go-to-k/cdkd#3426, and the name was the
|
|
29995
|
+
* defect. It answers "does this text contain a recorded secret" and makes no
|
|
29996
|
+
* claim about CONTROL CHARACTERS — but it read as "the spelling a log line
|
|
29997
|
+
* takes", so TEN local bindings took its result and interpolated it later,
|
|
29998
|
+
* one of them reaching an `Fn::ImportValue` warn and throw with a live
|
|
29999
|
+
* `ESC[2K` + CR from a template-supplied export name (measured on this tree,
|
|
30000
|
+
* at DEFAULT verbosity, on the DEFAULT path). Renaming it is what makes the
|
|
30001
|
+
* hazard visible at the BINDING rather than at the render: `const x =
|
|
30002
|
+
* this.maskSecretsRaw(...)` states that more work is owed.
|
|
30003
|
+
*
|
|
30004
|
+
* Reachable from ONE place, {@link maskThenStripThenMask}, which is itself
|
|
30005
|
+
* reachable only from {@link displayMasked}. That containment is the whole
|
|
30006
|
+
* mechanism and it is enforced, not conventional:
|
|
30007
|
+
* `scripts/check-resolver-mask-coverage.ts` does not list this method in
|
|
30008
|
+
* `MASKERS`, so its AST walk — which RESOLVES an interpolated identifier to
|
|
30009
|
+
* its declaration — reports any render that reaches it, through a binding or
|
|
30010
|
+
* directly. Do not add it to that list, and do not call it from a new site.
|
|
30011
|
+
*
|
|
30012
|
+
* ## What the masking itself does
|
|
29978
30013
|
*
|
|
29979
30014
|
* A value with a registered LOG TWIN prints as its twin first (issue
|
|
29980
30015
|
* [#3150](https://github.com/go-to-k/cdkd/issues/3150)). The needle mask
|
|
@@ -29984,7 +30019,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29984
30019
|
* reference) printed in the clear at every site that handed its RAW value
|
|
29985
30020
|
* here, although the pass had registered where the secret sits. Looking the
|
|
29986
30021
|
* twin up HERE, rather than at each such site, is what makes the class
|
|
29987
|
-
* closed for raw values: every one of those sites already
|
|
30022
|
+
* closed for raw values: every one of those sites already reaches this
|
|
30023
|
+
* method through the builder.
|
|
29988
30024
|
* The twin prints as it is: it is the raw text with masked spans, so it
|
|
29989
30025
|
* holds no recorded needle the raw text lacks. When the needle mask ALSO
|
|
29990
30026
|
* changes the raw text the whole text is masked instead, the rule
|
|
@@ -29992,8 +30028,21 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29992
30028
|
* cannot be merged. What this cannot see is a value TRANSFORMED before it
|
|
29993
30029
|
* arrives (a lowercased region, a sliced output name, an assembled
|
|
29994
30030
|
* sentence); those sites derive their text from the twin themselves.
|
|
30031
|
+
*
|
|
30032
|
+
* ## The SELF-COMPARISON, and why it did not block the strip
|
|
30033
|
+
*
|
|
30034
|
+
* The line below compares `maskNeedlesForLog(text) !== text` — the NEEDLE
|
|
30035
|
+
* mask, not this method's own result — so making the RENDER path strip
|
|
30036
|
+
* changes no comparison anywhere. An earlier revision of `displayMasked`'s
|
|
30037
|
+
* comment said stripping could not move inside "the masker" because its
|
|
30038
|
+
* result is also a comparison; that was a claim about this expression, and
|
|
30039
|
+
* the expression's operand is a different function. The measurement that
|
|
30040
|
+
* settled it: every one of this method's 20 escaping call sites rendered
|
|
30041
|
+
* into a log line, a throw, or a `display:` field that becomes one — none
|
|
30042
|
+
* compared, persisted or re-parsed the result — so the render path could
|
|
30043
|
+
* take the strip whole.
|
|
29995
30044
|
*/
|
|
29996
|
-
|
|
30045
|
+
maskSecretsRaw(text, context) {
|
|
29997
30046
|
const registered = this.registeredLogTwin(text, context);
|
|
29998
30047
|
if (registered === void 0) return this.maskNeedlesForLog(text, context);
|
|
29999
30048
|
return this.maskNeedlesForLog(text, context) !== text ? "***" : registered;
|
|
@@ -30012,19 +30061,19 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30012
30061
|
const raw = error instanceof Error ? error.message : String(error);
|
|
30013
30062
|
return {
|
|
30014
30063
|
unit,
|
|
30015
|
-
subject: this.
|
|
30016
|
-
message: this.
|
|
30064
|
+
subject: this.displayMasked(subject, context),
|
|
30065
|
+
message: this.displayMasked(preRedact === void 0 ? raw : preRedact(raw), context),
|
|
30017
30066
|
error,
|
|
30018
30067
|
carriedDynamicReference: carriesDynamicReference(rawInput),
|
|
30019
30068
|
carriedFetchableReference: carriesFetchableDynamicReference(rawInput)
|
|
30020
30069
|
};
|
|
30021
30070
|
}
|
|
30022
30071
|
/**
|
|
30023
|
-
* The needle mask alone: {@link
|
|
30072
|
+
* The needle mask alone: {@link maskSecretsRaw} without the log-twin
|
|
30024
30073
|
* lookup. For the two DETECTORS that must ask the needle mask apart from the
|
|
30025
30074
|
* position mask: `logTwinText`, which asks it of a value that already has a
|
|
30026
30075
|
* twin, and `resolveBase64`, whose other operand is the position mask. A
|
|
30027
|
-
* message masks through `
|
|
30076
|
+
* message masks through `displayMasked`.
|
|
30028
30077
|
*/
|
|
30029
30078
|
maskNeedlesForLog(text, context) {
|
|
30030
30079
|
let masked = text;
|
|
@@ -30052,7 +30101,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30052
30101
|
* part of it outside the span. The value's own needle mask cannot be merged
|
|
30053
30102
|
* with the twin's positions, so the line gives both up for `***`: never
|
|
30054
30103
|
* more text than either mask alone would print. Returns the text BEFORE the
|
|
30055
|
-
* needle mask; each log line wraps it in `
|
|
30104
|
+
* needle mask; each log line wraps it in `displayMasked` itself, so the
|
|
30056
30105
|
* resolver's mask-coverage checker sees a masker at the site.
|
|
30057
30106
|
*/
|
|
30058
30107
|
logTwinText(result, twin, context) {
|
|
@@ -30104,12 +30153,12 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30104
30153
|
* the leaf treated as a resolution product — masked whole when it is a
|
|
30105
30154
|
* recorded secret, otherwise the masked twin this pass registered for it —
|
|
30106
30155
|
* and then `logTwinText`'s whole-line guard. The caller still wraps the
|
|
30107
|
-
* result in `
|
|
30156
|
+
* result in `displayMasked`. Used where the text is needed BEFORE that
|
|
30108
30157
|
* masker, or apart from it: the `Fn::Base64` line and its detector, and the
|
|
30109
30158
|
* names issue [#3150](https://github.com/go-to-k/cdkd/issues/3150)
|
|
30110
30159
|
* transforms or composes before printing (`regionLogText`,
|
|
30111
30160
|
* `outputNameLogText`, the invalid-region refusals, the cross-stack `origin`
|
|
30112
|
-
* strings). A leaf printed as it is needs none of it: `
|
|
30161
|
+
* strings). A leaf printed as it is needs none of it: `displayMasked`
|
|
30113
30162
|
* looks the twin up itself, which is how `maskValueLeaves` gives its lines
|
|
30114
30163
|
* and the THROWN messages it masks (the `Fn::Cidr` argument refusals, for
|
|
30115
30164
|
* one) the same position mask.
|
|
@@ -30349,7 +30398,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30349
30398
|
maskValueLeaves(value, context) {
|
|
30350
30399
|
const done = /* @__PURE__ */ new Map();
|
|
30351
30400
|
const walk = (node) => {
|
|
30352
|
-
if (typeof node === "string") return this.
|
|
30401
|
+
if (typeof node === "string") return this.displayMasked(node, context);
|
|
30353
30402
|
if (node === null || typeof node !== "object") return node;
|
|
30354
30403
|
const memo = done.get(node);
|
|
30355
30404
|
if (memo !== void 0) return memo;
|
|
@@ -30361,7 +30410,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30361
30410
|
}
|
|
30362
30411
|
const out = Object.create(null);
|
|
30363
30412
|
done.set(node, out);
|
|
30364
|
-
for (const [key, child] of Object.entries(node)) out[this.
|
|
30413
|
+
for (const [key, child] of Object.entries(node)) out[this.displayMasked(key, context)] = walk(child);
|
|
30365
30414
|
return out;
|
|
30366
30415
|
};
|
|
30367
30416
|
return walk(value);
|
|
@@ -30392,10 +30441,18 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30392
30441
|
* of the text in hand. A value this resolver resolved cannot be that text
|
|
30393
30442
|
* (the split copy is itself recorded, so the first mask catches it), but a
|
|
30394
30443
|
* template LITERAL can: issue #3150's region-scoped clients refusal prints
|
|
30395
|
-
* a producer-region guest's region through
|
|
30396
|
-
* region spelling a recorded `st-1` as `s` + U+0001 + `t-1` is
|
|
30397
|
-
* by the second pass
|
|
30398
|
-
* pins both halves on
|
|
30444
|
+
* a producer-region guest's region through {@link displayMasked}, and a
|
|
30445
|
+
* literal ARN region spelling a recorded `st-1` as `s` + U+0001 + `t-1` is
|
|
30446
|
+
* masked only by the second pass
|
|
30447
|
+
* (`intrinsic-resolver-name-argument-log-twin.test.ts` pins both halves on
|
|
30448
|
+
* that route).
|
|
30449
|
+
*
|
|
30450
|
+
* ONE CALLER, {@link displayMasked}, since go-to-k/cdkd#3426. It is most of
|
|
30451
|
+
* the answer and reads like all of it — it omits `displaySafe`, and
|
|
30452
|
+
* therefore `U+2028` / `U+2029` and the bidi overrides — so a site reaching
|
|
30453
|
+
* for it directly is the near-miss back onto the treadmill. It is not in
|
|
30454
|
+
* `MASKERS` in `scripts/check-resolver-mask-coverage.ts`, so a render that
|
|
30455
|
+
* reaches it (through a binding or directly) is reported there.
|
|
30399
30456
|
*
|
|
30400
30457
|
* THE BOUND, since this file's job is to state them: this covers a needle
|
|
30401
30458
|
* split by a character `stripControlChars` removes. A needle split by
|
|
@@ -30404,7 +30461,109 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30404
30461
|
* solved here.
|
|
30405
30462
|
*/
|
|
30406
30463
|
maskThenStripThenMask(value, context) {
|
|
30407
|
-
return this.
|
|
30464
|
+
return this.maskSecretsRaw(stripControlChars(this.maskSecretsRaw(value, context)), context);
|
|
30465
|
+
}
|
|
30466
|
+
/**
|
|
30467
|
+
* The ONE way a masked value reaches a message in this file — and, since
|
|
30468
|
+
* go-to-k/cdkd#3426, the ONLY exit from the masking machinery at all.
|
|
30469
|
+
*
|
|
30470
|
+
* ## Why this exists rather than a rule about call sites
|
|
30471
|
+
*
|
|
30472
|
+
* {@link maskSecretsRaw} answers "does this text contain a recorded secret"
|
|
30473
|
+
* and makes NO claim about control characters. That split produced a
|
|
30474
|
+
* four-round treadmill on go-to-k/cdkd#3408. Round 1 found the four
|
|
30475
|
+
* `Fn::GetStackOutput` throws rendering a masked name raw and fixed them.
|
|
30476
|
+
* Round 2 found the CloudFormation-fallback warn — the DEFAULT path, at
|
|
30477
|
+
* DEFAULT verbosity — and the self-reference throw. Round 3 found the
|
|
30478
|
+
* `reresolveCrossStackValue` origin builder and `describeAvailableOutputs`.
|
|
30479
|
+
* Each round fixed what it found and the next round found more, because the
|
|
30480
|
+
* population was never enumerated. Measured 2026-09-19 with a
|
|
30481
|
+
* comment-stripped scan: SEVENTY-ONE interpolations rendered a bare masker
|
|
30482
|
+
* result directly, plus thirteen hand-spelled
|
|
30483
|
+
* `displaySafe(maskThenStripThenMask(...))` compositions and two bare
|
|
30484
|
+
* `maskThenStripThenMask` interpolations — and three reviewers between them
|
|
30485
|
+
* reached eight of the eighty-six.
|
|
30486
|
+
*
|
|
30487
|
+
* ROUND FIVE was the BINDING shape: `const loggedExportName =
|
|
30488
|
+
* this.<masker>(...)` interpolated later, which a line-shaped scanner
|
|
30489
|
+
* forbidding `${this.<masker>(` structurally cannot see. Ten of them existed,
|
|
30490
|
+
* and `loggedExportName` was a LIVE exposure — an `Fn::ImportValue` export
|
|
30491
|
+
* name carrying `ESC[2K` + CR reached a warn AND a throw unstripped, at
|
|
30492
|
+
* default verbosity on the default path.
|
|
30493
|
+
*
|
|
30494
|
+
* Patching those ten sites would have been the fifth round of one
|
|
30495
|
+
* enumeration. What closes the class instead is that there is no longer a
|
|
30496
|
+
* masking answer a site can reach WITHOUT the strip: every escaping call of
|
|
30497
|
+
* the old `maskSecretsForLog` now calls this builder, the raw masker is
|
|
30498
|
+
* reachable only through {@link maskThenStripThenMask}, and that helper is
|
|
30499
|
+
* reachable only from here.
|
|
30500
|
+
*
|
|
30501
|
+
* ## What keeps it closed
|
|
30502
|
+
*
|
|
30503
|
+
* `scripts/check-resolver-mask-coverage.ts` — an AST walk that already
|
|
30504
|
+
* RESOLVES an interpolated identifier to its declaration and judges the
|
|
30505
|
+
* initializer. Its `MASKERS` list names the functions a render may reach,
|
|
30506
|
+
* and since go-to-k/cdkd#3426 every entry on it SANITIZES as well as masks.
|
|
30507
|
+
* So a binding of a raw masker is a finding wherever it is later
|
|
30508
|
+
* interpolated, by the same mechanism that already answered the secret
|
|
30509
|
+
* question — no second scanner, and nothing line-shaped.
|
|
30510
|
+
* `tests/unit/deployment/resolver-display-masked-population.test.ts` pins the
|
|
30511
|
+
* population and the builder bodies beside it.
|
|
30512
|
+
*
|
|
30513
|
+
* KNOWN BOUND, stated rather than implied away: a site carrying an
|
|
30514
|
+
* exclusion marker is exempt from that walk, because the marker answers the
|
|
30515
|
+
* SECRET question ("this value cannot carry a plaintext"), which is not the
|
|
30516
|
+
* control-character question. Such a site sanitizes by hand or not at all —
|
|
30517
|
+
* `clientsForRegion`'s two region renders are both markered, and both
|
|
30518
|
+
* sanitize. Widening the walk to judge every interpolated value is
|
|
30519
|
+
* go-to-k/cdkd#3405's mixed-render scope, not this builder's.
|
|
30520
|
+
*
|
|
30521
|
+
* (The marker's literal spelling is deliberately not written in this comment:
|
|
30522
|
+
* the checker scans the raw text for it, and a prose mention parses as a
|
|
30523
|
+
* marker no site consumes — which it then reports STALE. Measured while
|
|
30524
|
+
* writing this paragraph.)
|
|
30525
|
+
*
|
|
30526
|
+
* ## What it does, in order
|
|
30527
|
+
*
|
|
30528
|
+
* `maskThenStripThenMask` first — mask, strip, mask — because
|
|
30529
|
+
* `stripControlChars` DELETES, so a plaintext split by an invisible would be
|
|
30530
|
+
* reconstituted contiguous by a strip applied after a single mask. Then
|
|
30531
|
+
* `displaySafe`, which covers the class `stripControlChars` does not:
|
|
30532
|
+
* `U+2028` / `U+2029` (line terminators to JSON and web log viewers) and the
|
|
30533
|
+
* Trojan-Source bidi overrides. That composition is what the `physicalId`
|
|
30534
|
+
* renders here already spelled by hand; this names it, and they now share it.
|
|
30535
|
+
*
|
|
30536
|
+
* It is listed in `MASKERS` in `scripts/check-resolver-mask-coverage.ts`,
|
|
30537
|
+
* which is a SECURITY decision and a sound one: every path through it passes
|
|
30538
|
+
* the needle-and-twin mask, twice, so it is strictly stronger than the bare
|
|
30539
|
+
* masker it replaced and cannot be weaker at any input.
|
|
30540
|
+
*/
|
|
30541
|
+
displayMasked(value, context) {
|
|
30542
|
+
return displaySafe(this.maskThenStripThenMask(value, context));
|
|
30543
|
+
}
|
|
30544
|
+
/**
|
|
30545
|
+
* The display form of a LOG-TWIN leaf — the second render route, named for
|
|
30546
|
+
* the same reason as {@link displayMasked} and closed by the same scanner.
|
|
30547
|
+
*
|
|
30548
|
+
* `logTextOfLeaf` resolves a value to its registered twin (or `SECRET_MASK`),
|
|
30549
|
+
* which is a MASKING answer and, like `maskSecretsRaw`'s, says nothing
|
|
30550
|
+
* about control characters. Four `origin` builders interpolated it raw — the
|
|
30551
|
+
* `Fn::ImportValue` pair, the `Fn::GetStackOutput` one and the nested-stack
|
|
30552
|
+
* attribute one — and those strings flow into `redactedAttributeReads[].display`
|
|
30553
|
+
* and out through a `ProvisioningError` message.
|
|
30554
|
+
*
|
|
30555
|
+
* This route is why fixing the secret masker alone did not close the class:
|
|
30556
|
+
* `displayMasked` covers every site that renders a needle-masked value, and
|
|
30557
|
+
* these render something else. Two routes, two names, one checker refusing
|
|
30558
|
+
* the raw form of both.
|
|
30559
|
+
*
|
|
30560
|
+
* Composed rather than re-derived. `maskSecretsInText` is idempotent (see
|
|
30561
|
+
* {@link maskThenStripThenMask}), so masking twin text again costs nothing
|
|
30562
|
+
* and cannot change the twin — which keeps this a STRICT addition of the
|
|
30563
|
+
* strip and the `displaySafe` pass, with the twin resolution untouched.
|
|
30564
|
+
*/
|
|
30565
|
+
displayLeaf(value, context) {
|
|
30566
|
+
return this.displayMasked(this.logTextOfLeaf(value, context), context);
|
|
30408
30567
|
}
|
|
30409
30568
|
async resolveDynamicReferences(value, context) {
|
|
30410
30569
|
return (await this.resolveDynamicReferencesWithLogTwin(value, value, context)).result;
|
|
@@ -30455,7 +30614,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30455
30614
|
continue;
|
|
30456
30615
|
}
|
|
30457
30616
|
const regionVerdict = classifyReplaySecretRegion(fullMatch, this.explicitRegion ?? this.resolverRegion, context?.producerRegions);
|
|
30458
|
-
if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${this.
|
|
30617
|
+
if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${this.displayMasked(tokenLogText, context)}: it names '${this.displayMasked(nameLogText(regionVerdict.secretName), context)}' without a region, and this stack reads from ${this.displayMasked(regionVerdict.foreignProducerRegions.map((r) => this.displayMasked(r, context)).join(", "), context)} as well as its own region. cdkd cannot tell which one must answer, and resolving against the wrong one yields a different secret. Spell the reference as a full ARN to say which region owns it.`));
|
|
30459
30618
|
if (regionVerdict.kind === "named-region") {
|
|
30460
30619
|
const foreign = await this.resolverForProducerRegion(regionVerdict.region, context, nameLogText(regionVerdict.region)).resolveDynamicReferencesWithLogTwin(fullMatch, fullMatch, withoutProducerRegions(context), {
|
|
30461
30620
|
tokenLogText,
|
|
@@ -30520,11 +30679,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30520
30679
|
resolved = param.value;
|
|
30521
30680
|
} else if (service === "ssm-secure") {
|
|
30522
30681
|
const param = await this.resolveSSMReference(parts, true, "ssm-secure", context, nameLogText);
|
|
30523
|
-
if (!param.secure) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to resolve ${this.
|
|
30682
|
+
if (!param.secure) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to resolve ${this.displayMasked(tokenLogText, context)}: the parameter is a ${param.type} parameter, and the ssm-secure spelling is defined for SecureString parameters only. Reference it as {{resolve:ssm:...}} if it is public configuration.`));
|
|
30524
30683
|
isSecret = true;
|
|
30525
30684
|
resolved = param.value;
|
|
30526
30685
|
} else {
|
|
30527
|
-
this.logger.warn(this.
|
|
30686
|
+
this.logger.warn(this.displayMasked(`Unsupported dynamic reference service: ${this.displayMasked(nameLogText(String(service)), context)}`, context));
|
|
30528
30687
|
complete = false;
|
|
30529
30688
|
continue;
|
|
30530
30689
|
}
|
|
@@ -30612,9 +30771,9 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30612
30771
|
} else secretId = afterService;
|
|
30613
30772
|
if (!versionStage) versionStage = "AWSCURRENT";
|
|
30614
30773
|
if (!secretId) throw new Error("Dynamic reference: secretsmanager SECRET_ID is required");
|
|
30615
|
-
const loggedSecretId = this.
|
|
30616
|
-
const loggedJsonKey = this.
|
|
30617
|
-
this.logger.debug(`Resolving dynamic reference: secretsmanager:${loggedSecretId}:SecretString:${loggedJsonKey}:${this.
|
|
30774
|
+
const loggedSecretId = this.displayMasked(nameLogText(secretId), context);
|
|
30775
|
+
const loggedJsonKey = this.displayMasked(nameLogText(jsonKey), context);
|
|
30776
|
+
this.logger.debug(`Resolving dynamic reference: secretsmanager:${loggedSecretId}:SecretString:${loggedJsonKey}:${this.displayMasked(nameLogText(versionStage), context)}:${this.displayMasked(nameLogText(versionId), context)}`);
|
|
30618
30777
|
const client = this.clientsForRegion(this.explicitRegion).secretsManager;
|
|
30619
30778
|
const command = new GetSecretValueCommand({
|
|
30620
30779
|
SecretId: secretId,
|
|
@@ -30656,7 +30815,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30656
30815
|
const count = Number(await this.resolveValue(rawCount, context));
|
|
30657
30816
|
const cidrBits = Number(await this.resolveValue(rawCidrBits, context));
|
|
30658
30817
|
if (!ipBlock || typeof ipBlock !== "string") throw new Error(`Fn::Cidr: ipBlock must be a string, got ${typeof ipBlock}: ${JSON.stringify(this.maskValueLeaves(ipBlock, context))}`);
|
|
30659
|
-
this.logger.debug(`Resolving Fn::Cidr: ipBlock=${this.
|
|
30818
|
+
this.logger.debug(`Resolving Fn::Cidr: ipBlock=${this.displayMasked(JSON.stringify(this.maskValueLeaves(ipBlock, context)), context)}, count=${count}, cidrBits=${cidrBits}`);
|
|
30660
30819
|
const isIpv6 = ipBlock.includes(":");
|
|
30661
30820
|
const results = [];
|
|
30662
30821
|
if (isIpv6) {
|
|
@@ -30688,7 +30847,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30688
30847
|
results.push(`${a}.${b}.${c}.${d}/${subnetPrefix}`);
|
|
30689
30848
|
}
|
|
30690
30849
|
}
|
|
30691
|
-
this.logger.debug(`Fn::Cidr result: ${this.
|
|
30850
|
+
this.logger.debug(`Fn::Cidr result: ${this.displayMasked(JSON.stringify(this.maskValueLeaves(results, context)), context)}`);
|
|
30692
30851
|
return results;
|
|
30693
30852
|
}
|
|
30694
30853
|
/** Expand IPv6 address to full 8-group form */
|
|
@@ -30778,7 +30937,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30778
30937
|
async resolveSSMReference(parts, decrypt, service, context, nameLogText) {
|
|
30779
30938
|
const parameterName = parts.slice(1).join(":");
|
|
30780
30939
|
if (!parameterName) throw new Error(`Dynamic reference: ${service} PARAMETER_NAME is required`);
|
|
30781
|
-
const loggedParameterName = this.
|
|
30940
|
+
const loggedParameterName = this.displayMasked(nameLogText(parameterName), context);
|
|
30782
30941
|
this.logger.debug(`Resolving dynamic reference: ${service}:${loggedParameterName}`);
|
|
30783
30942
|
const client = this.clientsForRegion(this.explicitRegion).ssm;
|
|
30784
30943
|
const command = new GetParameterCommand({
|
|
@@ -32476,7 +32635,7 @@ var CloudControlProvider = class {
|
|
|
32476
32635
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
32477
32636
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
32478
32637
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
32479
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
32638
|
+
const { ASGProvider } = await import("./asg-provider-DNzgk-BS.js").then((n) => n.n);
|
|
32480
32639
|
const asgProvider = new ASGProvider();
|
|
32481
32640
|
return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
|
|
32482
32641
|
}
|
|
@@ -45543,4 +45702,4 @@ var DeployEngine = class DeployEngine {
|
|
|
45543
45702
|
|
|
45544
45703
|
//#endregion
|
|
45545
45704
|
export { secretBearing as $, SynthesisError as $i, recordMaskOnlyValue as $n, AssetManifestLoader as $r, s3BucketArn as $t, extractDeploymentEventError as A, getAwsClients as Ai, refuseMalformedState as An, BOOTSTRAP_MARKER_PREFIX as Ar, isImpossibleEmptyStoredAttribute as At, toCfnInteger as B, IntrinsicResolutionRefusalError as Bi, STATE_SOURCED_BASELINE_RULES as Bn, buildDockerImage as Br, coerceCfnBoolean as Bt, buildFinalSnapshotIdentifier as C, canonicalizeRegion as Ci, producerRecordKey as Cn, stringifyValue as Cr, isTerminationProtectionPropagationError as Ct, refusesFinalSnapshot as D, clearBucketRegionCache as Di, refuseMalformedOutputsForDestroy as Dn, loadPublishableAssetManifest as Dr, cfnRefValueFromPhysicalId as Dt, isFinalSnapshotError as E, processStackMessages as Ei, refuseMalformedOutputs as En, createAssetRedirectResolver as Er, carriesFetchableDynamicReference as Et, isStatefulRecreateTargetSync as F, ConfigError as Fi, findSilentDropProperties as Fn, parseBootstrapMarker as Fr, isSettledInstanceState as Ft, gray as G, NestedStackChildDirectDestroyError as Gi, createSecretMasker as Gn, formatDockerLoginError as Gr, readConfigString as Gt, formatResourceLine as H, LocalStartServiceError as Hi, STATE_SOURCED_READBACK_RULES as Hn, describeDockerExecFailure as Hr, configBooleanRefusal as Ht, renderStatefulReason as I, CrossAccountSecretRefusalError as Ii, describeTypeWithThrottleRetry as In, readBootstrapMarkerBody as Ir, WAFv2WebACLProvider as It, yellow as J, ResourceTimeoutError as Ji, identityKeyFor as Jn, redactDockerArgvValues as Jr, requireConfigObject as Jt, green as K, PartialFailureError as Ki, dynamicReferenceTokens as Kn, getDockerCmd as Kr, replayWarn as Kt, WARM_THROUGHPUT_MEMBERS as L, DependencyError as Li, withRetry as Ln, validateAssetBucketName as Lr, normalizeAwsTagsToCfn as Lt, planOrphanAdoption as M, setAwsClients as Mi, repairMalformedResourcePropertiesForReadOnly as Mn, ensureAssetStorage as Mr, isUnboundTemplateParameter as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, AssetError as Ni, repairMalformedResourcesForReadOnly as Nn, getBootstrapMarkerKey as Nr, parameterTypeMayLoseSecretIdentity as Nt, unsupportedFinalSnapshotError as O, resolveBucketRegion as Oi, refuseMalformedResourcePropertiesForOrphan as On, rewriteTemplateAssetReferences as Or, coerceParameterTypedValue as Ot, isStatefulRecreateTargetForReplace as P, CdkdError as Pi, findActionableSilentDrops as Pn, isCrossRegionRedirect as Pr, refStateLookupFromResource as Pt, isExportAliasCollision as Q, StateError as Qi, maskSecretsInText as Qn, stripControlChars as Qr, withSharedDrainBudget as Qt, coerceWarmThroughput as R, DeployCancelledError as Ri, DagBuilder as Rn, validateContainerRepoName as Rr, resolveExplicitPhysicalId as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, PARTITION_TABLE as Si, malformedStateRefusalMessage as Sn, AssetPublisher as Sr, disableInstanceApiTermination as St, createPreDeleteFinalSnapshot as T, AssemblyReader as Ti, refuseMalformedNestedChildOutputs as Tn, buildAssetRedirectMap as Tr, carriesDynamicReference as Tt, bold as U, LockError as Ui, TEMPLATE_SOURCED_RULES as Un, describeDockerFailure as Ur, configIntegerRefusal as Ut, toFiniteNumber as V, LocalInvokeBuildError as Vi, STATE_SOURCED_CROSS_GENERATION_RULES as Vn, describeDockerCapturedOutput as Vr, coerceCfnInteger as Vt, cyan as W, MalformedProducerRecordRefusalError as Wi, carriesSecretMask as Wn, dockerSpawnEnvWithSensitive as Wr, configStringRefusal as Wt, collectPublishedOutputNames as X, StackHasActiveImportsError as Xi, markSameGenerationBag as Xn, runDockerStreaming as Xr, classifyReplaySecretRegion as Xt, collectDeclaredOutputNames as Y, ResourceUpdateNotSupportedError as Yi, isSingleDynamicReferenceToken as Yn, runDockerForeground as Yr, requireConfigString as Yt, exportAliasCollisionScrubWarning as Z, StackTerminationProtectionError as Zi, maskSecretsInError as Zn, escapeRegExp$1 as Zr, producerRegionsFromState as Zt, isSecretBearingReferenceString as _, findLargeInlineResources as _i, malformedOutputsRefusalMessage as _n, importableOutputs as _r, isWaitAbandonedError as _t, DeploymentEventsStore as a, isRetryableTransientError as aa, resolveApp as ai, AWS_CREDENTIAL_ENV_KEYS as an, rebuildClientForBucketRegion as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, decodeListingKey as bi, malformedResourcePropertiesWarning as bn, orphansCarriedFrom as br, deleteIndeterminateGuards as bt, replayFailedOperations as c, markNonRetryable as ca, resolveSkipPrefix as ci, envCredentialsAreAssumedRole as cn, buildLockContentionMessage as cr, createMaskedRetryLogger as ct, updatePartialReason as d, describeAwsFailure as da, resolveUseCdkBootstrapAssets as di, STATE_RESOURCES_MALFORMED as dn, shellQuote as dr, beginCommandInterruptScope as dt, formatError as ea, getDockerImageBySourceHash as ei, s3BucketDomainName as en, recoverMaskedOutput as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, safeStringify$1 as fa, stateBucketExistenceConfirmed as fi, hasReadableOutputs as fn, CUSTOM_RESOURCE_RESPONSE_PREFIX as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, MIGRATE_TMP_PREFIX as gi, malformedLocalOutputsWarning as gn, importableOutputKeys as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, CFN_TEMPLATE_URL_LIMIT as hi, malformedExportSourceWarning as hn, hasReadableExportSet as hr, startInterruptWatch as ht, DeploymentEventsReader as i, isMarkedNonRetryable as ia, getLegacyStateBucketName as ii, applyRoleArnIfSet as in, S3StateBackend as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, resetAwsClients as ji, repairMalformedOutputsForReadOnly as jn, assertAssetBucketRegion as jr, isNamelessDynamicReferenceError as jt, makeCanonicalizePropertiesFn as k, AwsClients as ki, refuseMalformedResourcesForDestroy as kn, AssetModeResolver as kr, getAccountInfo as kt, replayRollback as l, markRedactedCause as la, resolveStateBucketWithDefault as li, DiffCalculator as ln, forceQuitRecoveryClause as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, CFN_TEMPLATE_BODY_LIMIT as mi, malformedExportNamesWarning as mn, exportNamesCarriedFrom as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, normalizeAwsError as na, synthesisStatusMessage as ni, s3BucketRegionalDomainName as nn, scrubResourceRecord as nr, getCurrentResourceSecrets as nt, planFailedOps as o, isThrottlingError as oa, resolveAutoAssetStorage as oi, applyCallerIdentityCredentials as on, UNREPRODUCIBLE_LOCK_CLAUSE as or, ProviderRegistry as ot, maskingRetryLogger as p, __exportAll as pa, warnDeprecatedNoPrefixCliFlag as pi, hasReadableResources as pn, DEFAULT_STATE_PREFIX as pr, interruptWatchListenerCount as pt, red as q, ProvisioningError as qi, errorCauseChain as qn, partitionSensitiveEnv as qr, requireConfigArray as qt, DeployEngine as r, withErrorHandling as ra, getDefaultStateBucketName as ri, s3BucketWebsiteUrl as rn, LockManager as rr, IAMRoleProvider as rt, planRollback as s, isTransientServerError as sa, resolveCaptureObservedState as si, callerEnvCredentials as sn, buildForceUnlockCommand as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, isCdkdError as ta, Synthesizer as ti, s3BucketDualStackDomainName as tn, redactSecretsForState as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, retryClassificationText as ua, resolveStateBucketWithDefaultAndSource as ui, INTRINSIC_KEYS as un, formatLockExpiry as ur, maskerOrIdentity as ut, keptWholeReasonText as v, uploadCfnTemplate as vi, malformedOutputsWarning as vn, isReadableBag as vr, slowCcOperationTimeoutMs as vt, ccRoutedFinalSnapshotError as w, derivePartitionAndUrlSuffix as wi, refuseDivergentRecordRegionForDestroy as wn, WorkGraph as wr, IntrinsicFunctionResolver as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, expectedOwnerParam as xi, malformedResourcesWarning as xn, shouldRetainResource as xr, deleteSkipReason as xt, mergeNoChangeOutputs as y, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as yi, malformedRenderedContainersWarning as yn, orphansAfterRollback as yr, UNSPECIFIED_SKIP_REASON as yt, isWarmThroughputDecrease as z, DynamicReferenceRegionAmbiguousError as zi, TemplateParser as zn, buildDenyExternalAccessPolicy as zr, assertRegionMatch as zt };
|
|
45546
|
-
//# sourceMappingURL=deploy-engine-
|
|
45705
|
+
//# sourceMappingURL=deploy-engine-21iNqwR3.js.map
|