@jaypie/constructs 1.1.49 → 1.1.51

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.
Files changed (45) hide show
  1. package/dist/cjs/JaypieApiGateway.d.ts +1 -0
  2. package/dist/cjs/JaypieBucketQueuedLambda.d.ts +4 -19
  3. package/dist/cjs/JaypieDnsRecord.d.ts +45 -0
  4. package/dist/cjs/JaypieGitHubDeployRole.d.ts +14 -0
  5. package/dist/cjs/JaypieHostedZone.d.ts +26 -4
  6. package/dist/cjs/JaypieLambda.d.ts +1 -1
  7. package/dist/cjs/JaypieQueuedLambda.d.ts +1 -1
  8. package/dist/cjs/JaypieSsoPermissions.d.ts +96 -0
  9. package/dist/cjs/JaypieSsoSyncApplication.d.ts +27 -0
  10. package/dist/cjs/JaypieWebDeploymentBucket.d.ts +1 -0
  11. package/dist/cjs/__tests__/JaypieSsoSyncApplication.spec.d.ts +1 -0
  12. package/dist/cjs/helpers/__tests__/resolveDatadogForwarderFunction.spec.d.ts +1 -0
  13. package/dist/cjs/helpers/__tests__/resolveDatadogLoggingDestination.spec.d.ts +1 -0
  14. package/dist/cjs/helpers/index.d.ts +2 -0
  15. package/dist/cjs/helpers/resolveDatadogForwarderFunction.d.ts +7 -0
  16. package/dist/cjs/helpers/resolveDatadogLoggingDestination.d.ts +4 -0
  17. package/dist/cjs/index.cjs +592 -355
  18. package/dist/cjs/index.cjs.map +1 -1
  19. package/dist/cjs/index.d.ts +6 -2
  20. package/dist/esm/JaypieApiGateway.d.ts +1 -0
  21. package/dist/esm/JaypieBucketQueuedLambda.d.ts +4 -19
  22. package/dist/esm/JaypieDnsRecord.d.ts +45 -0
  23. package/dist/esm/JaypieGitHubDeployRole.d.ts +14 -0
  24. package/dist/esm/JaypieHostedZone.d.ts +26 -4
  25. package/dist/esm/JaypieLambda.d.ts +1 -1
  26. package/dist/esm/JaypieQueuedLambda.d.ts +1 -1
  27. package/dist/esm/JaypieSsoPermissions.d.ts +96 -0
  28. package/dist/esm/JaypieSsoSyncApplication.d.ts +27 -0
  29. package/dist/esm/JaypieWebDeploymentBucket.d.ts +1 -0
  30. package/dist/esm/__tests__/JaypieDnsRecord.spec.d.ts +1 -0
  31. package/dist/esm/__tests__/JaypieSsoPermissions.spec.d.ts +1 -0
  32. package/dist/esm/__tests__/JaypieSsoSyncApplication.spec.d.ts +1 -0
  33. package/dist/esm/helpers/__tests__/resolveDatadogForwarderFunction.spec.d.ts +1 -0
  34. package/dist/esm/helpers/__tests__/resolveDatadogLoggingDestination.spec.d.ts +1 -0
  35. package/dist/esm/helpers/index.d.ts +2 -0
  36. package/dist/esm/helpers/resolveDatadogForwarderFunction.d.ts +7 -0
  37. package/dist/esm/helpers/resolveDatadogLoggingDestination.d.ts +4 -0
  38. package/dist/esm/index.d.ts +6 -2
  39. package/dist/esm/index.js +585 -356
  40. package/dist/esm/index.js.map +1 -1
  41. package/package.json +3 -2
  42. package/dist/cjs/JaypieSsoGroups.d.ts +0 -121
  43. package/dist/esm/JaypieSsoGroups.d.ts +0 -121
  44. /package/dist/cjs/__tests__/{JaypieSsoGroups.spec.d.ts → JaypieDnsRecord.spec.d.ts} +0 -0
  45. /package/dist/{esm/__tests__/JaypieSsoGroups.spec.d.ts → cjs/__tests__/JaypieSsoPermissions.spec.d.ts} +0 -0
@@ -1,22 +1,25 @@
1
1
  'use strict';
2
2
 
3
+ var cdk = require('@jaypie/cdk');
3
4
  var constructs = require('constructs');
4
5
  var cdk$1 = require('aws-cdk-lib');
5
6
  var acm = require('aws-cdk-lib/aws-certificatemanager');
6
7
  var apiGateway = require('aws-cdk-lib/aws-apigateway');
7
8
  var route53 = require('aws-cdk-lib/aws-route53');
8
9
  var route53Targets = require('aws-cdk-lib/aws-route53-targets');
9
- var cdk = require('@jaypie/cdk');
10
10
  var secretsmanager = require('aws-cdk-lib/aws-secretsmanager');
11
11
  var datadogCdkConstructsV2 = require('datadog-cdk-constructs-v2');
12
12
  var lambda = require('aws-cdk-lib/aws-lambda');
13
+ var logDestinations = require('aws-cdk-lib/aws-logs-destinations');
13
14
  var s3 = require('aws-cdk-lib/aws-s3');
14
15
  var s3n = require('aws-cdk-lib/aws-s3-notifications');
15
16
  var sqs = require('aws-cdk-lib/aws-sqs');
16
17
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
17
18
  var awsIam = require('aws-cdk-lib/aws-iam');
18
19
  var awsLogs = require('aws-cdk-lib/aws-logs');
19
- var sso = require('aws-cdk-lib/aws-sso');
20
+ var awsSso = require('aws-cdk-lib/aws-sso');
21
+ var awsSam = require('aws-cdk-lib/aws-sam');
22
+ var errors = require('@jaypie/errors');
20
23
  var cloudfront = require('aws-cdk-lib/aws-cloudfront');
21
24
  var origins = require('aws-cdk-lib/aws-cloudfront-origins');
22
25
 
@@ -44,11 +47,11 @@ var route53__namespace = /*#__PURE__*/_interopNamespaceDefault(route53);
44
47
  var route53Targets__namespace = /*#__PURE__*/_interopNamespaceDefault(route53Targets);
45
48
  var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsmanager);
46
49
  var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
50
+ var logDestinations__namespace = /*#__PURE__*/_interopNamespaceDefault(logDestinations);
47
51
  var s3__namespace = /*#__PURE__*/_interopNamespaceDefault(s3);
48
52
  var s3n__namespace = /*#__PURE__*/_interopNamespaceDefault(s3n);
49
53
  var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
50
54
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
51
- var sso__namespace = /*#__PURE__*/_interopNamespaceDefault(sso);
52
55
  var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
53
56
  var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
54
57
 
@@ -247,6 +250,33 @@ function jaypieLambdaEnv(options = {}) {
247
250
  return environment;
248
251
  }
249
252
 
253
+ const DEFAULT_FUNCTION_NAME$1 = "DatadogForwarderFunction";
254
+ // Cache to store resolved functions
255
+ // Using nested structure to support multiple functions per scope with automatic GC
256
+ const functionCache = new WeakMap();
257
+ function resolveDatadogForwarderFunction(scope, options) {
258
+ const { import: importValue, name } = options || {};
259
+ const functionName = name || DEFAULT_FUNCTION_NAME$1;
260
+ const importKey = importValue || cdk.CDK.IMPORT.DATADOG_LOG_FORWARDER;
261
+ // Create a cache key based on name and import
262
+ const cacheKey = `${functionName}:${importKey}`;
263
+ // Get or create scope cache
264
+ let scopeCache = functionCache.get(scope);
265
+ if (!scopeCache) {
266
+ scopeCache = new Map();
267
+ functionCache.set(scope, scopeCache);
268
+ }
269
+ // Return cached function if it exists
270
+ const cachedFunction = scopeCache.get(cacheKey);
271
+ if (cachedFunction) {
272
+ return cachedFunction;
273
+ }
274
+ // Create and cache the function
275
+ const func = lambda__namespace.Function.fromFunctionArn(scope, functionName, cdk__namespace.Fn.importValue(importKey));
276
+ scopeCache.set(cacheKey, func);
277
+ return func;
278
+ }
279
+
250
280
  function resolveDatadogLayers(scope, options = {}) {
251
281
  const { datadogApiKeyArn, uniqueId } = options;
252
282
  let resolvedRegion = cdk$1.Stack.of(scope).region || "us-east-1";
@@ -266,6 +296,35 @@ function resolveDatadogLayers(scope, options = {}) {
266
296
  return [datadogNodeLayer, datadogExtensionLayer];
267
297
  }
268
298
 
299
+ const DEFAULT_FUNCTION_NAME = "DatadogForwarderFunction";
300
+ // Cache to store resolved logging destinations
301
+ // Using nested structure to support multiple destinations per scope with automatic GC
302
+ const destinationCache = new WeakMap();
303
+ function resolveDatadogLoggingDestination(scope, options) {
304
+ const { import: importValue, name } = options || {};
305
+ // Create a cache key based on name and import (same as forwarder function)
306
+ const functionName = name || DEFAULT_FUNCTION_NAME;
307
+ const importKey = importValue || cdk.CDK.IMPORT.DATADOG_LOG_FORWARDER;
308
+ const cacheKey = `${functionName}:${importKey}`;
309
+ // Get or create scope cache
310
+ let scopeCache = destinationCache.get(scope);
311
+ if (!scopeCache) {
312
+ scopeCache = new Map();
313
+ destinationCache.set(scope, scopeCache);
314
+ }
315
+ // Return cached destination if it exists
316
+ const cachedDestination = scopeCache.get(cacheKey);
317
+ if (cachedDestination) {
318
+ return cachedDestination;
319
+ }
320
+ // Resolve the Datadog forwarder function
321
+ const datadogForwarderFunction = resolveDatadogForwarderFunction(scope, options);
322
+ // Create and cache the logging destination
323
+ const datadogLoggingDestination = new logDestinations__namespace.LambdaDestination(datadogForwarderFunction);
324
+ scopeCache.set(cacheKey, datadogLoggingDestination);
325
+ return datadogLoggingDestination;
326
+ }
327
+
269
328
  function resolveHostedZone(scope, { name = "HostedZone", zone = process.env.CDK_ENV_HOSTED_ZONE, } = {}) {
270
329
  if (!zone) {
271
330
  throw new cdk.ConfigurationError("No `zone` provided. Set CDK_ENV_HOSTED_ZONE to use environment zone");
@@ -439,6 +498,11 @@ class JaypieApiGateway extends constructs.Construct {
439
498
  applyRemovalPolicy(policy) {
440
499
  this._api.applyRemovalPolicy(policy);
441
500
  }
501
+ get restApiRef() {
502
+ return {
503
+ restApiId: this._api.restApiId,
504
+ };
505
+ }
442
506
  }
443
507
 
444
508
  class JaypieStack extends cdk$1.Stack {
@@ -620,7 +684,10 @@ class JaypieLambda extends constructs.Construct {
620
684
  return this._reference.resourceArnsForGrantInvoke;
621
685
  }
622
686
  get functionRef() {
623
- return this._reference.functionRef;
687
+ return {
688
+ functionArn: this._reference.functionArn,
689
+ functionName: this._reference.functionName,
690
+ };
624
691
  }
625
692
  addEventSource(source) {
626
693
  this._reference.addEventSource(source);
@@ -982,7 +1049,7 @@ class JaypieBucketQueuedLambda extends JaypieQueuedLambda {
982
1049
  get policy() {
983
1050
  return this._bucket.policy;
984
1051
  }
985
- addEventNotification(event, dest, filters) {
1052
+ addEventNotification(event, dest, ...filters) {
986
1053
  this._bucket.addEventNotification(event, dest, ...filters);
987
1054
  }
988
1055
  addObjectCreatedNotification(dest, ...filters) {
@@ -1000,9 +1067,6 @@ class JaypieBucketQueuedLambda extends JaypieQueuedLambda {
1000
1067
  enableEventBridgeNotification() {
1001
1068
  this._bucket.enableEventBridgeNotification();
1002
1069
  }
1003
- grant(grantee, ...actions) {
1004
- return this._bucket.grant(grantee, ...actions);
1005
- }
1006
1070
  grantDelete(grantee, objectsKeyPattern) {
1007
1071
  return this._bucket.grantDelete(grantee, objectsKeyPattern);
1008
1072
  }
@@ -1045,54 +1109,17 @@ class JaypieBucketQueuedLambda extends JaypieQueuedLambda {
1045
1109
  virtualHostedUrlForObject(key, options) {
1046
1110
  return this._bucket.virtualHostedUrlForObject(key, options);
1047
1111
  }
1048
- // Bucket metrics
1049
- metricAllRequests(props) {
1050
- return this._bucket.metricAllRequests(props);
1051
- }
1052
- metricBucketSizeBytes(props) {
1053
- return this._bucket.metricBucketSizeBytes(props);
1054
- }
1055
- metricDeleteRequests(props) {
1056
- return this._bucket.metricDeleteRequests(props);
1057
- }
1058
- metricDownloadBytes(props) {
1059
- return this._bucket.metricDownloadBytes(props);
1060
- }
1061
- metricFirstByteLatency(props) {
1062
- return this._bucket.metricFirstByteLatency(props);
1063
- }
1064
- metricGetRequests(props) {
1065
- return this._bucket.metricGetRequests(props);
1066
- }
1067
- metricHeadRequests(props) {
1068
- return this._bucket.metricHeadRequests(props);
1069
- }
1070
- metricHttpRequests(props) {
1071
- return this._bucket.metricHttpRequests(props);
1072
- }
1073
- metricListRequests(props) {
1074
- return this._bucket.metricListRequests(props);
1075
- }
1076
- metricNumberOfObjects(props) {
1077
- return this._bucket.metricNumberOfObjects(props);
1078
- }
1079
- metricPostRequests(props) {
1080
- return this._bucket.metricPostRequests(props);
1081
- }
1082
- metricPutRequests(props) {
1083
- return this._bucket.metricPutRequests(props);
1084
- }
1085
- metricSelectRequests(props) {
1086
- return this._bucket.metricSelectRequests(props);
1087
- }
1088
- metricSelectScannedBytes(props) {
1089
- return this._bucket.metricSelectScannedBytes(props);
1112
+ grantReplicationPermission(identity, props) {
1113
+ return this._bucket.grantReplicationPermission(identity, props);
1090
1114
  }
1091
- metricUploadBytes(props) {
1092
- return this._bucket.metricUploadBytes(props);
1115
+ addReplicationPolicy(policy) {
1116
+ this._bucket.addReplicationPolicy(policy);
1093
1117
  }
1094
- metricSelectReturnedBytes(props) {
1095
- return this._bucket.metricSelectReturnedBytes(props);
1118
+ get bucketRef() {
1119
+ return {
1120
+ bucketArn: this._bucket.bucketArn,
1121
+ bucketName: this._bucket.bucketName,
1122
+ };
1096
1123
  }
1097
1124
  // Override applyRemovalPolicy to apply to all resources
1098
1125
  applyRemovalPolicy(policy) {
@@ -1246,6 +1273,166 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
1246
1273
  }
1247
1274
  }
1248
1275
 
1276
+ class JaypieDnsRecord extends constructs.Construct {
1277
+ constructor(scope, id, props) {
1278
+ super(scope, id);
1279
+ const { comment, recordName, type, values } = props;
1280
+ const ttl = props.ttl || cdk__namespace.Duration.seconds(cdk.CDK.DNS.CONFIG.TTL);
1281
+ // Resolve the hosted zone (supports both string and IHostedZone)
1282
+ const zone = resolveHostedZone(scope, {
1283
+ name: `${id}HostedZone`,
1284
+ zone: props.zone,
1285
+ });
1286
+ // Common properties for all record types
1287
+ const baseProps = {
1288
+ comment,
1289
+ recordName,
1290
+ ttl,
1291
+ zone,
1292
+ };
1293
+ // Create the appropriate record based on type
1294
+ switch (type) {
1295
+ case cdk.CDK.DNS.RECORD.A: {
1296
+ if (!Array.isArray(values) || values.length === 0) {
1297
+ throw new cdk.ConfigurationError("A record requires at least one IP address");
1298
+ }
1299
+ this.record = new route53.ARecord(this, "Record", {
1300
+ ...baseProps,
1301
+ target: route53.RecordTarget.fromIpAddresses(...values),
1302
+ });
1303
+ break;
1304
+ }
1305
+ case cdk.CDK.DNS.RECORD.CNAME: {
1306
+ if (!Array.isArray(values) || values.length === 0) {
1307
+ throw new cdk.ConfigurationError("CNAME record requires a domain name");
1308
+ }
1309
+ this.record = new route53.CnameRecord(this, "Record", {
1310
+ ...baseProps,
1311
+ domainName: values[0],
1312
+ });
1313
+ break;
1314
+ }
1315
+ case cdk.CDK.DNS.RECORD.MX: {
1316
+ if (!Array.isArray(values) || values.length === 0) {
1317
+ throw new cdk.ConfigurationError("MX record requires at least one mail server");
1318
+ }
1319
+ this.record = new route53.MxRecord(this, "Record", {
1320
+ ...baseProps,
1321
+ values: values,
1322
+ });
1323
+ break;
1324
+ }
1325
+ case cdk.CDK.DNS.RECORD.NS: {
1326
+ if (!Array.isArray(values) || values.length === 0) {
1327
+ throw new cdk.ConfigurationError("NS record requires at least one name server");
1328
+ }
1329
+ this.record = new route53.NsRecord(this, "Record", {
1330
+ ...baseProps,
1331
+ values: values,
1332
+ });
1333
+ break;
1334
+ }
1335
+ case cdk.CDK.DNS.RECORD.TXT: {
1336
+ if (!Array.isArray(values) || values.length === 0) {
1337
+ throw new cdk.ConfigurationError("TXT record requires at least one value");
1338
+ }
1339
+ this.record = new route53.TxtRecord(this, "Record", {
1340
+ ...baseProps,
1341
+ values: values,
1342
+ });
1343
+ break;
1344
+ }
1345
+ default:
1346
+ throw new cdk.ConfigurationError(`Unsupported DNS record type: ${type}. Supported types: A, CNAME, MX, NS, TXT`);
1347
+ }
1348
+ // Add standard tags to the DNS record
1349
+ cdk__namespace.Tags.of(this.record).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.INFRASTRUCTURE);
1350
+ cdk__namespace.Tags.of(this.record).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
1351
+ }
1352
+ }
1353
+
1354
+ class JaypieGitHubDeployRole extends constructs.Construct {
1355
+ constructor(scope, id, props = {}) {
1356
+ super(scope, id);
1357
+ const { oidcProviderArn = cdk$1.Fn.importValue(cdk.CDK.IMPORT.OIDC_PROVIDER), output = true, repoRestriction: propsRepoRestriction, } = props;
1358
+ // Extract account ID from the scope
1359
+ const accountId = cdk$1.Stack.of(this).account;
1360
+ // Resolve repoRestriction from props or environment variables
1361
+ let repoRestriction = propsRepoRestriction;
1362
+ if (!repoRestriction) {
1363
+ const envRepo = process.env.CDK_ENV_REPO || process.env.PROJECT_REPO;
1364
+ if (!envRepo) {
1365
+ throw new cdk.ConfigurationError("No repoRestriction provided. Set repoRestriction prop, CDK_ENV_REPO, or PROJECT_REPO environment variable");
1366
+ }
1367
+ // Extract organization from owner/repo format and create org-wide restriction
1368
+ const organization = envRepo.split("/")[0];
1369
+ repoRestriction = `repo:${organization}/*:*`;
1370
+ }
1371
+ // Create the IAM role
1372
+ this._role = new awsIam.Role(this, "GitHubActionsRole", {
1373
+ assumedBy: new awsIam.FederatedPrincipal(oidcProviderArn, {
1374
+ StringLike: {
1375
+ "token.actions.githubusercontent.com:sub": repoRestriction,
1376
+ },
1377
+ }, "sts:AssumeRoleWithWebIdentity"),
1378
+ maxSessionDuration: cdk$1.Duration.hours(1),
1379
+ path: "/",
1380
+ });
1381
+ cdk$1.Tags.of(this._role).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.DEPLOY);
1382
+ // Allow the role to access the GitHub OIDC provider
1383
+ this._role.addToPolicy(new awsIam.PolicyStatement({
1384
+ actions: ["sts:AssumeRoleWithWebIdentity"],
1385
+ resources: [`arn:aws:iam::${accountId}:oidc-provider/*`],
1386
+ }));
1387
+ // Allow the role to deploy CDK apps
1388
+ this._role.addToPolicy(new awsIam.PolicyStatement({
1389
+ actions: [
1390
+ "cloudformation:CreateStack",
1391
+ "cloudformation:DeleteStack",
1392
+ "cloudformation:DescribeStackEvents",
1393
+ "cloudformation:DescribeStackResource",
1394
+ "cloudformation:DescribeStackResources",
1395
+ "cloudformation:DescribeStacks",
1396
+ "cloudformation:GetTemplate",
1397
+ "cloudformation:SetStackPolicy",
1398
+ "cloudformation:UpdateStack",
1399
+ "cloudformation:ValidateTemplate",
1400
+ "iam:PassRole",
1401
+ "route53:ListHostedZones*",
1402
+ "s3:GetObject",
1403
+ "s3:ListBucket",
1404
+ ],
1405
+ effect: awsIam.Effect.ALLOW,
1406
+ resources: ["*"],
1407
+ }));
1408
+ this._role.addToPolicy(new awsIam.PolicyStatement({
1409
+ actions: ["iam:PassRole", "sts:AssumeRole"],
1410
+ effect: awsIam.Effect.ALLOW,
1411
+ resources: [
1412
+ "arn:aws:iam::*:role/cdk-hnb659fds-deploy-role-*",
1413
+ "arn:aws:iam::*:role/cdk-hnb659fds-file-publishing-*",
1414
+ "arn:aws:iam::*:role/cdk-readOnlyRole",
1415
+ ],
1416
+ }));
1417
+ // Export the ARN of the role
1418
+ if (output !== false) {
1419
+ const outputId = typeof output === "string" ? output : "GitHubActionsRoleArn";
1420
+ new cdk$1.CfnOutput(this, outputId, {
1421
+ value: this._role.roleArn,
1422
+ });
1423
+ }
1424
+ }
1425
+ get role() {
1426
+ return this._role;
1427
+ }
1428
+ get roleArn() {
1429
+ return this._role.roleArn;
1430
+ }
1431
+ get roleName() {
1432
+ return this._role.roleName;
1433
+ }
1434
+ }
1435
+
1249
1436
  class JaypieExpressLambda extends JaypieLambda {
1250
1437
  constructor(scope, id, props) {
1251
1438
  super(scope, id, {
@@ -1261,11 +1448,12 @@ const SERVICE = {
1261
1448
  };
1262
1449
  class JaypieHostedZone extends constructs.Construct {
1263
1450
  /**
1264
- * Create a new hosted zone with query logging
1451
+ * Create a new hosted zone with query logging and optional DNS records
1265
1452
  */
1266
1453
  constructor(scope, id, props) {
1267
1454
  super(scope, id);
1268
- const { destination, zoneName, project } = props;
1455
+ const { zoneName, project } = props;
1456
+ const destination = props.destination ?? true;
1269
1457
  const service = props.service || cdk.CDK.SERVICE.INFRASTRUCTURE;
1270
1458
  // Create the log group
1271
1459
  this.logGroup = new awsLogs.LogGroup(this, "LogGroup", {
@@ -1282,10 +1470,13 @@ class JaypieHostedZone extends constructs.Construct {
1282
1470
  }
1283
1471
  // Grant Route 53 permissions to write to the log group
1284
1472
  this.logGroup.grantWrite(new awsIam.ServicePrincipal(SERVICE.ROUTE53));
1285
- // Add destination if provided
1286
- if (destination) {
1473
+ // Add destination based on configuration
1474
+ if (destination !== false) {
1475
+ const lambdaDestination = destination === true
1476
+ ? resolveDatadogLoggingDestination(scope)
1477
+ : destination;
1287
1478
  this.logGroup.addSubscriptionFilter("DatadogLambdaDestination", {
1288
- destination,
1479
+ destination: lambdaDestination,
1289
1480
  filterPattern: awsLogs.FilterPattern.allEvents(),
1290
1481
  });
1291
1482
  }
@@ -1300,6 +1491,21 @@ class JaypieHostedZone extends constructs.Construct {
1300
1491
  if (project) {
1301
1492
  cdk__namespace.Tags.of(this.hostedZone).add(cdk.CDK.TAG.PROJECT, project);
1302
1493
  }
1494
+ // Create DNS records if provided
1495
+ this.dnsRecords = [];
1496
+ if (props.records) {
1497
+ props.records.forEach((recordConfig, index) => {
1498
+ const { id, ...recordProps } = recordConfig;
1499
+ // Generate a default ID if not provided
1500
+ const recordId = id ||
1501
+ `${recordProps.type}${recordProps.recordName ? `-${recordProps.recordName}` : ""}-${index}`;
1502
+ const dnsRecord = new JaypieDnsRecord(this, recordId, {
1503
+ ...recordProps,
1504
+ zone: this.hostedZone,
1505
+ });
1506
+ this.dnsRecords.push(dnsRecord);
1507
+ });
1508
+ }
1303
1509
  }
1304
1510
  }
1305
1511
 
@@ -1348,333 +1554,349 @@ class JaypieOpenAiSecret extends JaypieEnvSecret {
1348
1554
  }
1349
1555
 
1350
1556
  /**
1351
- * Permission set types with corresponding AWS managed policies
1557
+ * JaypieSsoPermissions Construct
1558
+ *
1559
+ * Creates and manages AWS IAM Identity Center (SSO) permission sets and assignments
1560
+ *
1561
+ * @example
1562
+ * const permissionSets = new JaypieSsoPermissions(this, "PermissionSets", {
1563
+ * iamIdentityCenterArn: "arn:aws:sso:::instance/...",
1564
+ * administratorGroupId: "b4c8b438-4031-7000-782d-5046945fb956",
1565
+ * analystGroupId: "2488f4e8-d061-708e-abe1-c315f0e30005",
1566
+ * developerGroupId: "b438a4f8-e0e1-707c-c6e8-21841daf9ad1",
1567
+ * administratorAccountAssignments: {
1568
+ * "211125635435": ["Administrator", "Analyst", "Developer"],
1569
+ * "381492033431": ["Administrator", "Analyst"],
1570
+ * },
1571
+ * analystAccountAssignments: {
1572
+ * "211125635435": ["Analyst", "Developer"],
1573
+ * "381492033431": [],
1574
+ * },
1575
+ * developerAccountAssignments: {
1576
+ * "211125635435": ["Analyst", "Developer"],
1577
+ * "381492033431": [],
1578
+ * },
1579
+ * });
1352
1580
  */
1353
- exports.PermissionSetType = void 0;
1354
- (function (PermissionSetType) {
1355
- PermissionSetType["ADMINISTRATOR"] = "Administrator";
1356
- PermissionSetType["ANALYST"] = "Analyst";
1357
- PermissionSetType["DEVELOPER"] = "Developer";
1358
- })(exports.PermissionSetType || (exports.PermissionSetType = {}));
1359
- /**
1360
- * Construct to simplify AWS SSO group management.
1361
- * This construct encapsulates the complexity of creating permission sets
1362
- * and assigning them to groups across multiple AWS accounts.
1363
- */
1364
- class JaypieSsoGroups extends constructs.Construct {
1581
+ class JaypieSsoPermissions extends constructs.Construct {
1365
1582
  constructor(scope, id, props) {
1366
1583
  super(scope, id);
1367
- this.permissionSets = {};
1368
- this.instanceArn = props.instanceArn;
1369
- this.props = props;
1370
- // Create the permission sets
1371
- this.createAdministratorPermissionSet();
1372
- this.createAnalystPermissionSet();
1373
- this.createDeveloperPermissionSet();
1374
- // Create the assignments
1375
- this.createPermissionSetAssignments(props);
1376
- }
1377
- /**
1378
- * Creates the Administrator permission set with AdministratorAccess policy
1379
- * and billing access
1380
- */
1381
- createAdministratorPermissionSet() {
1382
- const defaultInlinePolicy = {
1383
- Version: "2012-10-17",
1384
- Statement: [
1584
+ const { iamIdentityCenterArn: iamIdentityCenterArnProp, administratorGroupId, analystGroupId, developerGroupId, administratorAccountAssignments, analystAccountAssignments, developerAccountAssignments, } = props;
1585
+ const iamIdentityCenterArn = iamIdentityCenterArnProp || process.env.CDK_ENV_IAM_IDENTITY_CENTER_ARN;
1586
+ if (!iamIdentityCenterArn) {
1587
+ // If no IAM Identity Center ARN provided, skip SSO setup
1588
+ return;
1589
+ }
1590
+ //
1591
+ // Permission Sets
1592
+ //
1593
+ this.administratorPermissionSet = new awsSso.CfnPermissionSet(this, "AdministratorPermissionSet", {
1594
+ // Required
1595
+ instanceArn: iamIdentityCenterArn,
1596
+ name: "Administrator",
1597
+ // Optional
1598
+ description: "Unrestricted access",
1599
+ inlinePolicy: {
1600
+ Version: "2012-10-17",
1601
+ Statement: [
1602
+ {
1603
+ Effect: "Allow",
1604
+ Action: [
1605
+ "aws-portal:ViewUsage",
1606
+ "aws-portal:ViewBilling",
1607
+ "budgets:*",
1608
+ "cur:DescribeReportDefinitions",
1609
+ "cur:PutReportDefinition",
1610
+ "cur:DeleteReportDefinition",
1611
+ "cur:ModifyReportDefinition",
1612
+ ],
1613
+ Resource: "*",
1614
+ },
1615
+ ],
1616
+ },
1617
+ managedPolicies: [
1618
+ awsIam.ManagedPolicy.fromAwsManagedPolicyName("AdministratorAccess")
1619
+ .managedPolicyArn,
1620
+ awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
1621
+ ],
1622
+ sessionDuration: cdk$1.Duration.hours(1).toIsoString(),
1623
+ tags: [
1385
1624
  {
1386
- Effect: "Allow",
1387
- Action: [
1388
- "aws-portal:*",
1389
- "budgets:*",
1390
- "ce:*",
1391
- "cost-optimization-hub:*",
1392
- "cur:*",
1393
- ],
1394
- Resource: "*",
1625
+ key: cdk.CDK.TAG.SERVICE,
1626
+ value: cdk.CDK.SERVICE.SSO,
1395
1627
  },
1396
- ],
1397
- };
1398
- // Merge with any additional policy statements provided for administrators
1399
- const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.administrators);
1400
- const permissionSet = new sso__namespace.CfnPermissionSet(this, "AdministratorPermissionSet", {
1401
- instanceArn: this.instanceArn,
1402
- name: exports.PermissionSetType.ADMINISTRATOR,
1403
- description: "Full administrative access to all AWS services and resources",
1404
- sessionDuration: cdk$1.Duration.hours(8).toIsoString(),
1405
- managedPolicies: ["arn:aws:iam::aws:policy/AdministratorAccess"],
1406
- inlinePolicy: mergedPolicy,
1407
- });
1408
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1409
- this.permissionSets[exports.PermissionSetType.ADMINISTRATOR] = permissionSet;
1410
- }
1411
- /**
1412
- * Creates the Analyst permission set with ReadOnlyAccess policy
1413
- * and limited write access
1414
- */
1415
- createAnalystPermissionSet() {
1416
- const defaultInlinePolicy = {
1417
- Version: "2012-10-17",
1418
- Statement: [
1419
1628
  {
1420
- Effect: "Allow",
1421
- Action: [
1422
- "aws-portal:ViewUsage",
1423
- "aws-portal:ViewBilling",
1424
- "budgets:Describe*",
1425
- "budgets:View*",
1426
- "ce:Get*",
1427
- "ce:List*",
1428
- "cloudformation:Describe*",
1429
- "cloudformation:Get*",
1430
- "cloudformation:List*",
1431
- "cloudwatch:BatchGet*",
1432
- "cloudwatch:Get*",
1433
- "cloudwatch:List*",
1434
- "cost-optimization-hub:Get*",
1435
- "cost-optimization-hub:List*",
1436
- "ec2:Describe*",
1437
- "ec2:Get*",
1438
- "ec2:List*",
1439
- "ec2:Search*",
1440
- "iam:Get*",
1441
- "iam:List*",
1442
- "iam:PassRole",
1443
- "lambda:Get*",
1444
- "lambda:List*",
1445
- "logs:Describe*",
1446
- "logs:Get*",
1447
- "logs:List*",
1448
- "pipes:Describe*",
1449
- "pipes:List*",
1450
- "s3:Get*",
1451
- "s3:List*",
1452
- "secretsmanager:GetRandomPassword",
1453
- "secretsmanager:GetResourcePolicy",
1454
- "secretsmanager:List*",
1455
- "securityhub:Describe*",
1456
- "securityhub:Get*",
1457
- "securityhub:List*",
1458
- "servicecatalog:Describe*",
1459
- "sns:Get*",
1460
- "sns:List*",
1461
- "sqs:Get*",
1462
- "sqs:List*",
1463
- "states:Describe*",
1464
- "states:Get*",
1465
- "states:List*",
1466
- "tag:*",
1467
- "xray:*",
1468
- ],
1469
- Resource: "*",
1629
+ key: cdk.CDK.TAG.ROLE,
1630
+ value: cdk.CDK.ROLE.SECURITY,
1470
1631
  },
1471
1632
  ],
1472
- };
1473
- // Merge with any additional policy statements provided for analysts
1474
- const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.analysts);
1475
- const permissionSet = new sso__namespace.CfnPermissionSet(this, "AnalystPermissionSet", {
1476
- instanceArn: this.instanceArn,
1477
- name: exports.PermissionSetType.ANALYST,
1478
- description: "Read-only access with billing visibility and limited write access",
1479
- sessionDuration: cdk$1.Duration.hours(4).toIsoString(),
1633
+ });
1634
+ this.analystPermissionSet = new awsSso.CfnPermissionSet(this, "AnalystPermissionSet", {
1635
+ // Required
1636
+ instanceArn: iamIdentityCenterArn,
1637
+ name: "Analyst",
1638
+ // Optional
1639
+ description: "Read-only access; may expand to limited write access",
1640
+ inlinePolicy: {
1641
+ Version: "2012-10-17",
1642
+ Statement: [
1643
+ {
1644
+ Effect: "Allow",
1645
+ Action: [
1646
+ "aws-portal:ViewUsage",
1647
+ "aws-portal:ViewBilling",
1648
+ "budgets:Describe*",
1649
+ "budgets:View*",
1650
+ "ce:Get*",
1651
+ "ce:List*",
1652
+ "cloudformation:Describe*",
1653
+ "cloudformation:Get*",
1654
+ "cloudformation:List*",
1655
+ "cloudwatch:BatchGet*",
1656
+ "cloudwatch:Get*",
1657
+ "cloudwatch:List*",
1658
+ "cost-optimization-hub:Get*",
1659
+ "cost-optimization-hub:List*",
1660
+ "ec2:Describe*",
1661
+ "ec2:Get*",
1662
+ "ec2:List*",
1663
+ "ec2:Search*",
1664
+ "iam:Get*",
1665
+ "iam:List*",
1666
+ "iam:PassRole",
1667
+ "lambda:Get*",
1668
+ "lambda:List*",
1669
+ "logs:Describe*",
1670
+ "logs:Get*",
1671
+ "logs:List*",
1672
+ "pipes:Describe*",
1673
+ "pipes:List*",
1674
+ "s3:Get*",
1675
+ "s3:List*",
1676
+ "secretsmanager:GetRandomPassword",
1677
+ "secretsmanager:GetResourcePolicy",
1678
+ "secretsmanager:List*",
1679
+ "securityhub:Describe*",
1680
+ "securityhub:Get*",
1681
+ "securityhub:List*",
1682
+ "servicecatalog:Describe*",
1683
+ "sns:Get*",
1684
+ "sns:List*",
1685
+ "sqs:Get*",
1686
+ "sqs:List*",
1687
+ "states:Describe*",
1688
+ "states:Get*",
1689
+ "states:List*",
1690
+ "tag:*",
1691
+ "xray:*",
1692
+ ],
1693
+ Resource: "*",
1694
+ },
1695
+ ],
1696
+ },
1480
1697
  managedPolicies: [
1481
1698
  awsIam.ManagedPolicy.fromAwsManagedPolicyName("AmazonQDeveloperAccess")
1482
1699
  .managedPolicyArn,
1700
+ awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
1483
1701
  awsIam.ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess")
1484
1702
  .managedPolicyArn,
1485
1703
  ],
1486
- inlinePolicy: mergedPolicy,
1487
- });
1488
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1489
- this.permissionSets[exports.PermissionSetType.ANALYST] = permissionSet;
1490
- }
1491
- /**
1492
- * Creates the Developer permission set with SystemAdministrator policy
1493
- * and expanded write access
1494
- */
1495
- createDeveloperPermissionSet() {
1496
- const defaultInlinePolicy = {
1497
- Version: "2012-10-17",
1498
- Statement: [
1704
+ sessionDuration: cdk$1.Duration.hours(12).toIsoString(),
1705
+ tags: [
1499
1706
  {
1500
- Effect: "Allow",
1501
- Action: [
1502
- "budgets:*",
1503
- "ce:*",
1504
- "cloudformation:*",
1505
- "cloudwatch:*",
1506
- "cost-optimization-hub:*",
1507
- "ec2:*",
1508
- "iam:Get*",
1509
- "iam:List*",
1510
- "iam:PassRole",
1511
- "lambda:*",
1512
- "logs:*",
1513
- "pipes:*",
1514
- "s3:*",
1515
- "secretsmanager:*",
1516
- "securityhub:*",
1517
- "servicecatalog:*",
1518
- "sns:*",
1519
- "sqs:*",
1520
- "states:*",
1521
- "tag:*",
1522
- "xray:*",
1523
- ],
1524
- Resource: "*",
1707
+ key: cdk.CDK.TAG.SERVICE,
1708
+ value: cdk.CDK.SERVICE.SSO,
1525
1709
  },
1526
1710
  {
1527
- Effect: "Deny",
1528
- Action: [
1529
- "iam:*User*",
1530
- "iam:*Role*",
1531
- "iam:*Policy*",
1532
- "organizations:*",
1533
- "account:*",
1534
- ],
1535
- Resource: "*",
1711
+ key: cdk.CDK.TAG.ROLE,
1712
+ value: cdk.CDK.ROLE.SECURITY,
1536
1713
  },
1537
1714
  ],
1538
- };
1539
- // Merge with any additional policy statements provided for developers
1540
- const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.developers);
1541
- const permissionSet = new sso__namespace.CfnPermissionSet(this, "DeveloperPermissionSet", {
1542
- instanceArn: this.instanceArn,
1543
- name: exports.PermissionSetType.DEVELOPER,
1544
- description: "System administrator access with expanded write permissions",
1545
- sessionDuration: cdk$1.Duration.hours(8).toIsoString(),
1715
+ });
1716
+ this.developerPermissionSet = new awsSso.CfnPermissionSet(this, "DeveloperPermissionSet", {
1717
+ // Required
1718
+ instanceArn: iamIdentityCenterArn,
1719
+ name: "Developer",
1720
+ // Optional
1721
+ description: "Administrative access with limited restrictions",
1722
+ inlinePolicy: {
1723
+ Version: "2012-10-17",
1724
+ Statement: [
1725
+ {
1726
+ Effect: "Allow",
1727
+ Action: [
1728
+ "budgets:*",
1729
+ "ce:*",
1730
+ "cloudformation:*",
1731
+ "cloudwatch:*",
1732
+ "cost-optimization-hub:*",
1733
+ "ec2:*",
1734
+ "iam:Get*",
1735
+ "iam:List*",
1736
+ "iam:PassRole",
1737
+ "lambda:*",
1738
+ "logs:*",
1739
+ "pipes:*",
1740
+ "s3:*",
1741
+ "secretsmanager:*",
1742
+ "securityhub:*",
1743
+ "servicecatalog:*",
1744
+ "sns:*",
1745
+ "sqs:*",
1746
+ "states:*",
1747
+ "tag:*",
1748
+ "xray:*",
1749
+ ],
1750
+ Resource: "*",
1751
+ },
1752
+ ],
1753
+ },
1546
1754
  managedPolicies: [
1547
1755
  awsIam.ManagedPolicy.fromAwsManagedPolicyName("AmazonQDeveloperAccess")
1548
1756
  .managedPolicyArn,
1757
+ awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
1549
1758
  awsIam.ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess")
1550
1759
  .managedPolicyArn,
1551
1760
  awsIam.ManagedPolicy.fromAwsManagedPolicyName("job-function/SystemAdministrator").managedPolicyArn,
1552
1761
  ],
1553
- inlinePolicy: mergedPolicy,
1762
+ sessionDuration: cdk$1.Duration.hours(4).toIsoString(),
1763
+ tags: [
1764
+ {
1765
+ key: cdk.CDK.TAG.SERVICE,
1766
+ value: cdk.CDK.SERVICE.SSO,
1767
+ },
1768
+ {
1769
+ key: cdk.CDK.TAG.ROLE,
1770
+ value: cdk.CDK.ROLE.SECURITY,
1771
+ },
1772
+ ],
1554
1773
  });
1555
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1556
- this.permissionSets[exports.PermissionSetType.DEVELOPER] = permissionSet;
1557
- }
1558
- /**
1559
- * Gets the permission set for the specified type
1560
- */
1561
- getPermissionSet(type) {
1562
- return this.permissionSets[type];
1774
+ // Map permission set names to their ARNs and labels
1775
+ const permissionSetMap = {
1776
+ Administrator: {
1777
+ arn: this.administratorPermissionSet.attrPermissionSetArn,
1778
+ label: "Administrator",
1779
+ },
1780
+ Analyst: {
1781
+ arn: this.analystPermissionSet.attrPermissionSetArn,
1782
+ label: "Analyst",
1783
+ },
1784
+ Developer: {
1785
+ arn: this.developerPermissionSet.attrPermissionSetArn,
1786
+ label: "Developer",
1787
+ },
1788
+ };
1789
+ //
1790
+ // Assignments
1791
+ //
1792
+ // Helper function to create assignments for a group
1793
+ const createAssignments = (groupId, accountAssignments) => {
1794
+ if (!groupId || !accountAssignments) {
1795
+ return; // Skip if group ID or assignments not provided
1796
+ }
1797
+ Object.keys(accountAssignments).forEach((accountId) => {
1798
+ const permissionSetNames = accountAssignments[accountId];
1799
+ permissionSetNames.forEach((permissionSetName) => {
1800
+ const permissionSet = permissionSetMap[permissionSetName];
1801
+ if (!permissionSet) {
1802
+ throw new cdk.ConfigurationError(`Unknown permission set: ${permissionSetName}. Valid options: ${Object.keys(permissionSetMap).join(", ")}`);
1803
+ }
1804
+ const accountAssignment = new awsSso.CfnAssignment(this, `AccountAssignment-${accountId}-${permissionSet.label}Role-${groupId}Group`, {
1805
+ // Required
1806
+ instanceArn: iamIdentityCenterArn,
1807
+ permissionSetArn: permissionSet.arn,
1808
+ principalId: groupId,
1809
+ principalType: cdk.CDK.PRINCIPAL_TYPE.GROUP,
1810
+ targetId: accountId,
1811
+ targetType: cdk.CDK.TARGET_TYPE.AWS_ACCOUNT,
1812
+ });
1813
+ cdk$1.Tags.of(accountAssignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1814
+ cdk$1.Tags.of(accountAssignment).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.SECURITY);
1815
+ });
1816
+ });
1817
+ };
1818
+ // Create assignments for each group
1819
+ createAssignments(administratorGroupId, administratorAccountAssignments);
1820
+ createAssignments(analystGroupId, analystAccountAssignments);
1821
+ createAssignments(developerGroupId, developerAccountAssignments);
1563
1822
  }
1564
- /**
1565
- * Merges default inline policies with additional user-provided policy statements
1566
- *
1567
- * @param defaultPolicy - The default policy object with Version and Statement properties
1568
- * @param additionalStatements - Optional additional policy statements to merge
1569
- * @returns The merged policy object
1570
- */
1571
- mergeInlinePolicies(defaultPolicy, additionalStatements) {
1572
- if (!additionalStatements || additionalStatements.length === 0) {
1573
- return defaultPolicy;
1823
+ }
1824
+
1825
+ //
1826
+ //
1827
+ // Constants
1828
+ //
1829
+ const DEFAULT_APPLICATION_ID = "arn:aws:serverlessrepo:us-east-2:004480582608:applications/SSOSync";
1830
+ const DEFAULT_APPLICATION_VERSION = "2.3.3";
1831
+ const DEFAULT_GOOGLE_GROUP_MATCH = "name:AWS*";
1832
+ //
1833
+ //
1834
+ // Class
1835
+ //
1836
+ class JaypieSsoSyncApplication extends constructs.Construct {
1837
+ constructor(scope, id = "SsoSyncApplication", props = {}) {
1838
+ super(scope, id);
1839
+ const { googleAdminEmail, googleAdminEmailEnvKey = "CDK_ENV_SSOSYNC_GOOGLE_ADMIN_EMAIL", googleCredentials, googleCredentialsEnvKey = "CDK_ENV_SSOSYNC_GOOGLE_CREDENTIALS", googleGroupMatch, googleGroupMatchEnvKey = "CDK_ENV_SSOSYNC_GOOGLE_GROUP_MATCH", identityStoreId, identityStoreIdEnvKey = "CDK_ENV_SSOSYNC_IDENTITY_STORE_ID", scimEndpointAccessToken, scimEndpointAccessTokenEnvKey = "CDK_ENV_SCIM_ENDPOINT_ACCESS_TOKEN", scimEndpointUrl, scimEndpointUrlEnvKey = "CDK_ENV_SSOSYNC_SCIM_ENDPOINT_URL", semanticVersion, semanticVersionEnvKey = "CDK_ENV_SSOSYNC_SEMANTIC_VERSION", ssoSyncApplicationId = DEFAULT_APPLICATION_ID, tags, } = props;
1840
+ // Resolve all values from props or environment variables
1841
+ const resolvedGoogleAdminEmail = googleAdminEmail || process.env[googleAdminEmailEnvKey];
1842
+ const resolvedGoogleCredentials = googleCredentials || process.env[googleCredentialsEnvKey];
1843
+ const resolvedGoogleGroupMatch = googleGroupMatch ||
1844
+ process.env[googleGroupMatchEnvKey] ||
1845
+ DEFAULT_GOOGLE_GROUP_MATCH;
1846
+ const resolvedIdentityStoreId = identityStoreId || process.env[identityStoreIdEnvKey];
1847
+ const resolvedScimEndpointAccessToken = scimEndpointAccessToken || process.env[scimEndpointAccessTokenEnvKey];
1848
+ const resolvedScimEndpointUrl = scimEndpointUrl || process.env[scimEndpointUrlEnvKey];
1849
+ const resolvedSemanticVersion = semanticVersion ||
1850
+ process.env[semanticVersionEnvKey] ||
1851
+ DEFAULT_APPLICATION_VERSION;
1852
+ // Validate required parameters
1853
+ const missingParams = [];
1854
+ if (!resolvedGoogleAdminEmail) {
1855
+ missingParams.push(`googleAdminEmail or ${googleAdminEmailEnvKey} environment variable`);
1574
1856
  }
1575
- // Create a deep copy of the default policy to avoid modifying the original
1576
- const mergedPolicy = JSON.parse(JSON.stringify(defaultPolicy));
1577
- // Add the additional statements to the existing statements
1578
- mergedPolicy.Statement = [
1579
- ...mergedPolicy.Statement,
1580
- ...additionalStatements,
1581
- ];
1582
- return mergedPolicy;
1583
- }
1584
- /**
1585
- * Creates assignments between permission sets, groups, and accounts
1586
- * based on the provided configuration
1587
- */
1588
- createPermissionSetAssignments(props) {
1589
- // Administrator assignments
1590
- this.assignAdministratorPermissions(props);
1591
- // Analyst assignments
1592
- this.assignAnalystPermissions(props);
1593
- // Developer assignments
1594
- this.assignDeveloperPermissions(props);
1595
- }
1596
- /**
1597
- * Assigns Administrator permissions to appropriate accounts
1598
- */
1599
- assignAdministratorPermissions(props) {
1600
- const administratorGroup = props.groupMap.administrators;
1601
- const administratorPermissionSet = this.permissionSets[exports.PermissionSetType.ADMINISTRATOR];
1602
- // Administrators get access to all accounts
1603
- const allAccounts = [
1604
- ...props.accountMap.development,
1605
- ...props.accountMap.management,
1606
- ...props.accountMap.operations,
1607
- ...props.accountMap.production,
1608
- ...props.accountMap.sandbox,
1609
- ...props.accountMap.security,
1610
- ...props.accountMap.stage,
1611
- ];
1612
- // Create assignments for each account
1613
- allAccounts.forEach((accountId, index) => {
1614
- const assignment = new sso__namespace.CfnAssignment(this, `AdministratorAssignment${index}`, {
1615
- instanceArn: this.instanceArn,
1616
- permissionSetArn: administratorPermissionSet.attrPermissionSetArn,
1617
- principalId: administratorGroup,
1618
- principalType: "GROUP",
1619
- targetId: accountId,
1620
- targetType: "AWS_ACCOUNT",
1621
- });
1622
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1623
- cdk$1.Tags.of(assignment).add("Group", "administrators");
1857
+ if (!resolvedGoogleCredentials) {
1858
+ missingParams.push(`googleCredentials or ${googleCredentialsEnvKey} environment variable`);
1859
+ }
1860
+ if (!resolvedIdentityStoreId) {
1861
+ missingParams.push(`identityStoreId or ${identityStoreIdEnvKey} environment variable`);
1862
+ }
1863
+ if (!resolvedScimEndpointAccessToken) {
1864
+ missingParams.push(`scimEndpointAccessToken or ${scimEndpointAccessTokenEnvKey} environment variable`);
1865
+ }
1866
+ if (!resolvedScimEndpointUrl) {
1867
+ missingParams.push(`scimEndpointUrl or ${scimEndpointUrlEnvKey} environment variable`);
1868
+ }
1869
+ if (missingParams.length > 0) {
1870
+ throw new errors.ConfigurationError(`JaypieSsoSyncApplication missing required configuration: ${missingParams.join(", ")}`);
1871
+ }
1872
+ // Create the SSO Sync Application
1873
+ // Type assertion is safe because we validated all required values above
1874
+ this._application = new awsSam.CfnApplication(this, "Application", {
1875
+ location: {
1876
+ applicationId: ssoSyncApplicationId,
1877
+ semanticVersion: resolvedSemanticVersion,
1878
+ },
1879
+ parameters: {
1880
+ GoogleAdminEmail: resolvedGoogleAdminEmail,
1881
+ GoogleCredentials: resolvedGoogleCredentials,
1882
+ GoogleGroupMatch: resolvedGoogleGroupMatch,
1883
+ IdentityStoreID: resolvedIdentityStoreId,
1884
+ Region: cdk$1.Stack.of(this).region,
1885
+ SCIMEndpointAccessToken: resolvedScimEndpointAccessToken,
1886
+ SCIMEndpointUrl: resolvedScimEndpointUrl,
1887
+ },
1624
1888
  });
1625
- }
1626
- /**
1627
- * Assigns Analyst permissions to appropriate accounts
1628
- */
1629
- assignAnalystPermissions(props) {
1630
- const analystGroup = props.groupMap.analysts;
1631
- const analystPermissionSet = this.permissionSets[exports.PermissionSetType.ANALYST];
1632
- // Analysts get access to development, management, sandbox, and stage accounts
1633
- const analystAccounts = [
1634
- ...props.accountMap.development,
1635
- ...props.accountMap.management,
1636
- ...props.accountMap.sandbox,
1637
- ...props.accountMap.stage,
1638
- ];
1639
- // Create assignments for each account
1640
- analystAccounts.forEach((accountId, index) => {
1641
- const assignment = new sso__namespace.CfnAssignment(this, `AnalystAssignment${index}`, {
1642
- instanceArn: this.instanceArn,
1643
- permissionSetArn: analystPermissionSet.attrPermissionSetArn,
1644
- principalId: analystGroup,
1645
- principalType: "GROUP",
1646
- targetId: accountId,
1647
- targetType: "AWS_ACCOUNT",
1648
- });
1649
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1650
- cdk$1.Tags.of(assignment).add("Group", "analysts");
1889
+ // Add tags
1890
+ const defaultTags = {
1891
+ [cdk.CDK.TAG.ROLE]: cdk.CDK.ROLE.SECURITY,
1892
+ };
1893
+ const allTags = { ...defaultTags, ...tags };
1894
+ Object.entries(allTags).forEach(([key, value]) => {
1895
+ cdk$1.Tags.of(this._application).add(key, value);
1651
1896
  });
1652
1897
  }
1653
- /**
1654
- * Assigns Developer permissions to appropriate accounts
1655
- */
1656
- assignDeveloperPermissions(props) {
1657
- const developerGroup = props.groupMap.developers;
1658
- const developerPermissionSet = this.permissionSets[exports.PermissionSetType.DEVELOPER];
1659
- // Developers get access to development, sandbox, and stage accounts
1660
- const developerAccounts = [
1661
- ...props.accountMap.development,
1662
- ...props.accountMap.sandbox,
1663
- ...props.accountMap.stage,
1664
- ];
1665
- // Create assignments for each account
1666
- developerAccounts.forEach((accountId, index) => {
1667
- const assignment = new sso__namespace.CfnAssignment(this, `DeveloperAssignment${index}`, {
1668
- instanceArn: this.instanceArn,
1669
- permissionSetArn: developerPermissionSet.attrPermissionSetArn,
1670
- principalId: developerGroup,
1671
- principalType: "GROUP",
1672
- targetId: accountId,
1673
- targetType: "AWS_ACCOUNT",
1674
- });
1675
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1676
- cdk$1.Tags.of(assignment).add("Group", "developers");
1677
- });
1898
+ get application() {
1899
+ return this._application;
1678
1900
  }
1679
1901
  }
1680
1902
 
@@ -1936,21 +2158,34 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1936
2158
  applyRemovalPolicy(policy) {
1937
2159
  this.bucket.applyRemovalPolicy(policy);
1938
2160
  }
2161
+ get bucketRef() {
2162
+ return {
2163
+ bucketArn: this.bucket.bucketArn,
2164
+ bucketName: this.bucket.bucketName,
2165
+ };
2166
+ }
1939
2167
  }
1940
2168
 
2169
+ Object.defineProperty(exports, "CDK", {
2170
+ enumerable: true,
2171
+ get: function () { return cdk.CDK; }
2172
+ });
1941
2173
  exports.JaypieApiGateway = JaypieApiGateway;
1942
2174
  exports.JaypieAppStack = JaypieAppStack;
1943
2175
  exports.JaypieBucketQueuedLambda = JaypieBucketQueuedLambda;
1944
2176
  exports.JaypieDatadogSecret = JaypieDatadogSecret;
2177
+ exports.JaypieDnsRecord = JaypieDnsRecord;
1945
2178
  exports.JaypieEnvSecret = JaypieEnvSecret;
1946
2179
  exports.JaypieExpressLambda = JaypieExpressLambda;
2180
+ exports.JaypieGitHubDeployRole = JaypieGitHubDeployRole;
1947
2181
  exports.JaypieHostedZone = JaypieHostedZone;
1948
2182
  exports.JaypieInfrastructureStack = JaypieInfrastructureStack;
1949
2183
  exports.JaypieLambda = JaypieLambda;
1950
2184
  exports.JaypieMongoDbSecret = JaypieMongoDbSecret;
1951
2185
  exports.JaypieOpenAiSecret = JaypieOpenAiSecret;
1952
2186
  exports.JaypieQueuedLambda = JaypieQueuedLambda;
1953
- exports.JaypieSsoGroups = JaypieSsoGroups;
2187
+ exports.JaypieSsoPermissions = JaypieSsoPermissions;
2188
+ exports.JaypieSsoSyncApplication = JaypieSsoSyncApplication;
1954
2189
  exports.JaypieStack = JaypieStack;
1955
2190
  exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
1956
2191
  exports.JaypieWebDeploymentBucket = JaypieWebDeploymentBucket;
@@ -1963,7 +2198,9 @@ exports.isEnv = isEnv;
1963
2198
  exports.isProductionEnv = isProductionEnv;
1964
2199
  exports.isSandboxEnv = isSandboxEnv;
1965
2200
  exports.jaypieLambdaEnv = jaypieLambdaEnv;
2201
+ exports.resolveDatadogForwarderFunction = resolveDatadogForwarderFunction;
1966
2202
  exports.resolveDatadogLayers = resolveDatadogLayers;
2203
+ exports.resolveDatadogLoggingDestination = resolveDatadogLoggingDestination;
1967
2204
  exports.resolveHostedZone = resolveHostedZone;
1968
2205
  exports.resolveParamsAndSecrets = resolveParamsAndSecrets;
1969
2206
  //# sourceMappingURL=index.cjs.map