@go-to-k/cdkd 0.283.34 → 0.283.36
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-B1AQpZfU.js → asg-provider-BruE_3F2.js} +2 -2
- package/dist/{asg-provider-B1AQpZfU.js.map → asg-provider-BruE_3F2.js.map} +1 -1
- package/dist/cli.js +295 -18
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DlEg9thJ.js → deploy-engine-Bhq_JPCc.js} +208 -36
- package/dist/deploy-engine-Bhq_JPCc.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DlEg9thJ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as getAccountInfo, $t as formatDockerLoginError, A as cyan, An as resolveBucketRegion, At as TemplateParser, B as stateKeySecretExposure, Bn as LocalInvokeBuildError$1, Bt as loadPublishableAssetManifest, C as makeCanonicalizePropertiesFn, Cn as expectedOwnerParam, Ct as s3BucketWebsiteUrl, D as renderStatefulReason, Dn as AssemblyReader, Dt as describeTypeWithThrottleRetry, E as isStatefulRecreateTargetSync, En as derivePartitionAndUrlSuffix, Et as INTRINSIC_KEYS, F as collectDeclaredOutputNames, Ft as AssetPublisher, G as findActionableSilentDrops, Gn as NestedStackChildDirectDestroyError, Gt as BOOTSTRAP_MARKER_PREFIX, H as collectInlinePolicyNamesManagedBySiblings, Hn as LocalStartServiceError, Ht as escapeRegExp, I as collectPublishedOutputNames, In as CdkdError, It as stringifyValue, J as slowCcOperationTimeoutMs, Jn as ResourceTimeoutError, Jt as parseBootstrapMarker, K as findSilentDropProperties, Kn as PartialFailureError, Kt as ensureAssetStorage, L as exportAliasCollisionScrubWarning, Lt as WorkGraph, M as green, Mn as getAwsClients, Mt as S3StateBackend, N as red, Nn as resetAwsClients, Nt as rebuildClientForBucketRegion, O as formatResourceLine, On as processStackMessages, Ot as withRetry, P as yellow, Pn as setAwsClients, Pt as shouldRetainResource, Q as cfnRefValueFromPhysicalId, Qt as buildDockerImage, R as isExportAliasCollision, Rt as buildAssetRedirectMap, S as unsupportedFinalSnapshotError, Sn as uploadCfnTemplate, St as s3BucketRegionalDomainName, T as MULTI_REGION_RECREATE_BLOCKED_TYPES, Tn as canonicalizeRegion, Tt as DiffCalculator, U as clearOnUpdateRemoval, Ut as stripControlChars, V as IAMRoleProvider, Vn as LocalMigrateError, Vt as rewriteTemplateAssetReferences, W as ProviderRegistry, Wn as MissingCdkCliError, Wt as AssetModeResolver, X as isTerminationProtectionPropagationError, Xn as StackHasActiveImportsError, Xt as validateContainerRepoName, Y as disableInstanceApiTermination, Yn as ResourceUpdateNotSupportedError, Yt as validateAssetBucketName, Z as IntrinsicFunctionResolver, Zn as StackTerminationProtectionError, Zt as buildDenyExternalAccessPolicy, _ as buildFinalSnapshotIdentifier, _n as warnDeprecatedNoPrefixCliFlag, _t as redactSecretsForState, a as DeploymentEventsStore, an as Synthesizer, ar as isRetryableTransientError, at as coerceCfnBoolean, b as isFinalSnapshotError, bn as MIGRATE_TMP_PREFIX, bt as s3BucketDomainName, c as replayFailedOperations, cn as getLegacyStateBucketName, ct as readConfigString, d as deleteSkipReason, dn as resolveCaptureObservedState, dt as requireConfigObject, en as getDockerCmd, et as refStateLookupFromResource, f as withResourceDeadline, fn as resolveSkipPrefix, ft as requireConfigString, g as PRE_DELETE_SNAPSHOT_TYPES, gn as stateBucketExistenceConfirmed, gt as maskSecretsInText, h as ATOMIC_FINAL_SNAPSHOT_TYPES, hn as resolveUseCdkBootstrapAssets, ht as TEMPLATE_SOURCED_RULES, i as DeploymentEventsReader, in as getDockerImageBySourceHash, ir as isMarkedNonRetryable, it as assertRegionMatch, j as gray, jn as AwsClients, jt as LockManager, k as bold, kt as DagBuilder, l as replayRollback, ln as resolveApp, lt as replayWarn, m as computeImplicitDeleteEdges, mn as resolveStateBucketWithDefaultAndSource, mt as STATE_SOURCED_READBACK_RULES, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as runDockerStreaming, nr as normalizeAwsError, nt as normalizeAwsTagsToCfn, o as planFailedOps, on as synthesisStatusMessage, or as isThrottlingError, ot as configBooleanRefusal, p as IMPLICIT_DELETE_DEPENDENCIES, pn as resolveStateBucketWithDefault, pt as STATE_SOURCED_CROSS_GENERATION_RULES, q as CloudControlProvider, qn as ProvisioningError, qt as getBootstrapMarkerKey, r as DeployEngine, rn as AssetManifestLoader, rr as withErrorHandling, rt as resolveExplicitPhysicalId, s as planRollback, sn as getDefaultStateBucketName, sr as markNonRetryable, st as configStringRefusal, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as runDockerForeground, tt as WAFv2WebACLProvider, u as UNSPECIFIED_SKIP_REASON, un as resolveAutoAssetStorage, ut as requireConfigArray, v as ccRoutedFinalSnapshotError, vn as CFN_TEMPLATE_BODY_LIMIT, vt as scrubResourceRecord, w as extractDeploymentEventError, wn as PARTITION_TABLE, wt as applyRoleArnIfSet, x as refusesFinalSnapshot, xn as findLargeInlineResources, xt as s3BucketDualStackDomainName, y as createPreDeleteFinalSnapshot, yn as CFN_TEMPLATE_URL_LIMIT, yt as s3BucketArn, z as secretBearingStateKeyWarning, zn as DeployCancelledError, zt as createAssetRedirectResolver } from "./deploy-engine-
|
|
2
|
+
import { $ as getAccountInfo, $t as formatDockerLoginError, A as cyan, An as resolveBucketRegion, At as TemplateParser, B as stateKeySecretExposure, Bn as LocalInvokeBuildError$1, Bt as loadPublishableAssetManifest, C as makeCanonicalizePropertiesFn, Cn as expectedOwnerParam, Ct as s3BucketWebsiteUrl, D as renderStatefulReason, Dn as AssemblyReader, Dt as describeTypeWithThrottleRetry, E as isStatefulRecreateTargetSync, En as derivePartitionAndUrlSuffix, Et as INTRINSIC_KEYS, F as collectDeclaredOutputNames, Ft as AssetPublisher, G as findActionableSilentDrops, Gn as NestedStackChildDirectDestroyError, Gt as BOOTSTRAP_MARKER_PREFIX, H as collectInlinePolicyNamesManagedBySiblings, Hn as LocalStartServiceError, Ht as escapeRegExp, I as collectPublishedOutputNames, In as CdkdError, It as stringifyValue, J as slowCcOperationTimeoutMs, Jn as ResourceTimeoutError, Jt as parseBootstrapMarker, K as findSilentDropProperties, Kn as PartialFailureError, Kt as ensureAssetStorage, L as exportAliasCollisionScrubWarning, Lt as WorkGraph, M as green, Mn as getAwsClients, Mt as S3StateBackend, N as red, Nn as resetAwsClients, Nt as rebuildClientForBucketRegion, O as formatResourceLine, On as processStackMessages, Ot as withRetry, P as yellow, Pn as setAwsClients, Pt as shouldRetainResource, Q as cfnRefValueFromPhysicalId, Qt as buildDockerImage, R as isExportAliasCollision, Rt as buildAssetRedirectMap, S as unsupportedFinalSnapshotError, Sn as uploadCfnTemplate, St as s3BucketRegionalDomainName, T as MULTI_REGION_RECREATE_BLOCKED_TYPES, Tn as canonicalizeRegion, Tt as DiffCalculator, U as clearOnUpdateRemoval, Ut as stripControlChars, V as IAMRoleProvider, Vn as LocalMigrateError, Vt as rewriteTemplateAssetReferences, W as ProviderRegistry, Wn as MissingCdkCliError, Wt as AssetModeResolver, X as isTerminationProtectionPropagationError, Xn as StackHasActiveImportsError, Xt as validateContainerRepoName, Y as disableInstanceApiTermination, Yn as ResourceUpdateNotSupportedError, Yt as validateAssetBucketName, Z as IntrinsicFunctionResolver, Zn as StackTerminationProtectionError, Zt as buildDenyExternalAccessPolicy, _ as buildFinalSnapshotIdentifier, _n as warnDeprecatedNoPrefixCliFlag, _t as redactSecretsForState, a as DeploymentEventsStore, an as Synthesizer, ar as isRetryableTransientError, at as coerceCfnBoolean, b as isFinalSnapshotError, bn as MIGRATE_TMP_PREFIX, bt as s3BucketDomainName, c as replayFailedOperations, cn as getLegacyStateBucketName, ct as readConfigString, d as deleteSkipReason, dn as resolveCaptureObservedState, dt as requireConfigObject, en as getDockerCmd, et as refStateLookupFromResource, f as withResourceDeadline, fn as resolveSkipPrefix, ft as requireConfigString, g as PRE_DELETE_SNAPSHOT_TYPES, gn as stateBucketExistenceConfirmed, gt as maskSecretsInText, h as ATOMIC_FINAL_SNAPSHOT_TYPES, hn as resolveUseCdkBootstrapAssets, ht as TEMPLATE_SOURCED_RULES, i as DeploymentEventsReader, in as getDockerImageBySourceHash, ir as isMarkedNonRetryable, it as assertRegionMatch, j as gray, jn as AwsClients, jt as LockManager, k as bold, kt as DagBuilder, l as replayRollback, ln as resolveApp, lt as replayWarn, m as computeImplicitDeleteEdges, mn as resolveStateBucketWithDefaultAndSource, mt as STATE_SOURCED_READBACK_RULES, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as runDockerStreaming, nr as normalizeAwsError, nt as normalizeAwsTagsToCfn, o as planFailedOps, on as synthesisStatusMessage, or as isThrottlingError, ot as configBooleanRefusal, p as IMPLICIT_DELETE_DEPENDENCIES, pn as resolveStateBucketWithDefault, pt as STATE_SOURCED_CROSS_GENERATION_RULES, q as CloudControlProvider, qn as ProvisioningError, qt as getBootstrapMarkerKey, r as DeployEngine, rn as AssetManifestLoader, rr as withErrorHandling, rt as resolveExplicitPhysicalId, s as planRollback, sn as getDefaultStateBucketName, sr as markNonRetryable, st as configStringRefusal, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as runDockerForeground, tt as WAFv2WebACLProvider, u as UNSPECIFIED_SKIP_REASON, un as resolveAutoAssetStorage, ut as requireConfigArray, v as ccRoutedFinalSnapshotError, vn as CFN_TEMPLATE_BODY_LIMIT, vt as scrubResourceRecord, w as extractDeploymentEventError, wn as PARTITION_TABLE, wt as applyRoleArnIfSet, x as refusesFinalSnapshot, xn as findLargeInlineResources, xt as s3BucketDualStackDomainName, y as createPreDeleteFinalSnapshot, yn as CFN_TEMPLATE_URL_LIMIT, yt as s3BucketArn, z as secretBearingStateKeyWarning, zn as DeployCancelledError, zt as createAssetRedirectResolver } from "./deploy-engine-Bhq_JPCc.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-BruE_3F2.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -38931,6 +38931,46 @@ const MFA_FACTOR_SMS = "SMS_MFA";
|
|
|
38931
38931
|
const MFA_FACTOR_SOFTWARE_TOKEN = "SOFTWARE_TOKEN_MFA";
|
|
38932
38932
|
const MFA_FACTOR_EMAIL_OTP = "EMAIL_OTP";
|
|
38933
38933
|
/**
|
|
38934
|
+
* CFn path every `MfaConfiguration` shape refusal in this provider reports.
|
|
38935
|
+
* One constant so the three sites that READ the property -- `create`,
|
|
38936
|
+
* `update`, and `narrowMfaConfiguration` (the diff / effectiveProperties
|
|
38937
|
+
* side) -- cannot word the same fault differently. `buildMfaConfigRequest`
|
|
38938
|
+
* performs no read of its own; it is handed the already-guarded value.
|
|
38939
|
+
*/
|
|
38940
|
+
const MFA_CONFIGURATION_PATH = "AWS::Cognito::UserPool MfaConfiguration";
|
|
38941
|
+
function classifyDeclaredMfaConfiguration(raw) {
|
|
38942
|
+
if (raw === void 0) return "absent";
|
|
38943
|
+
if (typeof raw !== "string") return "refused";
|
|
38944
|
+
return raw.trim() === "" ? "blank" : "usable";
|
|
38945
|
+
}
|
|
38946
|
+
/**
|
|
38947
|
+
* Read the template's `MfaConfiguration` through the shape guard AND fold a
|
|
38948
|
+
* TRIMMED-BLANK value to absence.
|
|
38949
|
+
*
|
|
38950
|
+
* The fold is the load-bearing half. `requireConfigString` short-circuits on
|
|
38951
|
+
* `fallback === '' && typeof value === 'string'` (config-shape.ts), so against
|
|
38952
|
+
* the blank fallback this site uses it returns ANY string verbatim --
|
|
38953
|
+
* including `' '`. That value is truthy, so it rode the
|
|
38954
|
+
* `if (mfaConfiguration && ...)` gates onto `CreateUserPool` / `UpdateUserPool`
|
|
38955
|
+
* and the `|| default` in `buildMfaConfigRequest` onto `SetUserPoolMfaConfig`,
|
|
38956
|
+
* where AWS rejects the enum and the deploy fails -- while the blank-value
|
|
38957
|
+
* warning promised "the pool deploys with the default MFA configuration
|
|
38958
|
+
* instead". Two spellings of blank behaved differently and the message
|
|
38959
|
+
* described only one of them.
|
|
38960
|
+
*
|
|
38961
|
+
* Folding here rather than widening the guard keeps the change local to the
|
|
38962
|
+
* one site whose fallback is blank, and makes the wire behavior match what the
|
|
38963
|
+
* warning says: a blank declares nothing, so the default applies.
|
|
38964
|
+
*
|
|
38965
|
+
* Every read site MUST go through this, including `narrowMfaConfiguration` --
|
|
38966
|
+
* a diff side that folded differently from the wire is the phantom drift this
|
|
38967
|
+
* whole mechanism exists to remove.
|
|
38968
|
+
*/
|
|
38969
|
+
function readDeclaredMfaConfiguration(raw, options) {
|
|
38970
|
+
const value = requireConfigString(raw, "", MFA_CONFIGURATION_PATH, options);
|
|
38971
|
+
return value.trim() === "" ? "" : value;
|
|
38972
|
+
}
|
|
38973
|
+
/**
|
|
38934
38974
|
* Read `EnabledMfas` as the pair (recognized list, "the template asked for a
|
|
38935
38975
|
* factor at all").
|
|
38936
38976
|
*
|
|
@@ -38954,14 +38994,16 @@ function readEnabledMfas(properties) {
|
|
|
38954
38994
|
return {
|
|
38955
38995
|
factors,
|
|
38956
38996
|
declaresFactor: factors.length > 0,
|
|
38957
|
-
malformed: false
|
|
38997
|
+
malformed: false,
|
|
38998
|
+
blank: false
|
|
38958
38999
|
};
|
|
38959
39000
|
}
|
|
38960
39001
|
const malformed = raw !== void 0 && raw !== null && raw !== "";
|
|
38961
39002
|
return {
|
|
38962
39003
|
factors: void 0,
|
|
38963
39004
|
declaresFactor: malformed,
|
|
38964
|
-
malformed
|
|
39005
|
+
malformed,
|
|
39006
|
+
blank: raw === ""
|
|
38965
39007
|
};
|
|
38966
39008
|
}
|
|
38967
39009
|
/**
|
|
@@ -39000,9 +39042,17 @@ function hasMfaConfigProps(properties) {
|
|
|
39000
39042
|
* enables an MFA FACTOR — `OPTIONAL` if it does, `OFF` (CloudFormation's own
|
|
39001
39043
|
* default) if it does not. The body comment on that decision explains why both
|
|
39002
39044
|
* halves of the factor test are load-bearing.
|
|
39045
|
+
*
|
|
39046
|
+
* `declaredMfaConfiguration` is the caller's ALREADY-GUARDED read of
|
|
39047
|
+
* `properties['MfaConfiguration']` (issue #1925 item 2), with `''` meaning
|
|
39048
|
+
* "the template declared none, or declared a value the shape guard refused".
|
|
39049
|
+
* The read happens at the caller so it runs ONCE per deploy path — the value
|
|
39050
|
+
* is also needed for the `CreateUserPool` / `UpdateUserPool` forward — and so
|
|
39051
|
+
* the create path can REFUSE a malformed value while the update path only
|
|
39052
|
+
* warns, which is the split `requireConfigString`'s `onUnusable` encodes.
|
|
39003
39053
|
*/
|
|
39004
|
-
function buildMfaConfigRequest(physicalId, properties, logger) {
|
|
39005
|
-
const { factors: enabledMfas, declaresFactor, malformed: enabledMfasMalformed } = readEnabledMfas(properties);
|
|
39054
|
+
function buildMfaConfigRequest(physicalId, properties, logger, declaredMfaConfiguration = "") {
|
|
39055
|
+
const { factors: enabledMfas, declaresFactor, malformed: enabledMfasMalformed, blank: enabledMfasBlank } = readEnabledMfas(properties);
|
|
39006
39056
|
const emailMessage = properties["EmailAuthenticationMessage"] || void 0;
|
|
39007
39057
|
const emailSubject = properties["EmailAuthenticationSubject"] || void 0;
|
|
39008
39058
|
const webAuthnRpId = properties["WebAuthnRelyingPartyID"] || void 0;
|
|
@@ -39022,17 +39072,83 @@ function buildMfaConfigRequest(physicalId, properties, logger) {
|
|
|
39022
39072
|
...webAuthnUserVerification !== void 0 ? { UserVerification: webAuthnUserVerification } : {}
|
|
39023
39073
|
};
|
|
39024
39074
|
const enablesMfaFactor = declaresFactor || request.EmailMfaConfiguration !== void 0;
|
|
39025
|
-
request.MfaConfiguration =
|
|
39075
|
+
request.MfaConfiguration = declaredMfaConfiguration || (enablesMfaFactor ? "OPTIONAL" : "OFF");
|
|
39076
|
+
if (enabledMfasBlank) logger?.warn(`UserPool ${physicalId}: EnabledMfas is an empty string, which declares no MFA factor and is treated as absent — a mangled Fn::Join or an empty String parameter collapses to this shape. Nothing is enabled from it and MfaConfiguration is ${request.MfaConfiguration}; declare the factor names as a list (e.g. ["${MFA_FACTOR_SOFTWARE_TOKEN}"]) if a factor was intended.`);
|
|
39077
|
+
const anyFactorBlock = request.SmsMfaConfiguration !== void 0 || request.SoftwareTokenMfaConfiguration !== void 0 || request.EmailMfaConfiguration !== void 0;
|
|
39078
|
+
if (request.MfaConfiguration === "OFF" && anyFactorBlock) logger?.warn(`UserPool ${physicalId}: MfaConfiguration is pinned to OFF while an MFA factor block is configured. The factor configuration is still sent, but the pool deploys with MFA DISABLED. Remove MfaConfiguration (or set it to ON / OPTIONAL) to enable the declared factor.`);
|
|
39026
39079
|
const dropped = unrecognizedFactors.map((f) => JSON.stringify(f) ?? String(f));
|
|
39027
39080
|
if (enabledMfasMalformed) dropped.push(`${JSON.stringify(properties["EnabledMfas"])} (not a list)`);
|
|
39028
39081
|
if (dropped.length > 0) {
|
|
39029
|
-
const anyFactorBlock = request.SmsMfaConfiguration !== void 0 || request.SoftwareTokenMfaConfiguration !== void 0 || request.EmailMfaConfiguration !== void 0;
|
|
39030
39082
|
const consequence = request.MfaConfiguration === "OFF" ? `MfaConfiguration is OFF, so this pool deploys with MFA DISABLED` : anyFactorBlock ? `MfaConfiguration is ${request.MfaConfiguration} and another factor block IS sent, so these entries are silently ignored rather than failing the call on their own` : `MfaConfiguration is ${request.MfaConfiguration} with no factor enabled, so AWS rejects this call rather than deploying the pool with MFA disabled`;
|
|
39031
39083
|
logger?.warn(`UserPool ${physicalId}: EnabledMfas entries ${dropped.join(", ")} do not map to an MFA factor block (known: ${MFA_FACTOR_SMS}, ${MFA_FACTOR_SOFTWARE_TOKEN}, ${MFA_FACTOR_EMAIL_OTP}); no factor is enabled from them. ${consequence}.`);
|
|
39032
39084
|
}
|
|
39033
39085
|
return request;
|
|
39034
39086
|
}
|
|
39035
39087
|
/**
|
|
39088
|
+
* The `MfaConfiguration` cdkd actually SENDS for this bag, or `undefined` when
|
|
39089
|
+
* no call carries the field at all (nothing declared and no MFA-routed
|
|
39090
|
+
* property, so AWS applies its own default of OFF).
|
|
39091
|
+
*
|
|
39092
|
+
* Exactly one call ever carries it: `SetUserPoolMfaConfig` owns it whenever any
|
|
39093
|
+
* MFA-routed property is present -- and always sets it, because that API is a
|
|
39094
|
+
* full replace -- otherwise the `CreateUserPool` / `UpdateUserPool` forward
|
|
39095
|
+
* carries it, and only when it is non-blank.
|
|
39096
|
+
*
|
|
39097
|
+
* Delegates to {@link buildMfaConfigRequest} rather than re-deriving the
|
|
39098
|
+
* OPTIONAL/OFF default, so the recorded value and the wire value cannot
|
|
39099
|
+
* disagree. That function is pure and synchronous, which is what lets
|
|
39100
|
+
* `canonicalizeDesiredProperties` -- which runs inside the diff -- call it too.
|
|
39101
|
+
* The empty `physicalId` and absent logger are unused on this path: every
|
|
39102
|
+
* message it can emit is behind `logger?.`, so passing none makes the call
|
|
39103
|
+
* silent, which is required of the diff side.
|
|
39104
|
+
*/
|
|
39105
|
+
function resolveSentMfaConfiguration(properties, declaredMfaConfiguration) {
|
|
39106
|
+
const request = buildMfaConfigRequest("", properties, void 0, declaredMfaConfiguration);
|
|
39107
|
+
if (request) return request.MfaConfiguration;
|
|
39108
|
+
return declaredMfaConfiguration || void 0;
|
|
39109
|
+
}
|
|
39110
|
+
/**
|
|
39111
|
+
* Replace a DECLARED-but-unusable `MfaConfiguration` with the value cdkd
|
|
39112
|
+
* actually sends, or drop the key when nothing is sent. Returns the input
|
|
39113
|
+
* object unchanged when nothing applies, so the common case compares
|
|
39114
|
+
* byte-for-byte as before.
|
|
39115
|
+
*
|
|
39116
|
+
* ONE helper feeding BOTH sides of the decision, per `.claude/rules/
|
|
39117
|
+
* providers.md`: the provisioning path returns it as `effectiveProperties` so
|
|
39118
|
+
* STATE describes what AWS holds, and `canonicalizeDesiredProperties` applies
|
|
39119
|
+
* it to the DESIRED bag so the next diff compares the same thing. Shipping
|
|
39120
|
+
* only the first half is worse than shipping neither -- the template would keep
|
|
39121
|
+
* declaring the malformed value, and every later deploy would read the
|
|
39122
|
+
* narrowing back as a user-made change.
|
|
39123
|
+
*
|
|
39124
|
+
* Without this, all three substitution arms (the replay-CREATE downgrade, the
|
|
39125
|
+
* update-path warn-and-default, and the blank-string default) recorded the
|
|
39126
|
+
* declared `null` / `''` while AWS held `OPTIONAL` / `OFF` -- permanent phantom
|
|
39127
|
+
* drift that `cdkd drift --revert` re-issues forever with nothing to apply.
|
|
39128
|
+
*
|
|
39129
|
+
* A value that is merely ABSENT is deliberately NOT filled in. Reaching for
|
|
39130
|
+
* `effectiveProperties` is licensed only where the provider KNOWS it
|
|
39131
|
+
* substituted something it was told, and an omitted property was never a
|
|
39132
|
+
* declaration to contradict; writing the resolved default into the DESIRED
|
|
39133
|
+
* baseline there would also disable the #1160 absent-field removal derivation,
|
|
39134
|
+
* which reads that side.
|
|
39135
|
+
*/
|
|
39136
|
+
function narrowMfaConfiguration(properties) {
|
|
39137
|
+
const raw = properties["MfaConfiguration"];
|
|
39138
|
+
if (raw === void 0) return properties;
|
|
39139
|
+
const sent = resolveSentMfaConfiguration(properties, readDeclaredMfaConfiguration(raw, { onUnusable: () => {} }));
|
|
39140
|
+
if (sent === raw) return properties;
|
|
39141
|
+
if (sent === void 0) {
|
|
39142
|
+
const withoutMfaConfiguration = { ...properties };
|
|
39143
|
+
delete withoutMfaConfiguration["MfaConfiguration"];
|
|
39144
|
+
return withoutMfaConfiguration;
|
|
39145
|
+
}
|
|
39146
|
+
return {
|
|
39147
|
+
...properties,
|
|
39148
|
+
MfaConfiguration: sent
|
|
39149
|
+
};
|
|
39150
|
+
}
|
|
39151
|
+
/**
|
|
39036
39152
|
* AWS Cognito User Pool Provider
|
|
39037
39153
|
*
|
|
39038
39154
|
* Implements resource provisioning for AWS::Cognito::UserPool using the Cognito SDK.
|
|
@@ -39076,6 +39192,50 @@ var CognitoUserPoolProvider = class {
|
|
|
39076
39192
|
"WebAuthnUserVerification"
|
|
39077
39193
|
])]]);
|
|
39078
39194
|
unhandledByDesign = /* @__PURE__ */ new Map([["AWS::Cognito::UserPool", /* @__PURE__ */ new Map([["WebAuthnFactorConfiguration", "No SDK wire path: @aws-sdk/client-cognito-identity-provider has no field accepting SINGLE_FACTOR | MULTI_FACTOR_WITH_USER_VERIFICATION (not on CreateUserPool/UpdateUserPool, nor SetUserPoolMfaConfig.WebAuthnConfiguration which only carries RelyingPartyId/UserVerification); CC-API-registry-only property"]])]]);
|
|
39195
|
+
/**
|
|
39196
|
+
* Warn when `MfaConfiguration` is declared as a BLANK string (issue #1925
|
|
39197
|
+
* item 2, review round 2).
|
|
39198
|
+
*
|
|
39199
|
+
* `requireConfigString` accepts any string against a blank fallback, so `''`
|
|
39200
|
+
* passes the shape guard and is then substituted by the OPTIONAL/OFF default
|
|
39201
|
+
* downstream. That is the exact silent-default class the guard exists to
|
|
39202
|
+
* kill, reached one shape further in: on main a WebAuthn-only pool declaring
|
|
39203
|
+
* `MfaConfiguration: ''` failed LOUDLY with an AWS enum rejection, and with
|
|
39204
|
+
* the guard alone it would deploy MFA OFF with no message anywhere. A
|
|
39205
|
+
* collapsed `Fn::Join` or an empty `String` parameter produces exactly this.
|
|
39206
|
+
*
|
|
39207
|
+
* The twin of the blank-`EnabledMfas` warning one property over, and warned
|
|
39208
|
+
* for the same reason it is: the value stays absence ON THE WIRE (the
|
|
39209
|
+
* substitution is what CloudFormation's own default does), so only the
|
|
39210
|
+
* silence is removed.
|
|
39211
|
+
*
|
|
39212
|
+
* `.trim()` matches the fold in {@link readDeclaredMfaConfiguration}, and the
|
|
39213
|
+
* two must agree: `requireConfigString` does NOT treat whitespace-only as
|
|
39214
|
+
* blank against the blank fallback this site uses, so before that fold a
|
|
39215
|
+
* `' '` was warned about here and then sent to AWS verbatim -- this message
|
|
39216
|
+
* describing a default that never applied.
|
|
39217
|
+
*/
|
|
39218
|
+
warnOnBlankMfaConfiguration(raw) {
|
|
39219
|
+
if (typeof raw !== "string" || raw.trim() !== "") return;
|
|
39220
|
+
this.logger.warn("AWS::Cognito::UserPool MfaConfiguration is an empty string, which declares no MFA mode and is treated as absent -- a collapsed Fn::Join or an empty String parameter produces this shape. The pool deploys with the default MFA configuration instead; declare ON / OPTIONAL / OFF explicitly, or omit the property, to say which was meant.");
|
|
39221
|
+
}
|
|
39222
|
+
/**
|
|
39223
|
+
* The DIFF-side half of the `MfaConfiguration` substitution record.
|
|
39224
|
+
*
|
|
39225
|
+
* Applied by `DiffCalculator` to BOTH comparison sides, so a template that
|
|
39226
|
+
* declares a malformed / blank `MfaConfiguration` compares equal to the state
|
|
39227
|
+
* record holding the value cdkd actually sent for it. Without this half, the
|
|
39228
|
+
* `effectiveProperties` above would make every later deploy read the
|
|
39229
|
+
* substitution back as a user-made change and re-run the update forever.
|
|
39230
|
+
*
|
|
39231
|
+
* Shares ONE helper with the provisioning path rather than re-deriving the
|
|
39232
|
+
* rule, per `.claude/rules/providers.md` -- state and template narrowed by
|
|
39233
|
+
* different code is how this fix would become the bug.
|
|
39234
|
+
*/
|
|
39235
|
+
canonicalizeDesiredProperties(resourceType, properties) {
|
|
39236
|
+
if (resourceType !== "AWS::Cognito::UserPool") return properties;
|
|
39237
|
+
return narrowMfaConfiguration(properties);
|
|
39238
|
+
}
|
|
39079
39239
|
getClient() {
|
|
39080
39240
|
if (!this.cognitoClient) this.cognitoClient = new CognitoIdentityProviderClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
39081
39241
|
return this.cognitoClient;
|
|
@@ -39096,9 +39256,16 @@ var CognitoUserPoolProvider = class {
|
|
|
39096
39256
|
/**
|
|
39097
39257
|
* Create a Cognito User Pool
|
|
39098
39258
|
*/
|
|
39099
|
-
async create(logicalId, resourceType, properties) {
|
|
39259
|
+
async create(logicalId, resourceType, properties, context) {
|
|
39100
39260
|
this.logger.debug(`Creating Cognito User Pool ${logicalId}`);
|
|
39101
39261
|
const poolName = properties["UserPoolName"] || generateResourceName(logicalId, { maxLength: 128 });
|
|
39262
|
+
let mfaConfiguration;
|
|
39263
|
+
try {
|
|
39264
|
+
mfaConfiguration = readDeclaredMfaConfiguration(properties["MfaConfiguration"], replayWarn(this.logger, context));
|
|
39265
|
+
this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
|
|
39266
|
+
} catch (error) {
|
|
39267
|
+
throw new ProvisioningError(error instanceof Error ? error.message : String(error), resourceType, logicalId, poolName, error instanceof Error ? error : void 0);
|
|
39268
|
+
}
|
|
39102
39269
|
let createdUserPoolId;
|
|
39103
39270
|
try {
|
|
39104
39271
|
const createParams = { PoolName: poolName };
|
|
@@ -39110,7 +39277,7 @@ var CognitoUserPoolProvider = class {
|
|
|
39110
39277
|
}
|
|
39111
39278
|
if (properties["Schema"]) createParams.Schema = properties["Schema"];
|
|
39112
39279
|
if (properties["LambdaConfig"]) createParams.LambdaConfig = properties["LambdaConfig"];
|
|
39113
|
-
if (
|
|
39280
|
+
if (mfaConfiguration && !hasMfaConfigProps(properties)) createParams.MfaConfiguration = mfaConfiguration;
|
|
39114
39281
|
if (properties["UserPoolTags"]) createParams.UserPoolTags = properties["UserPoolTags"];
|
|
39115
39282
|
if (properties["AdminCreateUserConfig"]) createParams.AdminCreateUserConfig = properties["AdminCreateUserConfig"];
|
|
39116
39283
|
if (properties["AccountRecoverySetting"]) createParams.AccountRecoverySetting = properties["AccountRecoverySetting"];
|
|
@@ -39137,8 +39304,9 @@ var CognitoUserPoolProvider = class {
|
|
|
39137
39304
|
const { urlSuffix } = derivePartitionAndUrlSuffix(region);
|
|
39138
39305
|
const providerName = `cognito-idp.${region}.${urlSuffix}/${userPoolId}`;
|
|
39139
39306
|
const providerUrl = `https://cognito-idp.${region}.${urlSuffix}/${userPoolId}`;
|
|
39140
|
-
await this.applyMfaConfig(userPoolId, properties);
|
|
39307
|
+
await this.applyMfaConfig(userPoolId, properties, mfaConfiguration);
|
|
39141
39308
|
this.logger.debug(`Successfully created Cognito User Pool ${logicalId}: ${userPoolId}`);
|
|
39309
|
+
const effectiveProperties = narrowMfaConfiguration(properties);
|
|
39142
39310
|
return {
|
|
39143
39311
|
physicalId: userPoolId,
|
|
39144
39312
|
attributes: {
|
|
@@ -39146,7 +39314,8 @@ var CognitoUserPoolProvider = class {
|
|
|
39146
39314
|
ProviderName: providerName,
|
|
39147
39315
|
ProviderURL: providerUrl,
|
|
39148
39316
|
UserPoolId: userPoolId
|
|
39149
|
-
}
|
|
39317
|
+
},
|
|
39318
|
+
...effectiveProperties !== properties ? { effectiveProperties } : {}
|
|
39150
39319
|
};
|
|
39151
39320
|
} catch (error) {
|
|
39152
39321
|
if (createdUserPoolId) try {
|
|
@@ -39166,10 +39335,109 @@ var CognitoUserPoolProvider = class {
|
|
|
39166
39335
|
* control-plane writes on a freshly-created pool can briefly conflict
|
|
39167
39336
|
* (mirrors DynamoDBTableProvider.retryOnTransientControlPlane).
|
|
39168
39337
|
*/
|
|
39169
|
-
async applyMfaConfig(physicalId, properties) {
|
|
39170
|
-
const request = buildMfaConfigRequest(physicalId, properties, this.logger);
|
|
39338
|
+
async applyMfaConfig(physicalId, properties, declaredMfaConfiguration, options = {}) {
|
|
39339
|
+
const request = buildMfaConfigRequest(physicalId, properties, this.logger, declaredMfaConfiguration);
|
|
39171
39340
|
if (!request) return;
|
|
39172
39341
|
await this.retryOnTransientControlPlane(() => this.getClient().send(new SetUserPoolMfaConfigCommand(request)), `SetUserPoolMfaConfig(${physicalId})`);
|
|
39342
|
+
this.reportMfaConfigurationOff(physicalId, request, declaredMfaConfiguration, options);
|
|
39343
|
+
}
|
|
39344
|
+
/**
|
|
39345
|
+
* Say so when this deploy sends `MfaConfiguration=OFF` without the template
|
|
39346
|
+
* having asked for OFF (issue #1925, third item).
|
|
39347
|
+
*
|
|
39348
|
+
* Everything here keys on the BUILT request, so there is exactly one
|
|
39349
|
+
* definition of "this deploy resolves to OFF", and on `declaredMfaConfiguration
|
|
39350
|
+
* === ''`, i.e. the template did not pin a usable value. `create()` passes
|
|
39351
|
+
* neither a live value nor a `declaredKind`, so it reports nothing -- correct,
|
|
39352
|
+
* since a fresh pool has no value to downgrade.
|
|
39353
|
+
*
|
|
39354
|
+
* Three outcomes rather than one, because the live value can be KNOWN,
|
|
39355
|
+
* known-and-harmless, or UNAVAILABLE, and only the first is a downgrade that
|
|
39356
|
+
* can be named:
|
|
39357
|
+
*
|
|
39358
|
+
* - live `ON` / `OPTIONAL` -- a real downgrade; name the value being lost.
|
|
39359
|
+
* - live `OFF` -- not a downgrade at all; say nothing. This is the arm the
|
|
39360
|
+
* live-value test protects, and it is load-bearing in the SILENT
|
|
39361
|
+
* direction: without it every already-OFF pool and every failed probe
|
|
39362
|
+
* warned, the latter reading `live value was undefined`.
|
|
39363
|
+
* - live UNKNOWN (the probe failed) -- the case that made this necessary.
|
|
39364
|
+
* A malformed but TRUTHY value used to reach `UpdateUserPool`, AWS
|
|
39365
|
+
* rejected the enum, MFA stayed as it was and the deploy failed; now the
|
|
39366
|
+
* guard substitutes and the deploy exits 0 with MFA off. On a role lacking
|
|
39367
|
+
* `cognito-idp:GetUserPoolMfaConfig` -- exactly the role this arm exists
|
|
39368
|
+
* for -- the probe returns nothing, so without this the ONLY path that got
|
|
39369
|
+
* quieter than main would say nothing at all.
|
|
39370
|
+
*/
|
|
39371
|
+
reportMfaConfigurationOff(physicalId, request, declaredMfaConfiguration, options) {
|
|
39372
|
+
if (declaredMfaConfiguration !== "" || request.MfaConfiguration !== "OFF") return;
|
|
39373
|
+
const kind = options.declaredKind ?? "absent";
|
|
39374
|
+
const cause = kind === "refused" ? "the declared MfaConfiguration was refused as malformed (see the warning above), so this update sent MfaConfiguration=OFF instead" : kind === "blank" ? "the declared MfaConfiguration is blank, so it is treated as absent and this update sent MfaConfiguration=OFF" : "the template declares no MfaConfiguration, so this update sent MfaConfiguration=OFF (CloudFormation's own default)";
|
|
39375
|
+
const remedy = (value) => kind === "absent" ? `Declare MfaConfiguration: ${value} in the template to keep it.` : `Repair MfaConfiguration to a literal ${value} to keep it.`;
|
|
39376
|
+
if (options.liveMfaConfiguration === "ON" || options.liveMfaConfiguration === "OPTIONAL") {
|
|
39377
|
+
this.logger.warn(`UserPool ${physicalId}: ${cause} to a pool whose live value was ${options.liveMfaConfiguration} — SetUserPoolMfaConfig is a full replace, so MFA is now OFF. ${remedy(options.liveMfaConfiguration)}`);
|
|
39378
|
+
return;
|
|
39379
|
+
}
|
|
39380
|
+
if (options.liveReadFailed !== true) return;
|
|
39381
|
+
const declaredClause = kind === "absent" ? `the template declares no MfaConfiguration` : `the declared MfaConfiguration could not be used`;
|
|
39382
|
+
this.logger.warn(`UserPool ${physicalId}: ${declaredClause}, so this update sent MfaConfiguration=OFF — and the pool's previous MFA setting could not be read, so cdkd cannot say whether that turned MFA off. Grant cognito-idp:GetUserPoolMfaConfig to the deploy role to have this reported precisely. ${remedy("ON or OPTIONAL")}`);
|
|
39383
|
+
}
|
|
39384
|
+
/**
|
|
39385
|
+
* Read the pool's live `MfaConfiguration` for the undeclared-downgrade
|
|
39386
|
+
* announcement (issue #1925, third item), or `undefined` when it cannot be
|
|
39387
|
+
* determined.
|
|
39388
|
+
*
|
|
39389
|
+
* `SetUserPoolMfaConfig` is a full replace and this provider re-issues it on
|
|
39390
|
+
* every update carrying an MFA-routed property, unconditioned on the MFA
|
|
39391
|
+
* configuration having CHANGED. So a WebAuthn-only template applied to a pool
|
|
39392
|
+
* whose live `MfaConfiguration` is `ON` / `OPTIONAL` — console drift, or a
|
|
39393
|
+
* `cdkd import` of an MFA-enabled pool — writes `OFF` on the next unrelated
|
|
39394
|
+
* property change. That is defensible template-is-truth / CloudFormation
|
|
39395
|
+
* parity and is NOT changed here; only its silence is.
|
|
39396
|
+
*
|
|
39397
|
+
* **Called BEFORE `UpdateUserPool`, defensively — NOT because AWS resets the
|
|
39398
|
+
* field.** MEASURED us-east-1 2026-08-18: a pool at `ON` with software-token
|
|
39399
|
+
* enabled keeps `ON` through an `UpdateUserPool` that omits
|
|
39400
|
+
* `MfaConfiguration`, confirmed by both `get-user-pool-mfa-config` and
|
|
39401
|
+
* `describe-user-pool`, with controls proving the call really ran (a
|
|
39402
|
+
* `--auto-verified-attributes` change in the same request applied) and that
|
|
39403
|
+
* the field is writable here rather than ignored (an explicit
|
|
39404
|
+
* `--mfa-configuration OFF` did reset it). So AWS's blanket "unspecified
|
|
39405
|
+
* parameters are set to their default value" holds field by field —
|
|
39406
|
+
* `AutoVerifiedAttributes` DOES reset, `MfaConfiguration` does not — and
|
|
39407
|
+
* there is no MFA-OFF window to design around.
|
|
39408
|
+
*
|
|
39409
|
+
* The earlier ordering was reached from that doc sentence alone and is kept
|
|
39410
|
+
* only because it is strictly safer and already tested: reading first cannot
|
|
39411
|
+
* report a value this same call clobbered, whatever AWS does later. Do not
|
|
39412
|
+
* re-derive a redesign from the doc sentence — it has been measured.
|
|
39413
|
+
*
|
|
39414
|
+
* Best-effort by construction: the read exists only to ANNOUNCE, so a
|
|
39415
|
+
* failure must not fail the update the user asked for.
|
|
39416
|
+
*
|
|
39417
|
+
* **This adds `cognito-idp:GetUserPoolMfaConfig` to the permissions a deploy
|
|
39418
|
+
* role wants.** The action was previously needed only by `readCurrentState`
|
|
39419
|
+
* (drift / import), so a role scoped to deploying could legitimately lack it.
|
|
39420
|
+
*
|
|
39421
|
+
* A failure is REPORTED rather than swallowed, but not here: this method's
|
|
39422
|
+
* gate is a deliberate SUPERSET of the announcement condition (see the call
|
|
39423
|
+
* site in `update()`), so warning at the point of failure fired on templates
|
|
39424
|
+
* that structurally cannot downgrade -- an `EnabledMfas` with no
|
|
39425
|
+
* `MfaConfiguration` resolves to OPTIONAL, and a least-privileged role saw
|
|
39426
|
+
* "cdkd cannot say whether it turns MFA off" on every deploy of it. The flag
|
|
39427
|
+
* returned here is consumed by `reportMfaConfigurationOff`, which speaks only
|
|
39428
|
+
* where the request actually resolves to OFF.
|
|
39429
|
+
*/
|
|
39430
|
+
async readLiveMfaConfiguration(physicalId) {
|
|
39431
|
+
try {
|
|
39432
|
+
const live = await this.getClient().send(new GetUserPoolMfaConfigCommand({ UserPoolId: physicalId }));
|
|
39433
|
+
return live.MfaConfiguration !== void 0 ? {
|
|
39434
|
+
value: live.MfaConfiguration,
|
|
39435
|
+
failed: false
|
|
39436
|
+
} : { failed: false };
|
|
39437
|
+
} catch (error) {
|
|
39438
|
+
this.logger.debug(`GetUserPoolMfaConfig failed for UserPool ${physicalId} (${error instanceof Error ? error.name : typeof error}): ${error instanceof Error ? error.message : String(error)}`);
|
|
39439
|
+
return { failed: true };
|
|
39440
|
+
}
|
|
39173
39441
|
}
|
|
39174
39442
|
/**
|
|
39175
39443
|
* Retry a Cognito control-plane call on transient "settling" errors. A
|
|
@@ -39199,6 +39467,9 @@ var CognitoUserPoolProvider = class {
|
|
|
39199
39467
|
*/
|
|
39200
39468
|
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
39201
39469
|
this.logger.debug(`Updating Cognito User Pool ${logicalId}: ${physicalId}`);
|
|
39470
|
+
const mfaConfiguration = readDeclaredMfaConfiguration(properties["MfaConfiguration"], { onUnusable: (message) => this.logger.warn(message) });
|
|
39471
|
+
this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
|
|
39472
|
+
const liveMfa = mfaConfiguration === "" && hasMfaConfigProps(properties) ? await this.readLiveMfaConfiguration(physicalId) : void 0;
|
|
39202
39473
|
try {
|
|
39203
39474
|
const updateParams = { UserPoolId: physicalId };
|
|
39204
39475
|
if (properties["Policies"]) {
|
|
@@ -39207,7 +39478,7 @@ var CognitoUserPoolProvider = class {
|
|
|
39207
39478
|
}
|
|
39208
39479
|
if (properties["LambdaConfig"]) updateParams.LambdaConfig = properties["LambdaConfig"];
|
|
39209
39480
|
if (properties["AutoVerifiedAttributes"]) updateParams.AutoVerifiedAttributes = properties["AutoVerifiedAttributes"];
|
|
39210
|
-
if (properties
|
|
39481
|
+
if (mfaConfiguration && !hasMfaConfigProps(properties)) updateParams.MfaConfiguration = mfaConfiguration;
|
|
39211
39482
|
if (properties["AdminCreateUserConfig"]) updateParams.AdminCreateUserConfig = properties["AdminCreateUserConfig"];
|
|
39212
39483
|
if (properties["AccountRecoverySetting"]) updateParams.AccountRecoverySetting = properties["AccountRecoverySetting"];
|
|
39213
39484
|
if (properties["UserPoolTags"]) updateParams.UserPoolTags = properties["UserPoolTags"];
|
|
@@ -39225,13 +39496,18 @@ var CognitoUserPoolProvider = class {
|
|
|
39225
39496
|
if (properties["UserPoolTier"]) updateParams.UserPoolTier = properties["UserPoolTier"];
|
|
39226
39497
|
await this.getClient().send(new UpdateUserPoolCommand(updateParams));
|
|
39227
39498
|
await this.reconcileSchemaCustomAttributes(logicalId, physicalId, resourceType, properties["Schema"], previousProperties["Schema"]);
|
|
39228
|
-
await this.applyMfaConfig(physicalId, properties
|
|
39499
|
+
await this.applyMfaConfig(physicalId, properties, mfaConfiguration, {
|
|
39500
|
+
...liveMfa?.value !== void 0 ? { liveMfaConfiguration: liveMfa.value } : {},
|
|
39501
|
+
...liveMfa?.failed === true ? { liveReadFailed: true } : {},
|
|
39502
|
+
declaredKind: classifyDeclaredMfaConfiguration(properties["MfaConfiguration"])
|
|
39503
|
+
});
|
|
39229
39504
|
this.logger.debug(`Successfully updated Cognito User Pool ${logicalId}`);
|
|
39230
39505
|
const userPool = (await this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId }))).UserPool;
|
|
39231
39506
|
const region = await this.getClient().config.region();
|
|
39232
39507
|
const { urlSuffix } = derivePartitionAndUrlSuffix(region);
|
|
39233
39508
|
const providerName = `cognito-idp.${region}.${urlSuffix}/${physicalId}`;
|
|
39234
39509
|
const providerUrl = `https://cognito-idp.${region}.${urlSuffix}/${physicalId}`;
|
|
39510
|
+
const effectiveProperties = narrowMfaConfiguration(properties);
|
|
39235
39511
|
return {
|
|
39236
39512
|
physicalId,
|
|
39237
39513
|
wasReplaced: false,
|
|
@@ -39240,7 +39516,8 @@ var CognitoUserPoolProvider = class {
|
|
|
39240
39516
|
ProviderName: providerName,
|
|
39241
39517
|
ProviderURL: providerUrl,
|
|
39242
39518
|
UserPoolId: physicalId
|
|
39243
|
-
}
|
|
39519
|
+
},
|
|
39520
|
+
...effectiveProperties !== properties ? { effectiveProperties } : {}
|
|
39244
39521
|
};
|
|
39245
39522
|
} catch (error) {
|
|
39246
39523
|
if (error instanceof ResourceUpdateNotSupportedError || error instanceof ProvisioningError) throw error;
|
|
@@ -80969,7 +81246,7 @@ function createMigrateCommand() {
|
|
|
80969
81246
|
*/
|
|
80970
81247
|
function buildProgram() {
|
|
80971
81248
|
const program = new Command();
|
|
80972
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.
|
|
81249
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.36");
|
|
80973
81250
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
80974
81251
|
const { profile } = actionCommand.optsWithGlobals();
|
|
80975
81252
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|