quidproquo-deploy-awscdk 0.1.21 → 0.1.23
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/lib/commonjs/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.d.ts +1 -0
- package/lib/commonjs/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.js +29 -1
- package/lib/commonjs/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.js.map +1 -1
- package/lib/commonjs/stacks/InfQpqServiceStack.js +5 -0
- package/lib/commonjs/stacks/InfQpqServiceStack.js.map +1 -1
- package/lib/esm/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.d.ts +1 -0
- package/lib/esm/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.js +30 -2
- package/lib/esm/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.js.map +1 -1
- package/lib/esm/stacks/InfQpqServiceStack.js +5 -0
- package/lib/esm/stacks/InfQpqServiceStack.js.map +1 -1
- package/package.json +7 -7
- package/src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.test.ts +61 -0
- package/src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.ts +38 -2
- package/src/stacks/InfQpqServiceStack.ts +6 -0
|
@@ -9,5 +9,6 @@ export declare class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock
|
|
|
9
9
|
userPool: aws_cognito.IUserPool;
|
|
10
10
|
static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct;
|
|
11
11
|
constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps);
|
|
12
|
+
static authorizeReadActionsForRole(role: aws_iam.IRole, referencedDirectoryConfigs: UserDirectoryQPQConfigSetting[], qpqConfig: QPQConfig): void;
|
|
12
13
|
static authorizeAdminActionsForRole(role: aws_iam.IRole, userDirectoryConfigs: UserDirectoryQPQConfigSetting[], userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[], qpqConfig: QPQConfig): void;
|
|
13
14
|
}
|
|
@@ -207,8 +207,36 @@ class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock_1.QpqConstructB
|
|
|
207
207
|
});
|
|
208
208
|
qpqDeployAwsCdkUtils.exportStackValue(this, quidproquo_actionprocessor_awslambda_1.awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig), userPoolClient.userPoolClientId);
|
|
209
209
|
}
|
|
210
|
+
// Grants READ-ONLY Cognito actions on user directories this service merely
|
|
211
|
+
// references (owned by another service): look a user up by attribute / by id
|
|
212
|
+
// (askUserDirectoryGetUsersByAttribute, askUserDirectoryGetUserAttributesByUserId).
|
|
213
|
+
// Any service that shows "who" needs this - e.g. the tenant registry adding a
|
|
214
|
+
// member by email from a service that doesn't own the pool. Nothing that
|
|
215
|
+
// mutates the pool: admin actions stay with the owner (below). Cognito has no
|
|
216
|
+
// resource policy, so a pool in another account can't be granted this way -
|
|
217
|
+
// such directories are skipped (the call fails as it does today).
|
|
218
|
+
static authorizeReadActionsForRole(role, referencedDirectoryConfigs, qpqConfig) {
|
|
219
|
+
const local = (0, quidproquo_config_aws_1.getLocalServiceAccountInfo)(qpqConfig);
|
|
220
|
+
const resources = referencedDirectoryConfigs
|
|
221
|
+
.map((userDirectoryConfig) => ({
|
|
222
|
+
userDirectoryConfig,
|
|
223
|
+
account: (0, quidproquo_config_aws_1.resolveAwsServiceAccountInfo)(qpqConfig, userDirectoryConfig.owner),
|
|
224
|
+
}))
|
|
225
|
+
.filter(({ account }) => account.awsAccountId === local.awsAccountId && account.awsRegion === local.awsRegion)
|
|
226
|
+
.map(({ userDirectoryConfig, account }) => {
|
|
227
|
+
const userPoolId = qpqDeployAwsCdkUtils.importStackValue(quidproquo_actionprocessor_awslambda_1.awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryConfig.name, qpqConfig));
|
|
228
|
+
return `arn:aws:cognito-idp:${account.awsRegion}:${account.awsAccountId}:userpool/${userPoolId}`;
|
|
229
|
+
});
|
|
230
|
+
if (resources.length > 0) {
|
|
231
|
+
role.addToPrincipalPolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
|
|
232
|
+
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
|
|
233
|
+
actions: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],
|
|
234
|
+
resources,
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
210
238
|
// Grants admin Cognito actions for pools this service owns. Services that
|
|
211
|
-
// only reference a foreign user directory get
|
|
239
|
+
// only reference a foreign user directory get only the read grant above —
|
|
212
240
|
// token validation runs against the pool's public JWKs over HTTPS and needs
|
|
213
241
|
// no IAM. Call sites must pass only owned directories (see
|
|
214
242
|
// `qpqCoreUtils.getOwnedUserDirectories`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QpqInfCoreUserDirectoryConstruct.js","sourceRoot":"","sources":["../../../../../../src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+FAAsE;AACtE,iEAAmH;AACnH,qDAA+H;AAG/H,6CAAiG;AACjG,iDAAmC;AAGnC,wEAA0D;AAC1D,qDAAgH;AAChH,uEAA4F;AAE5F,oFAAiF;AACjF,sDAAmD;AAMnD,MAAM,UAAU,GAAG,CAAC,IAA0B,EAAmB,EAAE;IACjE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,sCAAoB,CAAC,QAAQ;YAChC,OAAO,yBAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClC,KAAK,sCAAoB,CAAC,QAAQ;YAChC,OAAO,yBAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClC,KAAK,sCAAoB,CAAC,GAAG,CAAC;QAC9B;YACE,OAAO,yBAAW,CAAC,GAAG,CAAC,GAAG,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC;AAEF,MAAa,gCAAiC,SAAQ,qCAAiB;IAGrE,MAAM,CAAC,cAAc,CAAC,KAAgB,EAAE,EAAU,EAAE,SAAoB,EAAE,iBAAyB;QACjG,MAAM,UAAU,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,qDAAc,CAAC,mCAAmC,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3I,MAAM,MAAO,SAAQ,qCAAiB;YAAtC;;gBACE,aAAQ,GAAG,yBAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAC9E,CAAC;SAAA;QAED,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,YAAY,KAAgB,EAAE,EAAU,EAAE,KAA4C;;QACpF,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAEvE,MAAM,sBAAsB,GAAG,yCAAiB,CAAC,4BAA4B,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE/F,MAAM,QAAQ,GAAG,IAAI,yBAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE;YAC3D,uFAAuF;YACvF,gGAAgG;YAChG,kFAAkF;YAClF,aAAa,EAAE,sBAAsB,KAAK,iDAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM;YAClI,kBAAkB,EAAE,sBAAsB,KAAK,iDAAyB,CAAC,MAAM;YAC/E,YAAY,EAAE,YAAY;YAC1B,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,iBAAiB;YAC9D,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;YACnD,iFAAiF;YACjF,eAAe,EAAE;gBACf,GAAG,EAAE,CAAC,MAAA,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,8CAA4B,CAAC,IAAI,CAAC;gBACpG,GAAG,EAAE,KAAK;aACX;YACD,cAAc,EAAE;gBACd,SAAS,EAAE,EAAE;gBACb,gBAAgB,EAAE,IAAI;gBACtB,gBAAgB,EAAE,IAAI;gBACtB,aAAa,EAAE,IAAI;gBACnB,cAAc,EAAE,IAAI;aACrB;YACD,kBAAkB,EAAE;gBAClB,KAAK,EAAE;oBACL,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,IAAI;iBACd;gBACD,WAAW,EAAE;oBACX,QAAQ,EAAE,KAAK,CAAC,mBAAmB,CAAC,aAAa;oBACjD,OAAO,EAAE,IAAI;iBACd;aACF;YACD,UAAU,EAAE;gBACV,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,KAAK,CAAC,mBAAmB,CAAC,aAAa;aAC/C;YACD,mBAAmB;YACnB,oBAAoB;YACpB,iBAAiB;YACjB,KAAK;SACN,CAAC,CAAC;QAEH,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAErE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IACE,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,aAAa;YACtD,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,kBAAkB;YAC3D,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,WAAW,EACpD,CAAC;YACD,MAAM,oBAAoB,GAAG,IAAI,mBAAQ,CAAC,IAAI,EAAE,sBAAsB,EAAE;gBACtE,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;gBAClF,YAAY,EAAE,yCAAyC;gBACvD,YAAY,EAAE,yCAAyC;gBAEvD,SAAS,EAAE,KAAK,CAAC,SAAS;gBAE1B,WAAW,EAAE;oBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;iBAClD;gBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;aAC5B,CAAC,CAAC;YAEH,QAAQ,CAAC,UAAU,CAAC,yBAAW,CAAC,iBAAiB,CAAC,cAAc,EAAE,oBAAoB,CAAC,cAAc,CAAC,CAAC;QACzG,CAAC;QAED,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,CAAC;YAChD,MAAM,uBAAuB,GAAG,IAAI,mBAAQ,CAAC,IAAI,EAAE,oBAAoB,EAAE;gBACvE,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;gBACrF,YAAY,EAAE,+CAA+C;gBAC7D,YAAY,EAAE,+CAA+C;gBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;gBAE1B,WAAW,EAAE;oBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;iBAClD;gBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;aAC5B,CAAC,CAAC;YAEH,QAAQ,CAAC,UAAU,CAAC,yBAAW,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC;YAEjH,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mBAAmB,EAAE,CAAC;gBACpE,MAAM,0BAA0B,GAAG,IAAI,mBAAQ,CAAC,IAAI,EAAE,uBAAuB,EAAE;oBAC7E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;oBACrF,YAAY,EAAE,+CAA+C;oBAC7D,YAAY,EAAE,+CAA+C;oBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;oBAE1B,WAAW,EAAE;wBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;qBAClD;oBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;iBAC5B,CAAC,CAAC;gBACH,QAAQ,CAAC,UAAU,CAAC,yBAAW,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,cAAc,CAAC,CAAC;YACtH,CAAC;YAED,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mBAAmB,EAAE,CAAC;gBACpE,MAAM,0BAA0B,GAAG,IAAI,mBAAQ,CAAC,IAAI,EAAE,uBAAuB,EAAE;oBAC7E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;oBACrF,YAAY,EAAE,+CAA+C;oBAC7D,YAAY,EAAE,+CAA+C;oBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;oBAE1B,WAAW,EAAE;wBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;qBAClD;oBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;iBAC5B,CAAC,CAAC;gBACH,QAAQ,CAAC,UAAU,CAAC,yBAAW,CAAC,iBAAiB,CAAC,8BAA8B,EAAE,0BAA0B,CAAC,cAAc,CAAC,CAAC;YAC/H,CAAC;QACH,CAAC;QAED,oBAAoB,CAAC,gBAAgB,CACnC,IAAI,EACJ,qDAAc,CAAC,mCAAmC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EACnG,IAAI,CAAC,QAAQ,CAAC,UAAU,CACzB,CAAC;QAEF,IAAI,KAAK,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC;YACxC,qFAAqF;YACrF,2EAA2E;YAC3E,MAAM,UAAU,GAAG,IAAA,iCAAwB,EAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;YAC3H,MAAM,UAAU,GAAG,IAAA,yBAAgB,EAAC,IAAI,EAAE,IAAA,iCAAwB,EAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;YACjG,MAAM,WAAW,GAAG,IAAA,iDAAuB,EAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhH,MAAM,cAAc,GAAG,IAAI,yBAAW,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE;gBAC9E,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBAEvB,qBAAqB;gBACrB,YAAY,EAAE;oBACZ,WAAW;oBACX,UAAU,EAAE,UAAU;iBACvB;aACF,CAAC,CAAC;YAEH,IAAI,yBAAW,CAAC,OAAO,CAAC,IAAI,EAAE,0BAA0B,EAAE;gBACxD,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,yBAAW,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,iCAAmB,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;aACzG,CAAC,CAAC;QACL,CAAC;QAED,qFAAqF;QACrF,uFAAuF;QACvF,uFAAuF;QACvF,2EAA2E;QAC3E,MAAM,0BAA0B,GAAG,KAAK,CAAC,mBAAmB,CAAC,0BAA0B,CAAC;QACxF,MAAM,aAAa,GAAG,0BAA0B,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9H,MAAM,cAAc,GAAG,IAAI,yBAAW,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE;YAC9E,kBAAkB,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC;YAC/E,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE;gBACT,iBAAiB,EAAE,IAAI;gBACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,iBAAiB;aACtD;YACD,mBAAmB,EAAE,aAAa;YAClC,eAAe,EAAE,aAAa;SAC/B,CAAC,CAAC;QAEH,oBAAoB,CAAC,gBAAgB,CACnC,IAAI,EACJ,qDAAc,CAAC,yCAAyC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EACzG,cAAc,CAAC,gBAAgB,CAChC,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,2DAA2D;IAC3D,2CAA2C;IACpC,MAAM,CAAC,4BAA4B,CACxC,IAAmB,EACnB,oBAAqD,EACrD,uBAA2D,EAC3D,SAAoB;QAEpB,IAAI,uBAAuB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,oBAAoB,CACvB,IAAI,qBAAO,CAAC,eAAe,CAAC;gBAC1B,MAAM,EAAE,qBAAO,CAAC,MAAM,CAAC,KAAK;gBAC5B,OAAO,EAAE;oBACP,oBAAoB;oBACpB,6BAA6B;oBAC7B,+BAA+B;oBAC/B,yCAAyC;oBACzC,iCAAiC;oBACjC,6BAA6B;oBAC7B,uCAAuC;oBACvC,uCAAuC;oBACvC,kCAAkC;oBAElC,uBAAuB;oBACvB,qBAAqB;oBACrB,0BAA0B;oBAC1B,wBAAwB;oBACxB,sBAAsB;oBACtB,2BAA2B;oBAC3B,8BAA8B;oBAC9B,oCAAoC;iBACrC;gBACD,SAAS,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE;oBACjE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,IAAA,oDAA4B,EAAC,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;oBAEvG,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAEtE,OAAO,uBAAuB,SAAS,IAAI,YAAY,aAAa,UAAU,EAAE,CAAC;gBACnF,CAAC,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAjPD,4EAiPC","sourcesContent":["import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { AwsDataStoreRemovalPolicy, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';\nimport { QPQConfig, UserDirectoryMfaMode, UserDirectoryMfaSecondFactor, UserDirectoryQPQConfigSetting } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { aws_cognito, aws_iam, aws_lambda, aws_route53, aws_route53_targets } from 'aws-cdk-lib';\nimport * as cdk from 'aws-cdk-lib';\nimport { Construct } from 'constructs';\n\nimport * as qpqDeployAwsCdkUtils from '../../../../utils';\nimport { lookupHostedZone, resolveDeployPrimaryHost, resolveHostedZoneForHost } from '../../../../utils/domain';\nimport { QpqConstructBlock, QpqConstructBlockProps } from '../../../base/QpqConstructBlock';\nimport { QpqResource } from '../../../base/QpqResource';\nimport { lookupDomainCertificate } from '../../../basic/DomainCertificateLookup';\nimport { Function } from '../../../basic/Function';\n\nexport interface QpqInfCoreUserDirectoryConstructProps extends QpqConstructBlockProps {\n userDirectoryConfig: UserDirectoryQPQConfigSetting;\n}\n\nconst mapMfaMode = (mode: UserDirectoryMfaMode): aws_cognito.Mfa => {\n switch (mode) {\n case UserDirectoryMfaMode.required:\n return aws_cognito.Mfa.REQUIRED;\n case UserDirectoryMfaMode.optional:\n return aws_cognito.Mfa.OPTIONAL;\n case UserDirectoryMfaMode.off:\n default:\n return aws_cognito.Mfa.OFF;\n }\n};\n\nexport class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {\n public userPool: aws_cognito.IUserPool;\n\n static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryName, qpqConfig));\n\n class Import extends QpqConstructBlock {\n userPool = aws_cognito.UserPool.fromUserPoolId(this, 'pool-id', userPoolId);\n }\n\n return new Import(scope, id, { qpqConfig });\n }\n\n constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps) {\n super(scope, id, props);\n\n const userPoolName = this.resourceName(props.userDirectoryConfig.name);\n\n const dataStoreRemovalPolicy = qpqConfigAwsUtils.getAwsDataStoreRemovalPolicy(props.qpqConfig);\n\n const userPool = new aws_cognito.UserPool(this, 'user-pool', {\n // Retain user pools by default (user accounts are unrecoverable); dev configs opt into\n // full teardown via defineAwsDataStoreRemovalPolicy(destroy). When retained, deletionProtection\n // also blocks deletes/replacements outright (RETAIN alone only orphans the pool).\n removalPolicy: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.destroy ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN,\n deletionProtection: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.retain,\n userPoolName: userPoolName,\n selfSignUpEnabled: props.userDirectoryConfig.selfSignUpEnabled,\n mfa: mapMfaMode(props.userDirectoryConfig.mfa.mode),\n // Derived from the config's enabled factors. Ignored by Cognito when mfa is OFF.\n mfaSecondFactor: {\n otp: (props.userDirectoryConfig.mfa.secondFactors ?? []).includes(UserDirectoryMfaSecondFactor.totp),\n sms: false,\n },\n passwordPolicy: {\n minLength: 12,\n requireLowercase: true,\n requireUppercase: true,\n requireDigits: true,\n requireSymbols: true,\n },\n standardAttributes: {\n email: {\n required: true,\n mutable: true,\n },\n phoneNumber: {\n required: props.userDirectoryConfig.phoneRequired,\n mutable: true,\n },\n },\n autoVerify: {\n email: true,\n phone: props.userDirectoryConfig.phoneRequired,\n },\n // signInAliases: {\n // username: true,\n // email: true,\n // },\n });\n\n qpqDeployAwsCdkUtils.applyEnvironmentTags(userPool, props.qpqConfig);\n\n this.userPool = userPool;\n\n if (\n props.userDirectoryConfig.emailTemplates.resetPassword ||\n props.userDirectoryConfig.emailTemplates.resetPasswordAdmin ||\n props.userDirectoryConfig.emailTemplates.verifyEmail\n ) {\n const customMessageTrigger = new Function(this, 'csm-msg-trigger-func', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cm-trig'),\n functionType: 'customMessageTriggerEvent_customMessage',\n executorName: 'customMessageTriggerEvent_customMessage',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.CUSTOM_MESSAGE, customMessageTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime) {\n const defAuthChallengeTrigger = new Function(this, 'def-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-define'),\n functionType: 'customMessageTriggerEvent_defineAuthChallenge',\n executorName: 'customMessageTriggerEvent_defineAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.DEFINE_AUTH_CHALLENGE, defAuthChallengeTrigger.lambdaFunction);\n\n if (props.userDirectoryConfig.customAuthRuntime.createAuthChallenge) {\n const createAuthChallengeTrigger = new Function(this, 'create-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-create'),\n functionType: 'customMessageTriggerEvent_createAuthChallenge',\n executorName: 'customMessageTriggerEvent_createAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.CREATE_AUTH_CHALLENGE, createAuthChallengeTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime.verifyAuthChallenge) {\n const verifyAuthChallengeTrigger = new Function(this, 'verify-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-verify'),\n functionType: 'customMessageTriggerEvent_verifyAuthChallenge',\n executorName: 'customMessageTriggerEvent_verifyAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.VERIFY_AUTH_CHALLENGE_RESPONSE, verifyAuthChallengeTrigger.lambdaFunction);\n }\n }\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n this.userPool.userPoolId,\n );\n\n if (props.userDirectoryConfig.dnsRecord) {\n // A pool has one custom domain, so it lives on the primary root only. Cognito custom\n // domains use CloudFront under the hood, so the cert must be in us-east-1.\n const fullDomain = resolveDeployPrimaryHost(props.qpqConfig, { subdomain: props.userDirectoryConfig.dnsRecord.subdomain });\n const hostedZone = lookupHostedZone(this, resolveHostedZoneForHost(props.qpqConfig, fullDomain));\n const certificate = lookupDomainCertificate(this, 'us-east-1', props.qpqConfig, props.userDirectoryConfig.name);\n\n const userPoolDomain = new aws_cognito.UserPoolDomain(this, 'user-pool-domain', {\n userPool: this.userPool,\n\n // Full custom domain\n customDomain: {\n certificate,\n domainName: fullDomain,\n },\n });\n\n new aws_route53.ARecord(this, 'CognitoDomainAliasRecord', {\n zone: hostedZone,\n recordName: fullDomain,\n target: aws_route53.RecordTarget.fromAlias(new aws_route53_targets.UserPoolDomainTarget(userPoolDomain)),\n });\n }\n\n // Short-lived JWTs shrink the window in which a revoked session's still-valid access\n // token keeps working (access tokens are stateless, so RevokeToken/GlobalSignOut can't\n // kill them before they expire). Omitted → Cognito's default (60 min). Applied to both\n // the access and ID tokens so the ID token can't outlive the access token.\n const accessTokenValidityMinutes = props.userDirectoryConfig.accessTokenValidityMinutes;\n const tokenValidity = accessTokenValidityMinutes !== undefined ? cdk.Duration.minutes(accessTokenValidityMinutes) : undefined;\n\n const userPoolClient = new aws_cognito.UserPoolClient(this, 'user-pool-client', {\n userPoolClientName: this.qpqResourceName(props.userDirectoryConfig.name, 'upc'),\n userPool: this.userPool,\n generateSecret: true,\n authFlows: {\n adminUserPassword: true,\n custom: !!props.userDirectoryConfig.customAuthRuntime,\n },\n accessTokenValidity: tokenValidity,\n idTokenValidity: tokenValidity,\n });\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n userPoolClient.userPoolClientId,\n );\n }\n\n // Grants admin Cognito actions for pools this service owns. Services that\n // only reference a foreign user directory get no Cognito IAM from here —\n // token validation runs against the pool's public JWKs over HTTPS and needs\n // no IAM. Call sites must pass only owned directories (see\n // `qpqCoreUtils.getOwnedUserDirectories`).\n public static authorizeAdminActionsForRole(\n role: aws_iam.IRole,\n userDirectoryConfigs: UserDirectoryQPQConfigSetting[],\n userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[],\n qpqConfig: QPQConfig,\n ) {\n if (userDirectoryConstructs.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: [\n 'cognito-idp:SignUp',\n 'cognito-idp:AdminCreateUser',\n 'cognito-idp:AdminInitiateAuth',\n 'cognito-idp:AdminRespondToAuthChallenge',\n 'cognito-idp:AdminAddUserToGroup',\n 'cognito-idp:AdminDeleteUser',\n 'cognito-idp:AdminUpdateUserAttributes',\n 'cognito-idp:AdminDeleteUserAttributes',\n 'cognito-idp:AdminSetUserPassword',\n\n 'cognito-idp:ListUsers',\n 'cognito-idp:GetUser',\n 'cognito-idp:AdminGetUser',\n 'cognito-idp:ListGroups',\n 'cognito-idp:GetGroup',\n 'cognito-idp:ListUserPools',\n 'cognito-idp:DescribeUserPool',\n 'cognito-idp:DescribeUserPoolClient',\n ],\n resources: userDirectoryConfigs.map((userDirectoryConfig, index) => {\n const { awsRegion, awsAccountId } = resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner);\n\n const userpoolId = userDirectoryConstructs[index].userPool.userPoolId;\n\n return `arn:aws:cognito-idp:${awsRegion}:${awsAccountId}:userpool/${userpoolId}`;\n }),\n }),\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"QpqInfCoreUserDirectoryConstruct.js","sourceRoot":"","sources":["../../../../../../src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.ts"],"names":[],"mappings":"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","sourcesContent":["import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { AwsDataStoreRemovalPolicy, getLocalServiceAccountInfo, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';\nimport { QPQConfig, UserDirectoryMfaMode, UserDirectoryMfaSecondFactor, UserDirectoryQPQConfigSetting } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { aws_cognito, aws_iam, aws_lambda, aws_route53, aws_route53_targets } from 'aws-cdk-lib';\nimport * as cdk from 'aws-cdk-lib';\nimport { Construct } from 'constructs';\n\nimport * as qpqDeployAwsCdkUtils from '../../../../utils';\nimport { lookupHostedZone, resolveDeployPrimaryHost, resolveHostedZoneForHost } from '../../../../utils/domain';\nimport { QpqConstructBlock, QpqConstructBlockProps } from '../../../base/QpqConstructBlock';\nimport { QpqResource } from '../../../base/QpqResource';\nimport { lookupDomainCertificate } from '../../../basic/DomainCertificateLookup';\nimport { Function } from '../../../basic/Function';\n\nexport interface QpqInfCoreUserDirectoryConstructProps extends QpqConstructBlockProps {\n userDirectoryConfig: UserDirectoryQPQConfigSetting;\n}\n\nconst mapMfaMode = (mode: UserDirectoryMfaMode): aws_cognito.Mfa => {\n switch (mode) {\n case UserDirectoryMfaMode.required:\n return aws_cognito.Mfa.REQUIRED;\n case UserDirectoryMfaMode.optional:\n return aws_cognito.Mfa.OPTIONAL;\n case UserDirectoryMfaMode.off:\n default:\n return aws_cognito.Mfa.OFF;\n }\n};\n\nexport class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {\n public userPool: aws_cognito.IUserPool;\n\n static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryName, qpqConfig));\n\n class Import extends QpqConstructBlock {\n userPool = aws_cognito.UserPool.fromUserPoolId(this, 'pool-id', userPoolId);\n }\n\n return new Import(scope, id, { qpqConfig });\n }\n\n constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps) {\n super(scope, id, props);\n\n const userPoolName = this.resourceName(props.userDirectoryConfig.name);\n\n const dataStoreRemovalPolicy = qpqConfigAwsUtils.getAwsDataStoreRemovalPolicy(props.qpqConfig);\n\n const userPool = new aws_cognito.UserPool(this, 'user-pool', {\n // Retain user pools by default (user accounts are unrecoverable); dev configs opt into\n // full teardown via defineAwsDataStoreRemovalPolicy(destroy). When retained, deletionProtection\n // also blocks deletes/replacements outright (RETAIN alone only orphans the pool).\n removalPolicy: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.destroy ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN,\n deletionProtection: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.retain,\n userPoolName: userPoolName,\n selfSignUpEnabled: props.userDirectoryConfig.selfSignUpEnabled,\n mfa: mapMfaMode(props.userDirectoryConfig.mfa.mode),\n // Derived from the config's enabled factors. Ignored by Cognito when mfa is OFF.\n mfaSecondFactor: {\n otp: (props.userDirectoryConfig.mfa.secondFactors ?? []).includes(UserDirectoryMfaSecondFactor.totp),\n sms: false,\n },\n passwordPolicy: {\n minLength: 12,\n requireLowercase: true,\n requireUppercase: true,\n requireDigits: true,\n requireSymbols: true,\n },\n standardAttributes: {\n email: {\n required: true,\n mutable: true,\n },\n phoneNumber: {\n required: props.userDirectoryConfig.phoneRequired,\n mutable: true,\n },\n },\n autoVerify: {\n email: true,\n phone: props.userDirectoryConfig.phoneRequired,\n },\n // signInAliases: {\n // username: true,\n // email: true,\n // },\n });\n\n qpqDeployAwsCdkUtils.applyEnvironmentTags(userPool, props.qpqConfig);\n\n this.userPool = userPool;\n\n if (\n props.userDirectoryConfig.emailTemplates.resetPassword ||\n props.userDirectoryConfig.emailTemplates.resetPasswordAdmin ||\n props.userDirectoryConfig.emailTemplates.verifyEmail\n ) {\n const customMessageTrigger = new Function(this, 'csm-msg-trigger-func', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cm-trig'),\n functionType: 'customMessageTriggerEvent_customMessage',\n executorName: 'customMessageTriggerEvent_customMessage',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.CUSTOM_MESSAGE, customMessageTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime) {\n const defAuthChallengeTrigger = new Function(this, 'def-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-define'),\n functionType: 'customMessageTriggerEvent_defineAuthChallenge',\n executorName: 'customMessageTriggerEvent_defineAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.DEFINE_AUTH_CHALLENGE, defAuthChallengeTrigger.lambdaFunction);\n\n if (props.userDirectoryConfig.customAuthRuntime.createAuthChallenge) {\n const createAuthChallengeTrigger = new Function(this, 'create-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-create'),\n functionType: 'customMessageTriggerEvent_createAuthChallenge',\n executorName: 'customMessageTriggerEvent_createAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.CREATE_AUTH_CHALLENGE, createAuthChallengeTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime.verifyAuthChallenge) {\n const verifyAuthChallengeTrigger = new Function(this, 'verify-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-verify'),\n functionType: 'customMessageTriggerEvent_verifyAuthChallenge',\n executorName: 'customMessageTriggerEvent_verifyAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.VERIFY_AUTH_CHALLENGE_RESPONSE, verifyAuthChallengeTrigger.lambdaFunction);\n }\n }\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n this.userPool.userPoolId,\n );\n\n if (props.userDirectoryConfig.dnsRecord) {\n // A pool has one custom domain, so it lives on the primary root only. Cognito custom\n // domains use CloudFront under the hood, so the cert must be in us-east-1.\n const fullDomain = resolveDeployPrimaryHost(props.qpqConfig, { subdomain: props.userDirectoryConfig.dnsRecord.subdomain });\n const hostedZone = lookupHostedZone(this, resolveHostedZoneForHost(props.qpqConfig, fullDomain));\n const certificate = lookupDomainCertificate(this, 'us-east-1', props.qpqConfig, props.userDirectoryConfig.name);\n\n const userPoolDomain = new aws_cognito.UserPoolDomain(this, 'user-pool-domain', {\n userPool: this.userPool,\n\n // Full custom domain\n customDomain: {\n certificate,\n domainName: fullDomain,\n },\n });\n\n new aws_route53.ARecord(this, 'CognitoDomainAliasRecord', {\n zone: hostedZone,\n recordName: fullDomain,\n target: aws_route53.RecordTarget.fromAlias(new aws_route53_targets.UserPoolDomainTarget(userPoolDomain)),\n });\n }\n\n // Short-lived JWTs shrink the window in which a revoked session's still-valid access\n // token keeps working (access tokens are stateless, so RevokeToken/GlobalSignOut can't\n // kill them before they expire). Omitted → Cognito's default (60 min). Applied to both\n // the access and ID tokens so the ID token can't outlive the access token.\n const accessTokenValidityMinutes = props.userDirectoryConfig.accessTokenValidityMinutes;\n const tokenValidity = accessTokenValidityMinutes !== undefined ? cdk.Duration.minutes(accessTokenValidityMinutes) : undefined;\n\n const userPoolClient = new aws_cognito.UserPoolClient(this, 'user-pool-client', {\n userPoolClientName: this.qpqResourceName(props.userDirectoryConfig.name, 'upc'),\n userPool: this.userPool,\n generateSecret: true,\n authFlows: {\n adminUserPassword: true,\n custom: !!props.userDirectoryConfig.customAuthRuntime,\n },\n accessTokenValidity: tokenValidity,\n idTokenValidity: tokenValidity,\n });\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n userPoolClient.userPoolClientId,\n );\n }\n\n // Grants READ-ONLY Cognito actions on user directories this service merely\n // references (owned by another service): look a user up by attribute / by id\n // (askUserDirectoryGetUsersByAttribute, askUserDirectoryGetUserAttributesByUserId).\n // Any service that shows \"who\" needs this - e.g. the tenant registry adding a\n // member by email from a service that doesn't own the pool. Nothing that\n // mutates the pool: admin actions stay with the owner (below). Cognito has no\n // resource policy, so a pool in another account can't be granted this way -\n // such directories are skipped (the call fails as it does today).\n public static authorizeReadActionsForRole(role: aws_iam.IRole, referencedDirectoryConfigs: UserDirectoryQPQConfigSetting[], qpqConfig: QPQConfig) {\n const local = getLocalServiceAccountInfo(qpqConfig);\n\n const resources = referencedDirectoryConfigs\n .map((userDirectoryConfig) => ({\n userDirectoryConfig,\n account: resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner),\n }))\n .filter(({ account }) => account.awsAccountId === local.awsAccountId && account.awsRegion === local.awsRegion)\n .map(({ userDirectoryConfig, account }) => {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryConfig.name, qpqConfig),\n );\n\n return `arn:aws:cognito-idp:${account.awsRegion}:${account.awsAccountId}:userpool/${userPoolId}`;\n });\n\n if (resources.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],\n resources,\n }),\n );\n }\n }\n\n // Grants admin Cognito actions for pools this service owns. Services that\n // only reference a foreign user directory get only the read grant above —\n // token validation runs against the pool's public JWKs over HTTPS and needs\n // no IAM. Call sites must pass only owned directories (see\n // `qpqCoreUtils.getOwnedUserDirectories`).\n public static authorizeAdminActionsForRole(\n role: aws_iam.IRole,\n userDirectoryConfigs: UserDirectoryQPQConfigSetting[],\n userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[],\n qpqConfig: QPQConfig,\n ) {\n if (userDirectoryConstructs.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: [\n 'cognito-idp:SignUp',\n 'cognito-idp:AdminCreateUser',\n 'cognito-idp:AdminInitiateAuth',\n 'cognito-idp:AdminRespondToAuthChallenge',\n 'cognito-idp:AdminAddUserToGroup',\n 'cognito-idp:AdminDeleteUser',\n 'cognito-idp:AdminUpdateUserAttributes',\n 'cognito-idp:AdminDeleteUserAttributes',\n 'cognito-idp:AdminSetUserPassword',\n\n 'cognito-idp:ListUsers',\n 'cognito-idp:GetUser',\n 'cognito-idp:AdminGetUser',\n 'cognito-idp:ListGroups',\n 'cognito-idp:GetGroup',\n 'cognito-idp:ListUserPools',\n 'cognito-idp:DescribeUserPool',\n 'cognito-idp:DescribeUserPoolClient',\n ],\n resources: userDirectoryConfigs.map((userDirectoryConfig, index) => {\n const { awsRegion, awsAccountId } = resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner);\n\n const userpoolId = userDirectoryConstructs[index].userPool.userPoolId;\n\n return `arn:aws:cognito-idp:${awsRegion}:${awsAccountId}:userpool/${userpoolId}`;\n }),\n }),\n );\n }\n }\n}\n"]}
|
|
@@ -60,6 +60,11 @@ class InfQpqServiceStack extends QpqServiceStack_1.QpqServiceStack {
|
|
|
60
60
|
userDirectoryConfig: setting,
|
|
61
61
|
}));
|
|
62
62
|
constructs_1.QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);
|
|
63
|
+
// Directories this service references but doesn't own: read-only user lookups.
|
|
64
|
+
const referencedUserDirectoriesConfigs = quidproquo_core_1.qpqCoreUtils
|
|
65
|
+
.getUserDirectories(props.qpqConfig)
|
|
66
|
+
.filter((setting) => !ownedUserDirectoriesConfigs.includes(setting));
|
|
67
|
+
constructs_1.QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(webserverRole, referencedUserDirectoriesConfigs, props.qpqConfig);
|
|
63
68
|
// Api Keys
|
|
64
69
|
const apiKeys = quidproquo_webserver_1.qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map((setting) => new constructs_1.QpqWebserverApiKeyConstruct(this, quidproquo_core_1.qpqCoreUtils.getUniqueKeyForSetting(setting), {
|
|
65
70
|
qpqConfig: props.qpqConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfQpqServiceStack.js","sourceRoot":"","sources":["../../../src/stacks/InfQpqServiceStack.ts"],"names":[],"mappings":"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","sourcesContent":["import { qpqCoreUtils } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { Construct } from 'constructs';\n\nimport { requireDomainResolver } from '../appWorkspace/requireDomainResolver';\nimport {\n QpqCoreAiConstruct,\n QpqCoreApiGraphDatabaseConstruct,\n QpqCoreCryptoKeyConstruct,\n QpqCoreEventBusConstruct,\n QpqCoreKeyValueStoreConstruct,\n QpqCoreParameterConstruct,\n QpqCoreQueueConstruct,\n QpqCoreSecretConstruct,\n QpqCoreStorageDriveConstruct,\n QpqInfCoreUserDirectoryConstruct,\n QpqWebserverApiKeyConstruct,\n QpqWebserverCertificateConstruct,\n QpqWebserverEmailSenderConstruct,\n QpqWebserverWebsocketConstruct,\n} from '../constructs';\nimport { WebserverRoll } from '../constructs/basic/WebserverRoll';\nimport { QpqWebServerCacheConstruct } from '../constructs/feature/webserver/cache/QpqWebServerCacheConstruct';\nimport { QpqServiceStack, QpqServiceStackProps } from './base/QpqServiceStack';\n\nexport interface InfQpqServiceStackProps extends QpqServiceStackProps {}\n\nexport class InfQpqServiceStack extends QpqServiceStack {\n constructor(scope: Construct, id: string, props: InfQpqServiceStackProps) {\n super(scope, id, props);\n\n // Build the role for this service.\n const webserverRole = new WebserverRoll(this, 'webserverRoll', {\n qpqConfig: props.qpqConfig,\n }).role;\n\n // Build the storage drives\n qpqCoreUtils.getOwnedStorageDrives(props.qpqConfig).map(\n (setting) =>\n new QpqCoreStorageDriveConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n storageDriveConfig: setting,\n\n corsAllowedOrigins: qpqWebServerUtils.getStorageDriveCorsAllowedOrigins(\n props.qpqConfig,\n setting.storageDrive,\n requireDomainResolver(props.qpqConfig),\n ),\n allowCloudFrontRead: qpqWebServerUtils.isStorageDriveWebEntryOrigin(props.qpqConfig, setting.storageDrive),\n }),\n );\n QpqCoreStorageDriveConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end storage drives\n\n // Build the parameters\n const parameters = qpqCoreUtils.getOwnedParameterConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreParameterConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n parameterConfig: setting,\n }),\n );\n QpqCoreParameterConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllParameterConfigs(props.qpqConfig), props.qpqConfig);\n // end parameters\n\n // Secrets\n const secrets = qpqCoreUtils.getOwnedSecrets(props.qpqConfig).map(\n (setting) =>\n new QpqCoreSecretConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n secretConfig: setting,\n }),\n );\n QpqCoreSecretConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllSecretConfigs(props.qpqConfig), props.qpqConfig);\n // end secrets\n\n // Crypto keys\n const cryptoKeys = qpqCoreUtils.getOwnedCryptoKeys(props.qpqConfig).map(\n (setting) =>\n new QpqCoreCryptoKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cryptoKeyConfig: setting,\n }),\n );\n QpqCoreCryptoKeyConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllCryptoKeyConfigs(props.qpqConfig), props.qpqConfig);\n // end crypto keys\n\n // Queues\n const queues = qpqCoreUtils.getQueues(props.qpqConfig).map(\n (setting) =>\n new QpqCoreQueueConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n queueConfig: setting,\n }),\n );\n QpqCoreQueueConstruct.authorizeActionsForRole(webserverRole, queues);\n // end queues\n\n // User Directories\n const ownedUserDirectoriesConfigs = qpqCoreUtils.getOwnedUserDirectories(props.qpqConfig);\n const userDirectories = ownedUserDirectoriesConfigs.map(\n (setting) =>\n new QpqInfCoreUserDirectoryConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n userDirectoryConfig: setting,\n }),\n );\n QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);\n\n // Api Keys\n const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverApiKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n apiKeyConfig: setting,\n }),\n );\n\n // Event Busses\n const eventBusses = qpqCoreUtils.getOwnedEventBusConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreEventBusConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n eventBusConfig: setting,\n }),\n );\n\n // key value store\n qpqCoreUtils.getOwnedKeyValueStores(props.qpqConfig).map(\n (setting) =>\n new QpqCoreKeyValueStoreConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n keyValueStoreConfig: setting,\n }),\n );\n QpqCoreKeyValueStoreConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end key value store\n\n // Graph Databases\n const allGraphDatabaseConfigs = qpqCoreUtils.getAllGraphDatabaseConfigs(props.qpqConfig);\n const graphDatabases = qpqCoreUtils.getOwnedGraphDatabases(props.qpqConfig).map(\n (setting) =>\n new QpqCoreApiGraphDatabaseConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n graphDatabaseConfig: setting,\n }),\n );\n QpqCoreApiGraphDatabaseConstruct.authorizeActionsForRole(webserverRole, allGraphDatabaseConfigs, props.qpqConfig);\n // end key value store\n\n // AI (Bedrock)\n QpqCoreAiConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllAiConfigs(props.qpqConfig));\n // end AI\n\n // Build websocket apis\n const websockets = qpqWebServerUtils.getOwnedWebsocketSettings(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverWebsocketConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n websocketConfig: setting,\n }),\n );\n QpqWebserverWebsocketConstruct.authorizeManageConnectionsForRole(webserverRole, websockets, props.qpqConfig);\n\n // Email senders (SES identities). The construct id is keyed by the primary root, not the\n // setting: an SES identity's physical id is the domain itself, so a changed logical id would\n // fail creation against the identity the stack already owns.\n const emailSenderConfigs = qpqWebServerUtils.getEmailSenderSettings(props.qpqConfig);\n const emailSenderConstructId = `EmailSender${qpqWebServerUtils.getPrimaryRootDomain(props.qpqConfig) ?? ''}`;\n emailSenderConfigs.map(\n (setting) =>\n new QpqWebserverEmailSenderConstruct(this, emailSenderConstructId, {\n qpqConfig: props.qpqConfig,\n\n emailSenderConfig: setting,\n }),\n );\n QpqWebserverEmailSenderConstruct.authorizeSendEmailForRole(webserverRole, emailSenderConfigs, props.qpqConfig);\n\n // Cache settings\n const cache = qpqWebServerUtils.getAllOwnedCacheConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebServerCacheConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cacheConfig: setting,\n }),\n );\n\n // Certifcates\n const certifcates = qpqWebServerUtils.getAllOwnedCertifcateConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverCertificateConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n certificateConfig: setting,\n }),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InfQpqServiceStack.js","sourceRoot":"","sources":["../../../src/stacks/InfQpqServiceStack.ts"],"names":[],"mappings":"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","sourcesContent":["import { qpqCoreUtils } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { Construct } from 'constructs';\n\nimport { requireDomainResolver } from '../appWorkspace/requireDomainResolver';\nimport {\n QpqCoreAiConstruct,\n QpqCoreApiGraphDatabaseConstruct,\n QpqCoreCryptoKeyConstruct,\n QpqCoreEventBusConstruct,\n QpqCoreKeyValueStoreConstruct,\n QpqCoreParameterConstruct,\n QpqCoreQueueConstruct,\n QpqCoreSecretConstruct,\n QpqCoreStorageDriveConstruct,\n QpqInfCoreUserDirectoryConstruct,\n QpqWebserverApiKeyConstruct,\n QpqWebserverCertificateConstruct,\n QpqWebserverEmailSenderConstruct,\n QpqWebserverWebsocketConstruct,\n} from '../constructs';\nimport { WebserverRoll } from '../constructs/basic/WebserverRoll';\nimport { QpqWebServerCacheConstruct } from '../constructs/feature/webserver/cache/QpqWebServerCacheConstruct';\nimport { QpqServiceStack, QpqServiceStackProps } from './base/QpqServiceStack';\n\nexport interface InfQpqServiceStackProps extends QpqServiceStackProps {}\n\nexport class InfQpqServiceStack extends QpqServiceStack {\n constructor(scope: Construct, id: string, props: InfQpqServiceStackProps) {\n super(scope, id, props);\n\n // Build the role for this service.\n const webserverRole = new WebserverRoll(this, 'webserverRoll', {\n qpqConfig: props.qpqConfig,\n }).role;\n\n // Build the storage drives\n qpqCoreUtils.getOwnedStorageDrives(props.qpqConfig).map(\n (setting) =>\n new QpqCoreStorageDriveConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n storageDriveConfig: setting,\n\n corsAllowedOrigins: qpqWebServerUtils.getStorageDriveCorsAllowedOrigins(\n props.qpqConfig,\n setting.storageDrive,\n requireDomainResolver(props.qpqConfig),\n ),\n allowCloudFrontRead: qpqWebServerUtils.isStorageDriveWebEntryOrigin(props.qpqConfig, setting.storageDrive),\n }),\n );\n QpqCoreStorageDriveConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end storage drives\n\n // Build the parameters\n const parameters = qpqCoreUtils.getOwnedParameterConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreParameterConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n parameterConfig: setting,\n }),\n );\n QpqCoreParameterConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllParameterConfigs(props.qpqConfig), props.qpqConfig);\n // end parameters\n\n // Secrets\n const secrets = qpqCoreUtils.getOwnedSecrets(props.qpqConfig).map(\n (setting) =>\n new QpqCoreSecretConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n secretConfig: setting,\n }),\n );\n QpqCoreSecretConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllSecretConfigs(props.qpqConfig), props.qpqConfig);\n // end secrets\n\n // Crypto keys\n const cryptoKeys = qpqCoreUtils.getOwnedCryptoKeys(props.qpqConfig).map(\n (setting) =>\n new QpqCoreCryptoKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cryptoKeyConfig: setting,\n }),\n );\n QpqCoreCryptoKeyConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllCryptoKeyConfigs(props.qpqConfig), props.qpqConfig);\n // end crypto keys\n\n // Queues\n const queues = qpqCoreUtils.getQueues(props.qpqConfig).map(\n (setting) =>\n new QpqCoreQueueConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n queueConfig: setting,\n }),\n );\n QpqCoreQueueConstruct.authorizeActionsForRole(webserverRole, queues);\n // end queues\n\n // User Directories\n const ownedUserDirectoriesConfigs = qpqCoreUtils.getOwnedUserDirectories(props.qpqConfig);\n const userDirectories = ownedUserDirectoriesConfigs.map(\n (setting) =>\n new QpqInfCoreUserDirectoryConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n userDirectoryConfig: setting,\n }),\n );\n QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);\n\n // Directories this service references but doesn't own: read-only user lookups.\n const referencedUserDirectoriesConfigs = qpqCoreUtils\n .getUserDirectories(props.qpqConfig)\n .filter((setting) => !ownedUserDirectoriesConfigs.includes(setting));\n QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(webserverRole, referencedUserDirectoriesConfigs, props.qpqConfig);\n\n // Api Keys\n const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverApiKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n apiKeyConfig: setting,\n }),\n );\n\n // Event Busses\n const eventBusses = qpqCoreUtils.getOwnedEventBusConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreEventBusConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n eventBusConfig: setting,\n }),\n );\n\n // key value store\n qpqCoreUtils.getOwnedKeyValueStores(props.qpqConfig).map(\n (setting) =>\n new QpqCoreKeyValueStoreConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n keyValueStoreConfig: setting,\n }),\n );\n QpqCoreKeyValueStoreConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end key value store\n\n // Graph Databases\n const allGraphDatabaseConfigs = qpqCoreUtils.getAllGraphDatabaseConfigs(props.qpqConfig);\n const graphDatabases = qpqCoreUtils.getOwnedGraphDatabases(props.qpqConfig).map(\n (setting) =>\n new QpqCoreApiGraphDatabaseConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n graphDatabaseConfig: setting,\n }),\n );\n QpqCoreApiGraphDatabaseConstruct.authorizeActionsForRole(webserverRole, allGraphDatabaseConfigs, props.qpqConfig);\n // end key value store\n\n // AI (Bedrock)\n QpqCoreAiConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllAiConfigs(props.qpqConfig));\n // end AI\n\n // Build websocket apis\n const websockets = qpqWebServerUtils.getOwnedWebsocketSettings(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverWebsocketConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n websocketConfig: setting,\n }),\n );\n QpqWebserverWebsocketConstruct.authorizeManageConnectionsForRole(webserverRole, websockets, props.qpqConfig);\n\n // Email senders (SES identities). The construct id is keyed by the primary root, not the\n // setting: an SES identity's physical id is the domain itself, so a changed logical id would\n // fail creation against the identity the stack already owns.\n const emailSenderConfigs = qpqWebServerUtils.getEmailSenderSettings(props.qpqConfig);\n const emailSenderConstructId = `EmailSender${qpqWebServerUtils.getPrimaryRootDomain(props.qpqConfig) ?? ''}`;\n emailSenderConfigs.map(\n (setting) =>\n new QpqWebserverEmailSenderConstruct(this, emailSenderConstructId, {\n qpqConfig: props.qpqConfig,\n\n emailSenderConfig: setting,\n }),\n );\n QpqWebserverEmailSenderConstruct.authorizeSendEmailForRole(webserverRole, emailSenderConfigs, props.qpqConfig);\n\n // Cache settings\n const cache = qpqWebServerUtils.getAllOwnedCacheConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebServerCacheConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cacheConfig: setting,\n }),\n );\n\n // Certifcates\n const certifcates = qpqWebServerUtils.getAllOwnedCertifcateConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverCertificateConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n certificateConfig: setting,\n }),\n );\n }\n}\n"]}
|
|
@@ -9,5 +9,6 @@ export declare class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock
|
|
|
9
9
|
userPool: aws_cognito.IUserPool;
|
|
10
10
|
static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct;
|
|
11
11
|
constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps);
|
|
12
|
+
static authorizeReadActionsForRole(role: aws_iam.IRole, referencedDirectoryConfigs: UserDirectoryQPQConfigSetting[], qpqConfig: QPQConfig): void;
|
|
12
13
|
static authorizeAdminActionsForRole(role: aws_iam.IRole, userDirectoryConfigs: UserDirectoryQPQConfigSetting[], userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[], qpqConfig: QPQConfig): void;
|
|
13
14
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';
|
|
2
|
-
import { AwsDataStoreRemovalPolicy, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';
|
|
2
|
+
import { AwsDataStoreRemovalPolicy, getLocalServiceAccountInfo, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';
|
|
3
3
|
import { UserDirectoryMfaMode, UserDirectoryMfaSecondFactor } from 'quidproquo-core';
|
|
4
4
|
import { aws_cognito, aws_iam, aws_route53, aws_route53_targets } from 'aws-cdk-lib';
|
|
5
5
|
import * as cdk from 'aws-cdk-lib';
|
|
@@ -168,8 +168,36 @@ export class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {
|
|
|
168
168
|
});
|
|
169
169
|
qpqDeployAwsCdkUtils.exportStackValue(this, awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig), userPoolClient.userPoolClientId);
|
|
170
170
|
}
|
|
171
|
+
// Grants READ-ONLY Cognito actions on user directories this service merely
|
|
172
|
+
// references (owned by another service): look a user up by attribute / by id
|
|
173
|
+
// (askUserDirectoryGetUsersByAttribute, askUserDirectoryGetUserAttributesByUserId).
|
|
174
|
+
// Any service that shows "who" needs this - e.g. the tenant registry adding a
|
|
175
|
+
// member by email from a service that doesn't own the pool. Nothing that
|
|
176
|
+
// mutates the pool: admin actions stay with the owner (below). Cognito has no
|
|
177
|
+
// resource policy, so a pool in another account can't be granted this way -
|
|
178
|
+
// such directories are skipped (the call fails as it does today).
|
|
179
|
+
static authorizeReadActionsForRole(role, referencedDirectoryConfigs, qpqConfig) {
|
|
180
|
+
const local = getLocalServiceAccountInfo(qpqConfig);
|
|
181
|
+
const resources = referencedDirectoryConfigs
|
|
182
|
+
.map((userDirectoryConfig) => ({
|
|
183
|
+
userDirectoryConfig,
|
|
184
|
+
account: resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner),
|
|
185
|
+
}))
|
|
186
|
+
.filter(({ account }) => account.awsAccountId === local.awsAccountId && account.awsRegion === local.awsRegion)
|
|
187
|
+
.map(({ userDirectoryConfig, account }) => {
|
|
188
|
+
const userPoolId = qpqDeployAwsCdkUtils.importStackValue(awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryConfig.name, qpqConfig));
|
|
189
|
+
return `arn:aws:cognito-idp:${account.awsRegion}:${account.awsAccountId}:userpool/${userPoolId}`;
|
|
190
|
+
});
|
|
191
|
+
if (resources.length > 0) {
|
|
192
|
+
role.addToPrincipalPolicy(new aws_iam.PolicyStatement({
|
|
193
|
+
effect: aws_iam.Effect.ALLOW,
|
|
194
|
+
actions: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],
|
|
195
|
+
resources,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
171
199
|
// Grants admin Cognito actions for pools this service owns. Services that
|
|
172
|
-
// only reference a foreign user directory get
|
|
200
|
+
// only reference a foreign user directory get only the read grant above —
|
|
173
201
|
// token validation runs against the pool's public JWKs over HTTPS and needs
|
|
174
202
|
// no IAM. Call sites must pass only owned directories (see
|
|
175
203
|
// `qpqCoreUtils.getOwnedUserDirectories`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QpqInfCoreUserDirectoryConstruct.js","sourceRoot":"","sources":["../../../../../../src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.ts"],"names":[],"mappings":"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","sourcesContent":["import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { AwsDataStoreRemovalPolicy, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';\nimport { QPQConfig, UserDirectoryMfaMode, UserDirectoryMfaSecondFactor, UserDirectoryQPQConfigSetting } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { aws_cognito, aws_iam, aws_lambda, aws_route53, aws_route53_targets } from 'aws-cdk-lib';\nimport * as cdk from 'aws-cdk-lib';\nimport { Construct } from 'constructs';\n\nimport * as qpqDeployAwsCdkUtils from '../../../../utils';\nimport { lookupHostedZone, resolveDeployPrimaryHost, resolveHostedZoneForHost } from '../../../../utils/domain';\nimport { QpqConstructBlock, QpqConstructBlockProps } from '../../../base/QpqConstructBlock';\nimport { QpqResource } from '../../../base/QpqResource';\nimport { lookupDomainCertificate } from '../../../basic/DomainCertificateLookup';\nimport { Function } from '../../../basic/Function';\n\nexport interface QpqInfCoreUserDirectoryConstructProps extends QpqConstructBlockProps {\n userDirectoryConfig: UserDirectoryQPQConfigSetting;\n}\n\nconst mapMfaMode = (mode: UserDirectoryMfaMode): aws_cognito.Mfa => {\n switch (mode) {\n case UserDirectoryMfaMode.required:\n return aws_cognito.Mfa.REQUIRED;\n case UserDirectoryMfaMode.optional:\n return aws_cognito.Mfa.OPTIONAL;\n case UserDirectoryMfaMode.off:\n default:\n return aws_cognito.Mfa.OFF;\n }\n};\n\nexport class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {\n public userPool: aws_cognito.IUserPool;\n\n static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryName, qpqConfig));\n\n class Import extends QpqConstructBlock {\n userPool = aws_cognito.UserPool.fromUserPoolId(this, 'pool-id', userPoolId);\n }\n\n return new Import(scope, id, { qpqConfig });\n }\n\n constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps) {\n super(scope, id, props);\n\n const userPoolName = this.resourceName(props.userDirectoryConfig.name);\n\n const dataStoreRemovalPolicy = qpqConfigAwsUtils.getAwsDataStoreRemovalPolicy(props.qpqConfig);\n\n const userPool = new aws_cognito.UserPool(this, 'user-pool', {\n // Retain user pools by default (user accounts are unrecoverable); dev configs opt into\n // full teardown via defineAwsDataStoreRemovalPolicy(destroy). When retained, deletionProtection\n // also blocks deletes/replacements outright (RETAIN alone only orphans the pool).\n removalPolicy: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.destroy ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN,\n deletionProtection: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.retain,\n userPoolName: userPoolName,\n selfSignUpEnabled: props.userDirectoryConfig.selfSignUpEnabled,\n mfa: mapMfaMode(props.userDirectoryConfig.mfa.mode),\n // Derived from the config's enabled factors. Ignored by Cognito when mfa is OFF.\n mfaSecondFactor: {\n otp: (props.userDirectoryConfig.mfa.secondFactors ?? []).includes(UserDirectoryMfaSecondFactor.totp),\n sms: false,\n },\n passwordPolicy: {\n minLength: 12,\n requireLowercase: true,\n requireUppercase: true,\n requireDigits: true,\n requireSymbols: true,\n },\n standardAttributes: {\n email: {\n required: true,\n mutable: true,\n },\n phoneNumber: {\n required: props.userDirectoryConfig.phoneRequired,\n mutable: true,\n },\n },\n autoVerify: {\n email: true,\n phone: props.userDirectoryConfig.phoneRequired,\n },\n // signInAliases: {\n // username: true,\n // email: true,\n // },\n });\n\n qpqDeployAwsCdkUtils.applyEnvironmentTags(userPool, props.qpqConfig);\n\n this.userPool = userPool;\n\n if (\n props.userDirectoryConfig.emailTemplates.resetPassword ||\n props.userDirectoryConfig.emailTemplates.resetPasswordAdmin ||\n props.userDirectoryConfig.emailTemplates.verifyEmail\n ) {\n const customMessageTrigger = new Function(this, 'csm-msg-trigger-func', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cm-trig'),\n functionType: 'customMessageTriggerEvent_customMessage',\n executorName: 'customMessageTriggerEvent_customMessage',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.CUSTOM_MESSAGE, customMessageTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime) {\n const defAuthChallengeTrigger = new Function(this, 'def-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-define'),\n functionType: 'customMessageTriggerEvent_defineAuthChallenge',\n executorName: 'customMessageTriggerEvent_defineAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.DEFINE_AUTH_CHALLENGE, defAuthChallengeTrigger.lambdaFunction);\n\n if (props.userDirectoryConfig.customAuthRuntime.createAuthChallenge) {\n const createAuthChallengeTrigger = new Function(this, 'create-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-create'),\n functionType: 'customMessageTriggerEvent_createAuthChallenge',\n executorName: 'customMessageTriggerEvent_createAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.CREATE_AUTH_CHALLENGE, createAuthChallengeTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime.verifyAuthChallenge) {\n const verifyAuthChallengeTrigger = new Function(this, 'verify-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-verify'),\n functionType: 'customMessageTriggerEvent_verifyAuthChallenge',\n executorName: 'customMessageTriggerEvent_verifyAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.VERIFY_AUTH_CHALLENGE_RESPONSE, verifyAuthChallengeTrigger.lambdaFunction);\n }\n }\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n this.userPool.userPoolId,\n );\n\n if (props.userDirectoryConfig.dnsRecord) {\n // A pool has one custom domain, so it lives on the primary root only. Cognito custom\n // domains use CloudFront under the hood, so the cert must be in us-east-1.\n const fullDomain = resolveDeployPrimaryHost(props.qpqConfig, { subdomain: props.userDirectoryConfig.dnsRecord.subdomain });\n const hostedZone = lookupHostedZone(this, resolveHostedZoneForHost(props.qpqConfig, fullDomain));\n const certificate = lookupDomainCertificate(this, 'us-east-1', props.qpqConfig, props.userDirectoryConfig.name);\n\n const userPoolDomain = new aws_cognito.UserPoolDomain(this, 'user-pool-domain', {\n userPool: this.userPool,\n\n // Full custom domain\n customDomain: {\n certificate,\n domainName: fullDomain,\n },\n });\n\n new aws_route53.ARecord(this, 'CognitoDomainAliasRecord', {\n zone: hostedZone,\n recordName: fullDomain,\n target: aws_route53.RecordTarget.fromAlias(new aws_route53_targets.UserPoolDomainTarget(userPoolDomain)),\n });\n }\n\n // Short-lived JWTs shrink the window in which a revoked session's still-valid access\n // token keeps working (access tokens are stateless, so RevokeToken/GlobalSignOut can't\n // kill them before they expire). Omitted → Cognito's default (60 min). Applied to both\n // the access and ID tokens so the ID token can't outlive the access token.\n const accessTokenValidityMinutes = props.userDirectoryConfig.accessTokenValidityMinutes;\n const tokenValidity = accessTokenValidityMinutes !== undefined ? cdk.Duration.minutes(accessTokenValidityMinutes) : undefined;\n\n const userPoolClient = new aws_cognito.UserPoolClient(this, 'user-pool-client', {\n userPoolClientName: this.qpqResourceName(props.userDirectoryConfig.name, 'upc'),\n userPool: this.userPool,\n generateSecret: true,\n authFlows: {\n adminUserPassword: true,\n custom: !!props.userDirectoryConfig.customAuthRuntime,\n },\n accessTokenValidity: tokenValidity,\n idTokenValidity: tokenValidity,\n });\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n userPoolClient.userPoolClientId,\n );\n }\n\n // Grants admin Cognito actions for pools this service owns. Services that\n // only reference a foreign user directory get no Cognito IAM from here —\n // token validation runs against the pool's public JWKs over HTTPS and needs\n // no IAM. Call sites must pass only owned directories (see\n // `qpqCoreUtils.getOwnedUserDirectories`).\n public static authorizeAdminActionsForRole(\n role: aws_iam.IRole,\n userDirectoryConfigs: UserDirectoryQPQConfigSetting[],\n userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[],\n qpqConfig: QPQConfig,\n ) {\n if (userDirectoryConstructs.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: [\n 'cognito-idp:SignUp',\n 'cognito-idp:AdminCreateUser',\n 'cognito-idp:AdminInitiateAuth',\n 'cognito-idp:AdminRespondToAuthChallenge',\n 'cognito-idp:AdminAddUserToGroup',\n 'cognito-idp:AdminDeleteUser',\n 'cognito-idp:AdminUpdateUserAttributes',\n 'cognito-idp:AdminDeleteUserAttributes',\n 'cognito-idp:AdminSetUserPassword',\n\n 'cognito-idp:ListUsers',\n 'cognito-idp:GetUser',\n 'cognito-idp:AdminGetUser',\n 'cognito-idp:ListGroups',\n 'cognito-idp:GetGroup',\n 'cognito-idp:ListUserPools',\n 'cognito-idp:DescribeUserPool',\n 'cognito-idp:DescribeUserPoolClient',\n ],\n resources: userDirectoryConfigs.map((userDirectoryConfig, index) => {\n const { awsRegion, awsAccountId } = resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner);\n\n const userpoolId = userDirectoryConstructs[index].userPool.userPoolId;\n\n return `arn:aws:cognito-idp:${awsRegion}:${awsAccountId}:userpool/${userpoolId}`;\n }),\n }),\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"QpqInfCoreUserDirectoryConstruct.js","sourceRoot":"","sources":["../../../../../../src/constructs/feature/core/auth/QpqInfCoreUserDirectoryConstruct.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAC/I,OAAO,EAAa,oBAAoB,EAAE,4BAA4B,EAAiC,MAAM,iBAAiB,CAAC;AAG/H,OAAO,EAAE,WAAW,EAAE,OAAO,EAAc,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjG,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAGnC,OAAO,KAAK,oBAAoB,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAChH,OAAO,EAAE,iBAAiB,EAA0B,MAAM,iCAAiC,CAAC;AAE5F,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAMnD,MAAM,UAAU,GAAG,CAAC,IAA0B,EAAmB,EAAE;IACjE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,oBAAoB,CAAC,QAAQ;YAChC,OAAO,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClC,KAAK,oBAAoB,CAAC,QAAQ;YAChC,OAAO,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClC,KAAK,oBAAoB,CAAC,GAAG,CAAC;QAC9B;YACE,OAAO,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,gCAAiC,SAAQ,iBAAiB;IAC9D,QAAQ,CAAwB;IAEvC,MAAM,CAAC,cAAc,CAAC,KAAgB,EAAE,EAAU,EAAE,SAAoB,EAAE,iBAAyB;QACjG,MAAM,UAAU,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,cAAc,CAAC,mCAAmC,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3I,MAAM,MAAO,SAAQ,iBAAiB;YACpC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;SAC7E;QAED,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,YAAY,KAAgB,EAAE,EAAU,EAAE,KAA4C;QACpF,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAEvE,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,4BAA4B,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE/F,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE;YAC3D,uFAAuF;YACvF,gGAAgG;YAChG,kFAAkF;YAClF,aAAa,EAAE,sBAAsB,KAAK,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM;YAClI,kBAAkB,EAAE,sBAAsB,KAAK,yBAAyB,CAAC,MAAM;YAC/E,YAAY,EAAE,YAAY;YAC1B,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,iBAAiB;YAC9D,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;YACnD,iFAAiF;YACjF,eAAe,EAAE;gBACf,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC,IAAI,CAAC;gBACpG,GAAG,EAAE,KAAK;aACX;YACD,cAAc,EAAE;gBACd,SAAS,EAAE,EAAE;gBACb,gBAAgB,EAAE,IAAI;gBACtB,gBAAgB,EAAE,IAAI;gBACtB,aAAa,EAAE,IAAI;gBACnB,cAAc,EAAE,IAAI;aACrB;YACD,kBAAkB,EAAE;gBAClB,KAAK,EAAE;oBACL,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,IAAI;iBACd;gBACD,WAAW,EAAE;oBACX,QAAQ,EAAE,KAAK,CAAC,mBAAmB,CAAC,aAAa;oBACjD,OAAO,EAAE,IAAI;iBACd;aACF;YACD,UAAU,EAAE;gBACV,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,KAAK,CAAC,mBAAmB,CAAC,aAAa;aAC/C;YACD,mBAAmB;YACnB,oBAAoB;YACpB,iBAAiB;YACjB,KAAK;SACN,CAAC,CAAC;QAEH,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAErE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IACE,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,aAAa;YACtD,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,kBAAkB;YAC3D,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,WAAW,EACpD,CAAC;YACD,MAAM,oBAAoB,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,sBAAsB,EAAE;gBACtE,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;gBAClF,YAAY,EAAE,yCAAyC;gBACvD,YAAY,EAAE,yCAAyC;gBAEvD,SAAS,EAAE,KAAK,CAAC,SAAS;gBAE1B,WAAW,EAAE;oBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;iBAClD;gBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;aAC5B,CAAC,CAAC;YAEH,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,cAAc,EAAE,oBAAoB,CAAC,cAAc,CAAC,CAAC;QACzG,CAAC;QAED,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,CAAC;YAChD,MAAM,uBAAuB,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,oBAAoB,EAAE;gBACvE,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;gBACrF,YAAY,EAAE,+CAA+C;gBAC7D,YAAY,EAAE,+CAA+C;gBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;gBAE1B,WAAW,EAAE;oBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;iBAClD;gBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;aAC5B,CAAC,CAAC;YAEH,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC;YAEjH,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mBAAmB,EAAE,CAAC;gBACpE,MAAM,0BAA0B,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,EAAE;oBAC7E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;oBACrF,YAAY,EAAE,+CAA+C;oBAC7D,YAAY,EAAE,+CAA+C;oBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;oBAE1B,WAAW,EAAE;wBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;qBAClD;oBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;iBAC5B,CAAC,CAAC;gBACH,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,cAAc,CAAC,CAAC;YACtH,CAAC;YAED,IAAI,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mBAAmB,EAAE,CAAC;gBACpE,MAAM,0BAA0B,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,EAAE;oBAC7E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC;oBACrF,YAAY,EAAE,+CAA+C;oBAC7D,YAAY,EAAE,+CAA+C;oBAE7D,SAAS,EAAE,KAAK,CAAC,SAAS;oBAE1B,WAAW,EAAE;wBACX,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI;qBAClD;oBAED,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;iBAC5B,CAAC,CAAC;gBACH,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,8BAA8B,EAAE,0BAA0B,CAAC,cAAc,CAAC,CAAC;YAC/H,CAAC;QACH,CAAC;QAED,oBAAoB,CAAC,gBAAgB,CACnC,IAAI,EACJ,cAAc,CAAC,mCAAmC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EACnG,IAAI,CAAC,QAAQ,CAAC,UAAU,CACzB,CAAC;QAEF,IAAI,KAAK,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC;YACxC,qFAAqF;YACrF,2EAA2E;YAC3E,MAAM,UAAU,GAAG,wBAAwB,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;YAC3H,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,EAAE,wBAAwB,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;YACjG,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhH,MAAM,cAAc,GAAG,IAAI,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE;gBAC9E,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBAEvB,qBAAqB;gBACrB,YAAY,EAAE;oBACZ,WAAW;oBACX,UAAU,EAAE,UAAU;iBACvB;aACF,CAAC,CAAC;YAEH,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,0BAA0B,EAAE;gBACxD,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,mBAAmB,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;aACzG,CAAC,CAAC;QACL,CAAC;QAED,qFAAqF;QACrF,uFAAuF;QACvF,uFAAuF;QACvF,2EAA2E;QAC3E,MAAM,0BAA0B,GAAG,KAAK,CAAC,mBAAmB,CAAC,0BAA0B,CAAC;QACxF,MAAM,aAAa,GAAG,0BAA0B,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9H,MAAM,cAAc,GAAG,IAAI,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE;YAC9E,kBAAkB,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC;YAC/E,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE;gBACT,iBAAiB,EAAE,IAAI;gBACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,iBAAiB;aACtD;YACD,mBAAmB,EAAE,aAAa;YAClC,eAAe,EAAE,aAAa;SAC/B,CAAC,CAAC;QAEH,oBAAoB,CAAC,gBAAgB,CACnC,IAAI,EACJ,cAAc,CAAC,yCAAyC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EACzG,cAAc,CAAC,gBAAgB,CAChC,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,oFAAoF;IACpF,8EAA8E;IAC9E,yEAAyE;IACzE,8EAA8E;IAC9E,4EAA4E;IAC5E,kEAAkE;IAC3D,MAAM,CAAC,2BAA2B,CAAC,IAAmB,EAAE,0BAA2D,EAAE,SAAoB;QAC9I,MAAM,KAAK,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;QAEpD,MAAM,SAAS,GAAG,0BAA0B;aACzC,GAAG,CAAC,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;YAC7B,mBAAmB;YACnB,OAAO,EAAE,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC;SAC5E,CAAC,CAAC;aACF,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,KAAK,KAAK,CAAC,YAAY,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC;aAC7G,GAAG,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE;YACxC,MAAM,UAAU,GAAG,oBAAoB,CAAC,gBAAgB,CACtD,cAAc,CAAC,mCAAmC,CAAC,mBAAmB,CAAC,IAAI,EAAE,SAAS,CAAC,CACxF,CAAC;YAEF,OAAO,uBAAuB,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,YAAY,aAAa,UAAU,EAAE,CAAC;QACnG,CAAC,CAAC,CAAC;QAEL,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,oBAAoB,CACvB,IAAI,OAAO,CAAC,eAAe,CAAC;gBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;gBAC5B,OAAO,EAAE,CAAC,uBAAuB,EAAE,0BAA0B,CAAC;gBAC9D,SAAS;aACV,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,2DAA2D;IAC3D,2CAA2C;IACpC,MAAM,CAAC,4BAA4B,CACxC,IAAmB,EACnB,oBAAqD,EACrD,uBAA2D,EAC3D,SAAoB;QAEpB,IAAI,uBAAuB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,oBAAoB,CACvB,IAAI,OAAO,CAAC,eAAe,CAAC;gBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;gBAC5B,OAAO,EAAE;oBACP,oBAAoB;oBACpB,6BAA6B;oBAC7B,+BAA+B;oBAC/B,yCAAyC;oBACzC,iCAAiC;oBACjC,6BAA6B;oBAC7B,uCAAuC;oBACvC,uCAAuC;oBACvC,kCAAkC;oBAElC,uBAAuB;oBACvB,qBAAqB;oBACrB,0BAA0B;oBAC1B,wBAAwB;oBACxB,sBAAsB;oBACtB,2BAA2B;oBAC3B,8BAA8B;oBAC9B,oCAAoC;iBACrC;gBACD,SAAS,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE;oBACjE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;oBAEvG,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAEtE,OAAO,uBAAuB,SAAS,IAAI,YAAY,aAAa,UAAU,EAAE,CAAC;gBACnF,CAAC,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF","sourcesContent":["import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { AwsDataStoreRemovalPolicy, getLocalServiceAccountInfo, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';\nimport { QPQConfig, UserDirectoryMfaMode, UserDirectoryMfaSecondFactor, UserDirectoryQPQConfigSetting } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { aws_cognito, aws_iam, aws_lambda, aws_route53, aws_route53_targets } from 'aws-cdk-lib';\nimport * as cdk from 'aws-cdk-lib';\nimport { Construct } from 'constructs';\n\nimport * as qpqDeployAwsCdkUtils from '../../../../utils';\nimport { lookupHostedZone, resolveDeployPrimaryHost, resolveHostedZoneForHost } from '../../../../utils/domain';\nimport { QpqConstructBlock, QpqConstructBlockProps } from '../../../base/QpqConstructBlock';\nimport { QpqResource } from '../../../base/QpqResource';\nimport { lookupDomainCertificate } from '../../../basic/DomainCertificateLookup';\nimport { Function } from '../../../basic/Function';\n\nexport interface QpqInfCoreUserDirectoryConstructProps extends QpqConstructBlockProps {\n userDirectoryConfig: UserDirectoryQPQConfigSetting;\n}\n\nconst mapMfaMode = (mode: UserDirectoryMfaMode): aws_cognito.Mfa => {\n switch (mode) {\n case UserDirectoryMfaMode.required:\n return aws_cognito.Mfa.REQUIRED;\n case UserDirectoryMfaMode.optional:\n return aws_cognito.Mfa.OPTIONAL;\n case UserDirectoryMfaMode.off:\n default:\n return aws_cognito.Mfa.OFF;\n }\n};\n\nexport class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {\n public userPool: aws_cognito.IUserPool;\n\n static fromOtherStack(scope: Construct, id: string, qpqConfig: QPQConfig, userDirectoryName: string): QpqInfCoreUserDirectoryConstruct {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryName, qpqConfig));\n\n class Import extends QpqConstructBlock {\n userPool = aws_cognito.UserPool.fromUserPoolId(this, 'pool-id', userPoolId);\n }\n\n return new Import(scope, id, { qpqConfig });\n }\n\n constructor(scope: Construct, id: string, props: QpqInfCoreUserDirectoryConstructProps) {\n super(scope, id, props);\n\n const userPoolName = this.resourceName(props.userDirectoryConfig.name);\n\n const dataStoreRemovalPolicy = qpqConfigAwsUtils.getAwsDataStoreRemovalPolicy(props.qpqConfig);\n\n const userPool = new aws_cognito.UserPool(this, 'user-pool', {\n // Retain user pools by default (user accounts are unrecoverable); dev configs opt into\n // full teardown via defineAwsDataStoreRemovalPolicy(destroy). When retained, deletionProtection\n // also blocks deletes/replacements outright (RETAIN alone only orphans the pool).\n removalPolicy: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.destroy ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN,\n deletionProtection: dataStoreRemovalPolicy === AwsDataStoreRemovalPolicy.retain,\n userPoolName: userPoolName,\n selfSignUpEnabled: props.userDirectoryConfig.selfSignUpEnabled,\n mfa: mapMfaMode(props.userDirectoryConfig.mfa.mode),\n // Derived from the config's enabled factors. Ignored by Cognito when mfa is OFF.\n mfaSecondFactor: {\n otp: (props.userDirectoryConfig.mfa.secondFactors ?? []).includes(UserDirectoryMfaSecondFactor.totp),\n sms: false,\n },\n passwordPolicy: {\n minLength: 12,\n requireLowercase: true,\n requireUppercase: true,\n requireDigits: true,\n requireSymbols: true,\n },\n standardAttributes: {\n email: {\n required: true,\n mutable: true,\n },\n phoneNumber: {\n required: props.userDirectoryConfig.phoneRequired,\n mutable: true,\n },\n },\n autoVerify: {\n email: true,\n phone: props.userDirectoryConfig.phoneRequired,\n },\n // signInAliases: {\n // username: true,\n // email: true,\n // },\n });\n\n qpqDeployAwsCdkUtils.applyEnvironmentTags(userPool, props.qpqConfig);\n\n this.userPool = userPool;\n\n if (\n props.userDirectoryConfig.emailTemplates.resetPassword ||\n props.userDirectoryConfig.emailTemplates.resetPasswordAdmin ||\n props.userDirectoryConfig.emailTemplates.verifyEmail\n ) {\n const customMessageTrigger = new Function(this, 'csm-msg-trigger-func', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cm-trig'),\n functionType: 'customMessageTriggerEvent_customMessage',\n executorName: 'customMessageTriggerEvent_customMessage',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.CUSTOM_MESSAGE, customMessageTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime) {\n const defAuthChallengeTrigger = new Function(this, 'def-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-define'),\n functionType: 'customMessageTriggerEvent_defineAuthChallenge',\n executorName: 'customMessageTriggerEvent_defineAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n\n userPool.addTrigger(aws_cognito.UserPoolOperation.DEFINE_AUTH_CHALLENGE, defAuthChallengeTrigger.lambdaFunction);\n\n if (props.userDirectoryConfig.customAuthRuntime.createAuthChallenge) {\n const createAuthChallengeTrigger = new Function(this, 'create-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-create'),\n functionType: 'customMessageTriggerEvent_createAuthChallenge',\n executorName: 'customMessageTriggerEvent_createAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.CREATE_AUTH_CHALLENGE, createAuthChallengeTrigger.lambdaFunction);\n }\n\n if (props.userDirectoryConfig.customAuthRuntime.verifyAuthChallenge) {\n const verifyAuthChallengeTrigger = new Function(this, 'verify-auth-challenge', {\n functionName: this.qpqResourceName(`${props.userDirectoryConfig.name}`, 'cac-verify'),\n functionType: 'customMessageTriggerEvent_verifyAuthChallenge',\n executorName: 'customMessageTriggerEvent_verifyAuthChallenge',\n\n qpqConfig: props.qpqConfig,\n\n environment: {\n userDirectoryName: props.userDirectoryConfig.name,\n },\n\n role: this.getServiceRole(),\n });\n userPool.addTrigger(aws_cognito.UserPoolOperation.VERIFY_AUTH_CHALLENGE_RESPONSE, verifyAuthChallengeTrigger.lambdaFunction);\n }\n }\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n this.userPool.userPoolId,\n );\n\n if (props.userDirectoryConfig.dnsRecord) {\n // A pool has one custom domain, so it lives on the primary root only. Cognito custom\n // domains use CloudFront under the hood, so the cert must be in us-east-1.\n const fullDomain = resolveDeployPrimaryHost(props.qpqConfig, { subdomain: props.userDirectoryConfig.dnsRecord.subdomain });\n const hostedZone = lookupHostedZone(this, resolveHostedZoneForHost(props.qpqConfig, fullDomain));\n const certificate = lookupDomainCertificate(this, 'us-east-1', props.qpqConfig, props.userDirectoryConfig.name);\n\n const userPoolDomain = new aws_cognito.UserPoolDomain(this, 'user-pool-domain', {\n userPool: this.userPool,\n\n // Full custom domain\n customDomain: {\n certificate,\n domainName: fullDomain,\n },\n });\n\n new aws_route53.ARecord(this, 'CognitoDomainAliasRecord', {\n zone: hostedZone,\n recordName: fullDomain,\n target: aws_route53.RecordTarget.fromAlias(new aws_route53_targets.UserPoolDomainTarget(userPoolDomain)),\n });\n }\n\n // Short-lived JWTs shrink the window in which a revoked session's still-valid access\n // token keeps working (access tokens are stateless, so RevokeToken/GlobalSignOut can't\n // kill them before they expire). Omitted → Cognito's default (60 min). Applied to both\n // the access and ID tokens so the ID token can't outlive the access token.\n const accessTokenValidityMinutes = props.userDirectoryConfig.accessTokenValidityMinutes;\n const tokenValidity = accessTokenValidityMinutes !== undefined ? cdk.Duration.minutes(accessTokenValidityMinutes) : undefined;\n\n const userPoolClient = new aws_cognito.UserPoolClient(this, 'user-pool-client', {\n userPoolClientName: this.qpqResourceName(props.userDirectoryConfig.name, 'upc'),\n userPool: this.userPool,\n generateSecret: true,\n authFlows: {\n adminUserPassword: true,\n custom: !!props.userDirectoryConfig.customAuthRuntime,\n },\n accessTokenValidity: tokenValidity,\n idTokenValidity: tokenValidity,\n });\n\n qpqDeployAwsCdkUtils.exportStackValue(\n this,\n awsNamingUtils.getCFExportNameUserPoolClientIdFromConfig(props.userDirectoryConfig.name, props.qpqConfig),\n userPoolClient.userPoolClientId,\n );\n }\n\n // Grants READ-ONLY Cognito actions on user directories this service merely\n // references (owned by another service): look a user up by attribute / by id\n // (askUserDirectoryGetUsersByAttribute, askUserDirectoryGetUserAttributesByUserId).\n // Any service that shows \"who\" needs this - e.g. the tenant registry adding a\n // member by email from a service that doesn't own the pool. Nothing that\n // mutates the pool: admin actions stay with the owner (below). Cognito has no\n // resource policy, so a pool in another account can't be granted this way -\n // such directories are skipped (the call fails as it does today).\n public static authorizeReadActionsForRole(role: aws_iam.IRole, referencedDirectoryConfigs: UserDirectoryQPQConfigSetting[], qpqConfig: QPQConfig) {\n const local = getLocalServiceAccountInfo(qpqConfig);\n\n const resources = referencedDirectoryConfigs\n .map((userDirectoryConfig) => ({\n userDirectoryConfig,\n account: resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner),\n }))\n .filter(({ account }) => account.awsAccountId === local.awsAccountId && account.awsRegion === local.awsRegion)\n .map(({ userDirectoryConfig, account }) => {\n const userPoolId = qpqDeployAwsCdkUtils.importStackValue(\n awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryConfig.name, qpqConfig),\n );\n\n return `arn:aws:cognito-idp:${account.awsRegion}:${account.awsAccountId}:userpool/${userPoolId}`;\n });\n\n if (resources.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],\n resources,\n }),\n );\n }\n }\n\n // Grants admin Cognito actions for pools this service owns. Services that\n // only reference a foreign user directory get only the read grant above —\n // token validation runs against the pool's public JWKs over HTTPS and needs\n // no IAM. Call sites must pass only owned directories (see\n // `qpqCoreUtils.getOwnedUserDirectories`).\n public static authorizeAdminActionsForRole(\n role: aws_iam.IRole,\n userDirectoryConfigs: UserDirectoryQPQConfigSetting[],\n userDirectoryConstructs: QpqInfCoreUserDirectoryConstruct[],\n qpqConfig: QPQConfig,\n ) {\n if (userDirectoryConstructs.length > 0) {\n role.addToPrincipalPolicy(\n new aws_iam.PolicyStatement({\n effect: aws_iam.Effect.ALLOW,\n actions: [\n 'cognito-idp:SignUp',\n 'cognito-idp:AdminCreateUser',\n 'cognito-idp:AdminInitiateAuth',\n 'cognito-idp:AdminRespondToAuthChallenge',\n 'cognito-idp:AdminAddUserToGroup',\n 'cognito-idp:AdminDeleteUser',\n 'cognito-idp:AdminUpdateUserAttributes',\n 'cognito-idp:AdminDeleteUserAttributes',\n 'cognito-idp:AdminSetUserPassword',\n\n 'cognito-idp:ListUsers',\n 'cognito-idp:GetUser',\n 'cognito-idp:AdminGetUser',\n 'cognito-idp:ListGroups',\n 'cognito-idp:GetGroup',\n 'cognito-idp:ListUserPools',\n 'cognito-idp:DescribeUserPool',\n 'cognito-idp:DescribeUserPoolClient',\n ],\n resources: userDirectoryConfigs.map((userDirectoryConfig, index) => {\n const { awsRegion, awsAccountId } = resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner);\n\n const userpoolId = userDirectoryConstructs[index].userPool.userPoolId;\n\n return `arn:aws:cognito-idp:${awsRegion}:${awsAccountId}:userpool/${userpoolId}`;\n }),\n }),\n );\n }\n }\n}\n"]}
|
|
@@ -56,6 +56,11 @@ export class InfQpqServiceStack extends QpqServiceStack {
|
|
|
56
56
|
userDirectoryConfig: setting,
|
|
57
57
|
}));
|
|
58
58
|
QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);
|
|
59
|
+
// Directories this service references but doesn't own: read-only user lookups.
|
|
60
|
+
const referencedUserDirectoriesConfigs = qpqCoreUtils
|
|
61
|
+
.getUserDirectories(props.qpqConfig)
|
|
62
|
+
.filter((setting) => !ownedUserDirectoriesConfigs.includes(setting));
|
|
63
|
+
QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(webserverRole, referencedUserDirectoriesConfigs, props.qpqConfig);
|
|
59
64
|
// Api Keys
|
|
60
65
|
const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map((setting) => new QpqWebserverApiKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {
|
|
61
66
|
qpqConfig: props.qpqConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfQpqServiceStack.js","sourceRoot":"","sources":["../../../src/stacks/InfQpqServiceStack.ts"],"names":[],"mappings":"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","sourcesContent":["import { qpqCoreUtils } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { Construct } from 'constructs';\n\nimport { requireDomainResolver } from '../appWorkspace/requireDomainResolver';\nimport {\n QpqCoreAiConstruct,\n QpqCoreApiGraphDatabaseConstruct,\n QpqCoreCryptoKeyConstruct,\n QpqCoreEventBusConstruct,\n QpqCoreKeyValueStoreConstruct,\n QpqCoreParameterConstruct,\n QpqCoreQueueConstruct,\n QpqCoreSecretConstruct,\n QpqCoreStorageDriveConstruct,\n QpqInfCoreUserDirectoryConstruct,\n QpqWebserverApiKeyConstruct,\n QpqWebserverCertificateConstruct,\n QpqWebserverEmailSenderConstruct,\n QpqWebserverWebsocketConstruct,\n} from '../constructs';\nimport { WebserverRoll } from '../constructs/basic/WebserverRoll';\nimport { QpqWebServerCacheConstruct } from '../constructs/feature/webserver/cache/QpqWebServerCacheConstruct';\nimport { QpqServiceStack, QpqServiceStackProps } from './base/QpqServiceStack';\n\nexport interface InfQpqServiceStackProps extends QpqServiceStackProps {}\n\nexport class InfQpqServiceStack extends QpqServiceStack {\n constructor(scope: Construct, id: string, props: InfQpqServiceStackProps) {\n super(scope, id, props);\n\n // Build the role for this service.\n const webserverRole = new WebserverRoll(this, 'webserverRoll', {\n qpqConfig: props.qpqConfig,\n }).role;\n\n // Build the storage drives\n qpqCoreUtils.getOwnedStorageDrives(props.qpqConfig).map(\n (setting) =>\n new QpqCoreStorageDriveConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n storageDriveConfig: setting,\n\n corsAllowedOrigins: qpqWebServerUtils.getStorageDriveCorsAllowedOrigins(\n props.qpqConfig,\n setting.storageDrive,\n requireDomainResolver(props.qpqConfig),\n ),\n allowCloudFrontRead: qpqWebServerUtils.isStorageDriveWebEntryOrigin(props.qpqConfig, setting.storageDrive),\n }),\n );\n QpqCoreStorageDriveConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end storage drives\n\n // Build the parameters\n const parameters = qpqCoreUtils.getOwnedParameterConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreParameterConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n parameterConfig: setting,\n }),\n );\n QpqCoreParameterConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllParameterConfigs(props.qpqConfig), props.qpqConfig);\n // end parameters\n\n // Secrets\n const secrets = qpqCoreUtils.getOwnedSecrets(props.qpqConfig).map(\n (setting) =>\n new QpqCoreSecretConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n secretConfig: setting,\n }),\n );\n QpqCoreSecretConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllSecretConfigs(props.qpqConfig), props.qpqConfig);\n // end secrets\n\n // Crypto keys\n const cryptoKeys = qpqCoreUtils.getOwnedCryptoKeys(props.qpqConfig).map(\n (setting) =>\n new QpqCoreCryptoKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cryptoKeyConfig: setting,\n }),\n );\n QpqCoreCryptoKeyConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllCryptoKeyConfigs(props.qpqConfig), props.qpqConfig);\n // end crypto keys\n\n // Queues\n const queues = qpqCoreUtils.getQueues(props.qpqConfig).map(\n (setting) =>\n new QpqCoreQueueConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n queueConfig: setting,\n }),\n );\n QpqCoreQueueConstruct.authorizeActionsForRole(webserverRole, queues);\n // end queues\n\n // User Directories\n const ownedUserDirectoriesConfigs = qpqCoreUtils.getOwnedUserDirectories(props.qpqConfig);\n const userDirectories = ownedUserDirectoriesConfigs.map(\n (setting) =>\n new QpqInfCoreUserDirectoryConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n userDirectoryConfig: setting,\n }),\n );\n QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);\n\n // Api Keys\n const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverApiKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n apiKeyConfig: setting,\n }),\n );\n\n // Event Busses\n const eventBusses = qpqCoreUtils.getOwnedEventBusConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreEventBusConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n eventBusConfig: setting,\n }),\n );\n\n // key value store\n qpqCoreUtils.getOwnedKeyValueStores(props.qpqConfig).map(\n (setting) =>\n new QpqCoreKeyValueStoreConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n keyValueStoreConfig: setting,\n }),\n );\n QpqCoreKeyValueStoreConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end key value store\n\n // Graph Databases\n const allGraphDatabaseConfigs = qpqCoreUtils.getAllGraphDatabaseConfigs(props.qpqConfig);\n const graphDatabases = qpqCoreUtils.getOwnedGraphDatabases(props.qpqConfig).map(\n (setting) =>\n new QpqCoreApiGraphDatabaseConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n graphDatabaseConfig: setting,\n }),\n );\n QpqCoreApiGraphDatabaseConstruct.authorizeActionsForRole(webserverRole, allGraphDatabaseConfigs, props.qpqConfig);\n // end key value store\n\n // AI (Bedrock)\n QpqCoreAiConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllAiConfigs(props.qpqConfig));\n // end AI\n\n // Build websocket apis\n const websockets = qpqWebServerUtils.getOwnedWebsocketSettings(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverWebsocketConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n websocketConfig: setting,\n }),\n );\n QpqWebserverWebsocketConstruct.authorizeManageConnectionsForRole(webserverRole, websockets, props.qpqConfig);\n\n // Email senders (SES identities). The construct id is keyed by the primary root, not the\n // setting: an SES identity's physical id is the domain itself, so a changed logical id would\n // fail creation against the identity the stack already owns.\n const emailSenderConfigs = qpqWebServerUtils.getEmailSenderSettings(props.qpqConfig);\n const emailSenderConstructId = `EmailSender${qpqWebServerUtils.getPrimaryRootDomain(props.qpqConfig) ?? ''}`;\n emailSenderConfigs.map(\n (setting) =>\n new QpqWebserverEmailSenderConstruct(this, emailSenderConstructId, {\n qpqConfig: props.qpqConfig,\n\n emailSenderConfig: setting,\n }),\n );\n QpqWebserverEmailSenderConstruct.authorizeSendEmailForRole(webserverRole, emailSenderConfigs, props.qpqConfig);\n\n // Cache settings\n const cache = qpqWebServerUtils.getAllOwnedCacheConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebServerCacheConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cacheConfig: setting,\n }),\n );\n\n // Certifcates\n const certifcates = qpqWebServerUtils.getAllOwnedCertifcateConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverCertificateConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n certificateConfig: setting,\n }),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InfQpqServiceStack.js","sourceRoot":"","sources":["../../../src/stacks/InfQpqServiceStack.ts"],"names":[],"mappings":"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","sourcesContent":["import { qpqCoreUtils } from 'quidproquo-core';\nimport { qpqWebServerUtils } from 'quidproquo-webserver';\n\nimport { Construct } from 'constructs';\n\nimport { requireDomainResolver } from '../appWorkspace/requireDomainResolver';\nimport {\n QpqCoreAiConstruct,\n QpqCoreApiGraphDatabaseConstruct,\n QpqCoreCryptoKeyConstruct,\n QpqCoreEventBusConstruct,\n QpqCoreKeyValueStoreConstruct,\n QpqCoreParameterConstruct,\n QpqCoreQueueConstruct,\n QpqCoreSecretConstruct,\n QpqCoreStorageDriveConstruct,\n QpqInfCoreUserDirectoryConstruct,\n QpqWebserverApiKeyConstruct,\n QpqWebserverCertificateConstruct,\n QpqWebserverEmailSenderConstruct,\n QpqWebserverWebsocketConstruct,\n} from '../constructs';\nimport { WebserverRoll } from '../constructs/basic/WebserverRoll';\nimport { QpqWebServerCacheConstruct } from '../constructs/feature/webserver/cache/QpqWebServerCacheConstruct';\nimport { QpqServiceStack, QpqServiceStackProps } from './base/QpqServiceStack';\n\nexport interface InfQpqServiceStackProps extends QpqServiceStackProps {}\n\nexport class InfQpqServiceStack extends QpqServiceStack {\n constructor(scope: Construct, id: string, props: InfQpqServiceStackProps) {\n super(scope, id, props);\n\n // Build the role for this service.\n const webserverRole = new WebserverRoll(this, 'webserverRoll', {\n qpqConfig: props.qpqConfig,\n }).role;\n\n // Build the storage drives\n qpqCoreUtils.getOwnedStorageDrives(props.qpqConfig).map(\n (setting) =>\n new QpqCoreStorageDriveConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n storageDriveConfig: setting,\n\n corsAllowedOrigins: qpqWebServerUtils.getStorageDriveCorsAllowedOrigins(\n props.qpqConfig,\n setting.storageDrive,\n requireDomainResolver(props.qpqConfig),\n ),\n allowCloudFrontRead: qpqWebServerUtils.isStorageDriveWebEntryOrigin(props.qpqConfig, setting.storageDrive),\n }),\n );\n QpqCoreStorageDriveConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end storage drives\n\n // Build the parameters\n const parameters = qpqCoreUtils.getOwnedParameterConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreParameterConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n parameterConfig: setting,\n }),\n );\n QpqCoreParameterConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllParameterConfigs(props.qpqConfig), props.qpqConfig);\n // end parameters\n\n // Secrets\n const secrets = qpqCoreUtils.getOwnedSecrets(props.qpqConfig).map(\n (setting) =>\n new QpqCoreSecretConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n secretConfig: setting,\n }),\n );\n QpqCoreSecretConstruct.authorizeActionsForRole(this, webserverRole, qpqCoreUtils.getAllSecretConfigs(props.qpqConfig), props.qpqConfig);\n // end secrets\n\n // Crypto keys\n const cryptoKeys = qpqCoreUtils.getOwnedCryptoKeys(props.qpqConfig).map(\n (setting) =>\n new QpqCoreCryptoKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cryptoKeyConfig: setting,\n }),\n );\n QpqCoreCryptoKeyConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllCryptoKeyConfigs(props.qpqConfig), props.qpqConfig);\n // end crypto keys\n\n // Queues\n const queues = qpqCoreUtils.getQueues(props.qpqConfig).map(\n (setting) =>\n new QpqCoreQueueConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n queueConfig: setting,\n }),\n );\n QpqCoreQueueConstruct.authorizeActionsForRole(webserverRole, queues);\n // end queues\n\n // User Directories\n const ownedUserDirectoriesConfigs = qpqCoreUtils.getOwnedUserDirectories(props.qpqConfig);\n const userDirectories = ownedUserDirectoriesConfigs.map(\n (setting) =>\n new QpqInfCoreUserDirectoryConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n userDirectoryConfig: setting,\n }),\n );\n QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);\n\n // Directories this service references but doesn't own: read-only user lookups.\n const referencedUserDirectoriesConfigs = qpqCoreUtils\n .getUserDirectories(props.qpqConfig)\n .filter((setting) => !ownedUserDirectoriesConfigs.includes(setting));\n QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(webserverRole, referencedUserDirectoriesConfigs, props.qpqConfig);\n\n // Api Keys\n const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverApiKeyConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n apiKeyConfig: setting,\n }),\n );\n\n // Event Busses\n const eventBusses = qpqCoreUtils.getOwnedEventBusConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqCoreEventBusConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n eventBusConfig: setting,\n }),\n );\n\n // key value store\n qpqCoreUtils.getOwnedKeyValueStores(props.qpqConfig).map(\n (setting) =>\n new QpqCoreKeyValueStoreConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n keyValueStoreConfig: setting,\n }),\n );\n QpqCoreKeyValueStoreConstruct.authorizeActionsForRole(this, webserverRole, props.qpqConfig);\n // end key value store\n\n // Graph Databases\n const allGraphDatabaseConfigs = qpqCoreUtils.getAllGraphDatabaseConfigs(props.qpqConfig);\n const graphDatabases = qpqCoreUtils.getOwnedGraphDatabases(props.qpqConfig).map(\n (setting) =>\n new QpqCoreApiGraphDatabaseConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n graphDatabaseConfig: setting,\n }),\n );\n QpqCoreApiGraphDatabaseConstruct.authorizeActionsForRole(webserverRole, allGraphDatabaseConfigs, props.qpqConfig);\n // end key value store\n\n // AI (Bedrock)\n QpqCoreAiConstruct.authorizeActionsForRole(webserverRole, qpqCoreUtils.getAllAiConfigs(props.qpqConfig));\n // end AI\n\n // Build websocket apis\n const websockets = qpqWebServerUtils.getOwnedWebsocketSettings(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverWebsocketConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n websocketConfig: setting,\n }),\n );\n QpqWebserverWebsocketConstruct.authorizeManageConnectionsForRole(webserverRole, websockets, props.qpqConfig);\n\n // Email senders (SES identities). The construct id is keyed by the primary root, not the\n // setting: an SES identity's physical id is the domain itself, so a changed logical id would\n // fail creation against the identity the stack already owns.\n const emailSenderConfigs = qpqWebServerUtils.getEmailSenderSettings(props.qpqConfig);\n const emailSenderConstructId = `EmailSender${qpqWebServerUtils.getPrimaryRootDomain(props.qpqConfig) ?? ''}`;\n emailSenderConfigs.map(\n (setting) =>\n new QpqWebserverEmailSenderConstruct(this, emailSenderConstructId, {\n qpqConfig: props.qpqConfig,\n\n emailSenderConfig: setting,\n }),\n );\n QpqWebserverEmailSenderConstruct.authorizeSendEmailForRole(webserverRole, emailSenderConfigs, props.qpqConfig);\n\n // Cache settings\n const cache = qpqWebServerUtils.getAllOwnedCacheConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebServerCacheConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n cacheConfig: setting,\n }),\n );\n\n // Certifcates\n const certifcates = qpqWebServerUtils.getAllOwnedCertifcateConfigs(props.qpqConfig).map(\n (setting) =>\n new QpqWebserverCertificateConstruct(this, qpqCoreUtils.getUniqueKeyForSetting(setting), {\n qpqConfig: props.qpqConfig,\n\n certificateConfig: setting,\n }),\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quidproquo-deploy-awscdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"constructs": "^10.7.1",
|
|
42
42
|
"esbuild": "^0.25.8",
|
|
43
43
|
"liquidjs": "^10.7.0",
|
|
44
|
-
"quidproquo-actionprocessor-awslambda": "0.1.
|
|
45
|
-
"quidproquo-actionprocessor-node": "0.1.
|
|
46
|
-
"quidproquo-config-aws": "0.1.
|
|
47
|
-
"quidproquo-core": "0.1.
|
|
48
|
-
"quidproquo-webserver": "0.1.
|
|
44
|
+
"quidproquo-actionprocessor-awslambda": "0.1.23",
|
|
45
|
+
"quidproquo-actionprocessor-node": "0.1.23",
|
|
46
|
+
"quidproquo-config-aws": "0.1.23",
|
|
47
|
+
"quidproquo-core": "0.1.23",
|
|
48
|
+
"quidproquo-webserver": "0.1.23",
|
|
49
49
|
"upath": "^2.0.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@types/babel__traverse": "7.18.2",
|
|
54
54
|
"@types/node": "^22.13.13",
|
|
55
55
|
"@types/prettier": "2.6.0",
|
|
56
|
-
"quidproquo-tsconfig": "0.1.
|
|
56
|
+
"quidproquo-tsconfig": "0.1.23",
|
|
57
57
|
"typescript": "^5.8.2"
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineAwsServiceAccountInfo } from 'quidproquo-config-aws';
|
|
2
|
+
import { buildTestQpqConfig, defineUserDirectory } from 'quidproquo-core';
|
|
3
|
+
|
|
4
|
+
import { App, aws_iam, Stack } from 'aws-cdk-lib';
|
|
5
|
+
import { Match, Template } from 'aws-cdk-lib/assertions';
|
|
6
|
+
import { describe, expect, it } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { QpqInfCoreUserDirectoryConstruct } from './QpqInfCoreUserDirectoryConstruct';
|
|
9
|
+
|
|
10
|
+
const env = { account: '123456789012', region: 'ap-southeast-2' };
|
|
11
|
+
|
|
12
|
+
// A service ('ca') that references a user directory owned by another service ('auth')
|
|
13
|
+
// in the same account.
|
|
14
|
+
const referenced = defineUserDirectory('users', { owner: { module: 'auth' } });
|
|
15
|
+
const qpqConfig = buildTestQpqConfig(
|
|
16
|
+
[defineAwsServiceAccountInfo(env.account, env.region, [{ moduleName: 'auth', awsAccountId: env.account, awsRegion: env.region }]), referenced],
|
|
17
|
+
{ moduleName: 'ca' },
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const buildRole = () => {
|
|
21
|
+
const stack = new Stack(new App(), 'test-svc', { env });
|
|
22
|
+
const role = new aws_iam.Role(stack, 'role', { assumedBy: new aws_iam.ServicePrincipal('lambda.amazonaws.com') });
|
|
23
|
+
return { stack, role };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe('QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole', () => {
|
|
27
|
+
it('grants read-only user lookups on a referenced (foreign-owned) pool via its exported pool id', () => {
|
|
28
|
+
const { stack, role } = buildRole();
|
|
29
|
+
|
|
30
|
+
QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(role, [referenced], qpqConfig);
|
|
31
|
+
|
|
32
|
+
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', {
|
|
33
|
+
PolicyDocument: {
|
|
34
|
+
Statement: Match.arrayWith([
|
|
35
|
+
Match.objectLike({
|
|
36
|
+
Effect: 'Allow',
|
|
37
|
+
Action: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],
|
|
38
|
+
// The pool id comes from the owner's stack export, composed into the pool ARN.
|
|
39
|
+
Resource: Match.objectLike({ 'Fn::Join': Match.anyValue() }),
|
|
40
|
+
}),
|
|
41
|
+
]),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const json = JSON.stringify(Template.fromStack(stack).toJSON());
|
|
46
|
+
expect(json).toContain('Fn::ImportValue');
|
|
47
|
+
expect(json).not.toContain('AdminCreateUser');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('skips a directory owned in another account (no cross-account Cognito grants)', () => {
|
|
51
|
+
const { stack, role } = buildRole();
|
|
52
|
+
const foreignConfig = buildTestQpqConfig(
|
|
53
|
+
[defineAwsServiceAccountInfo(env.account, env.region, [{ moduleName: 'auth', awsAccountId: '999999999999', awsRegion: env.region }]), referenced],
|
|
54
|
+
{ moduleName: 'ca' },
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(role, [referenced], foreignConfig);
|
|
58
|
+
|
|
59
|
+
expect(Template.fromStack(stack).findResources('AWS::IAM::Policy')).toEqual({});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';
|
|
2
|
-
import { AwsDataStoreRemovalPolicy, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';
|
|
2
|
+
import { AwsDataStoreRemovalPolicy, getLocalServiceAccountInfo, qpqConfigAwsUtils, resolveAwsServiceAccountInfo } from 'quidproquo-config-aws';
|
|
3
3
|
import { QPQConfig, UserDirectoryMfaMode, UserDirectoryMfaSecondFactor, UserDirectoryQPQConfigSetting } from 'quidproquo-core';
|
|
4
4
|
import { qpqWebServerUtils } from 'quidproquo-webserver';
|
|
5
5
|
|
|
@@ -225,8 +225,44 @@ export class QpqInfCoreUserDirectoryConstruct extends QpqConstructBlock {
|
|
|
225
225
|
);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// Grants READ-ONLY Cognito actions on user directories this service merely
|
|
229
|
+
// references (owned by another service): look a user up by attribute / by id
|
|
230
|
+
// (askUserDirectoryGetUsersByAttribute, askUserDirectoryGetUserAttributesByUserId).
|
|
231
|
+
// Any service that shows "who" needs this - e.g. the tenant registry adding a
|
|
232
|
+
// member by email from a service that doesn't own the pool. Nothing that
|
|
233
|
+
// mutates the pool: admin actions stay with the owner (below). Cognito has no
|
|
234
|
+
// resource policy, so a pool in another account can't be granted this way -
|
|
235
|
+
// such directories are skipped (the call fails as it does today).
|
|
236
|
+
public static authorizeReadActionsForRole(role: aws_iam.IRole, referencedDirectoryConfigs: UserDirectoryQPQConfigSetting[], qpqConfig: QPQConfig) {
|
|
237
|
+
const local = getLocalServiceAccountInfo(qpqConfig);
|
|
238
|
+
|
|
239
|
+
const resources = referencedDirectoryConfigs
|
|
240
|
+
.map((userDirectoryConfig) => ({
|
|
241
|
+
userDirectoryConfig,
|
|
242
|
+
account: resolveAwsServiceAccountInfo(qpqConfig, userDirectoryConfig.owner),
|
|
243
|
+
}))
|
|
244
|
+
.filter(({ account }) => account.awsAccountId === local.awsAccountId && account.awsRegion === local.awsRegion)
|
|
245
|
+
.map(({ userDirectoryConfig, account }) => {
|
|
246
|
+
const userPoolId = qpqDeployAwsCdkUtils.importStackValue(
|
|
247
|
+
awsNamingUtils.getCFExportNameUserPoolIdFromConfig(userDirectoryConfig.name, qpqConfig),
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
return `arn:aws:cognito-idp:${account.awsRegion}:${account.awsAccountId}:userpool/${userPoolId}`;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
if (resources.length > 0) {
|
|
254
|
+
role.addToPrincipalPolicy(
|
|
255
|
+
new aws_iam.PolicyStatement({
|
|
256
|
+
effect: aws_iam.Effect.ALLOW,
|
|
257
|
+
actions: ['cognito-idp:ListUsers', 'cognito-idp:AdminGetUser'],
|
|
258
|
+
resources,
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
228
264
|
// Grants admin Cognito actions for pools this service owns. Services that
|
|
229
|
-
// only reference a foreign user directory get
|
|
265
|
+
// only reference a foreign user directory get only the read grant above —
|
|
230
266
|
// token validation runs against the pool's public JWKs over HTTPS and needs
|
|
231
267
|
// no IAM. Call sites must pass only owned directories (see
|
|
232
268
|
// `qpqCoreUtils.getOwnedUserDirectories`).
|
|
@@ -114,6 +114,12 @@ export class InfQpqServiceStack extends QpqServiceStack {
|
|
|
114
114
|
);
|
|
115
115
|
QpqInfCoreUserDirectoryConstruct.authorizeAdminActionsForRole(webserverRole, ownedUserDirectoriesConfigs, userDirectories, props.qpqConfig);
|
|
116
116
|
|
|
117
|
+
// Directories this service references but doesn't own: read-only user lookups.
|
|
118
|
+
const referencedUserDirectoriesConfigs = qpqCoreUtils
|
|
119
|
+
.getUserDirectories(props.qpqConfig)
|
|
120
|
+
.filter((setting) => !ownedUserDirectoriesConfigs.includes(setting));
|
|
121
|
+
QpqInfCoreUserDirectoryConstruct.authorizeReadActionsForRole(webserverRole, referencedUserDirectoriesConfigs, props.qpqConfig);
|
|
122
|
+
|
|
117
123
|
// Api Keys
|
|
118
124
|
const apiKeys = qpqWebServerUtils.getAllApiKeyConfigs(props.qpqConfig).map(
|
|
119
125
|
(setting) =>
|