@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.
- package/dist/cjs/JaypieApiGateway.d.ts +1 -0
- package/dist/cjs/JaypieBucketQueuedLambda.d.ts +4 -19
- package/dist/cjs/JaypieDnsRecord.d.ts +45 -0
- package/dist/cjs/JaypieGitHubDeployRole.d.ts +14 -0
- package/dist/cjs/JaypieHostedZone.d.ts +26 -4
- package/dist/cjs/JaypieLambda.d.ts +1 -1
- package/dist/cjs/JaypieQueuedLambda.d.ts +1 -1
- package/dist/cjs/JaypieSsoPermissions.d.ts +96 -0
- package/dist/cjs/JaypieSsoSyncApplication.d.ts +27 -0
- package/dist/cjs/JaypieWebDeploymentBucket.d.ts +1 -0
- package/dist/cjs/__tests__/JaypieSsoSyncApplication.spec.d.ts +1 -0
- package/dist/cjs/helpers/__tests__/resolveDatadogForwarderFunction.spec.d.ts +1 -0
- package/dist/cjs/helpers/__tests__/resolveDatadogLoggingDestination.spec.d.ts +1 -0
- package/dist/cjs/helpers/index.d.ts +2 -0
- package/dist/cjs/helpers/resolveDatadogForwarderFunction.d.ts +7 -0
- package/dist/cjs/helpers/resolveDatadogLoggingDestination.d.ts +4 -0
- package/dist/cjs/index.cjs +592 -355
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +6 -2
- package/dist/esm/JaypieApiGateway.d.ts +1 -0
- package/dist/esm/JaypieBucketQueuedLambda.d.ts +4 -19
- package/dist/esm/JaypieDnsRecord.d.ts +45 -0
- package/dist/esm/JaypieGitHubDeployRole.d.ts +14 -0
- package/dist/esm/JaypieHostedZone.d.ts +26 -4
- package/dist/esm/JaypieLambda.d.ts +1 -1
- package/dist/esm/JaypieQueuedLambda.d.ts +1 -1
- package/dist/esm/JaypieSsoPermissions.d.ts +96 -0
- package/dist/esm/JaypieSsoSyncApplication.d.ts +27 -0
- package/dist/esm/JaypieWebDeploymentBucket.d.ts +1 -0
- package/dist/esm/__tests__/JaypieDnsRecord.spec.d.ts +1 -0
- package/dist/esm/__tests__/JaypieSsoPermissions.spec.d.ts +1 -0
- package/dist/esm/__tests__/JaypieSsoSyncApplication.spec.d.ts +1 -0
- package/dist/esm/helpers/__tests__/resolveDatadogForwarderFunction.spec.d.ts +1 -0
- package/dist/esm/helpers/__tests__/resolveDatadogLoggingDestination.spec.d.ts +1 -0
- package/dist/esm/helpers/index.d.ts +2 -0
- package/dist/esm/helpers/resolveDatadogForwarderFunction.d.ts +7 -0
- package/dist/esm/helpers/resolveDatadogLoggingDestination.d.ts +4 -0
- package/dist/esm/index.d.ts +6 -2
- package/dist/esm/index.js +585 -356
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/cjs/JaypieSsoGroups.d.ts +0 -121
- package/dist/esm/JaypieSsoGroups.d.ts +0 -121
- /package/dist/cjs/__tests__/{JaypieSsoGroups.spec.d.ts → JaypieDnsRecord.spec.d.ts} +0 -0
- /package/dist/{esm/__tests__/JaypieSsoGroups.spec.d.ts → cjs/__tests__/JaypieSsoPermissions.spec.d.ts} +0 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
1049
|
-
|
|
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
|
-
|
|
1092
|
-
|
|
1115
|
+
addReplicationPolicy(policy) {
|
|
1116
|
+
this._bucket.addReplicationPolicy(policy);
|
|
1093
1117
|
}
|
|
1094
|
-
|
|
1095
|
-
return
|
|
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 {
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
//
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
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
|
-
|
|
1387
|
-
|
|
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
|
-
|
|
1421
|
-
|
|
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
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
description: "Read-only access
|
|
1479
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1501
|
-
|
|
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
|
-
|
|
1528
|
-
|
|
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
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
description: "
|
|
1545
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
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
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
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
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
//
|
|
1592
|
-
this.
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
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
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
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
|
-
|
|
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.
|
|
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
|