@jaypie/constructs 1.1.49 → 1.1.50
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 +15 -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 +95 -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 +589 -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 +15 -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 +95 -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 +582 -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,164 @@ 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 { accountId, oidcProviderArn = cdk$1.Fn.importValue(cdk.CDK.IMPORT.OIDC_PROVIDER), output = true, repoRestriction: propsRepoRestriction, } = props;
|
|
1358
|
+
// Resolve repoRestriction from props or environment variables
|
|
1359
|
+
let repoRestriction = propsRepoRestriction;
|
|
1360
|
+
if (!repoRestriction) {
|
|
1361
|
+
const envRepo = process.env.CDK_ENV_REPO || process.env.PROJECT_REPO;
|
|
1362
|
+
if (!envRepo) {
|
|
1363
|
+
throw new cdk.ConfigurationError("No repoRestriction provided. Set repoRestriction prop, CDK_ENV_REPO, or PROJECT_REPO environment variable");
|
|
1364
|
+
}
|
|
1365
|
+
// Extract organization from owner/repo format and create org-wide restriction
|
|
1366
|
+
const organization = envRepo.split("/")[0];
|
|
1367
|
+
repoRestriction = `repo:${organization}/*:*`;
|
|
1368
|
+
}
|
|
1369
|
+
// Create the IAM role
|
|
1370
|
+
this._role = new awsIam.Role(this, "GitHubActionsRole", {
|
|
1371
|
+
assumedBy: new awsIam.FederatedPrincipal(oidcProviderArn, {
|
|
1372
|
+
StringLike: {
|
|
1373
|
+
"token.actions.githubusercontent.com:sub": repoRestriction,
|
|
1374
|
+
},
|
|
1375
|
+
}, "sts:AssumeRoleWithWebIdentity"),
|
|
1376
|
+
maxSessionDuration: cdk$1.Duration.hours(1),
|
|
1377
|
+
path: "/",
|
|
1378
|
+
});
|
|
1379
|
+
cdk$1.Tags.of(this._role).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.DEPLOY);
|
|
1380
|
+
// Allow the role to access the GitHub OIDC provider
|
|
1381
|
+
this._role.addToPolicy(new awsIam.PolicyStatement({
|
|
1382
|
+
actions: ["sts:AssumeRoleWithWebIdentity"],
|
|
1383
|
+
resources: [`arn:aws:iam::${accountId}:oidc-provider/*`],
|
|
1384
|
+
}));
|
|
1385
|
+
// Allow the role to deploy CDK apps
|
|
1386
|
+
this._role.addToPolicy(new awsIam.PolicyStatement({
|
|
1387
|
+
actions: [
|
|
1388
|
+
"cloudformation:CreateStack",
|
|
1389
|
+
"cloudformation:DeleteStack",
|
|
1390
|
+
"cloudformation:DescribeStackEvents",
|
|
1391
|
+
"cloudformation:DescribeStackResource",
|
|
1392
|
+
"cloudformation:DescribeStackResources",
|
|
1393
|
+
"cloudformation:DescribeStacks",
|
|
1394
|
+
"cloudformation:GetTemplate",
|
|
1395
|
+
"cloudformation:SetStackPolicy",
|
|
1396
|
+
"cloudformation:UpdateStack",
|
|
1397
|
+
"cloudformation:ValidateTemplate",
|
|
1398
|
+
"iam:PassRole",
|
|
1399
|
+
"route53:ListHostedZones*",
|
|
1400
|
+
"s3:GetObject",
|
|
1401
|
+
"s3:ListBucket",
|
|
1402
|
+
],
|
|
1403
|
+
effect: awsIam.Effect.ALLOW,
|
|
1404
|
+
resources: ["*"],
|
|
1405
|
+
}));
|
|
1406
|
+
this._role.addToPolicy(new awsIam.PolicyStatement({
|
|
1407
|
+
actions: ["iam:PassRole", "sts:AssumeRole"],
|
|
1408
|
+
effect: awsIam.Effect.ALLOW,
|
|
1409
|
+
resources: [
|
|
1410
|
+
"arn:aws:iam::*:role/cdk-hnb659fds-deploy-role-*",
|
|
1411
|
+
"arn:aws:iam::*:role/cdk-hnb659fds-file-publishing-*",
|
|
1412
|
+
"arn:aws:iam::*:role/cdk-readOnlyRole",
|
|
1413
|
+
],
|
|
1414
|
+
}));
|
|
1415
|
+
// Export the ARN of the role
|
|
1416
|
+
if (output !== false) {
|
|
1417
|
+
const outputId = typeof output === "string" ? output : "GitHubActionsRoleArn";
|
|
1418
|
+
new cdk$1.CfnOutput(this, outputId, {
|
|
1419
|
+
value: this._role.roleArn,
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
get role() {
|
|
1424
|
+
return this._role;
|
|
1425
|
+
}
|
|
1426
|
+
get roleArn() {
|
|
1427
|
+
return this._role.roleArn;
|
|
1428
|
+
}
|
|
1429
|
+
get roleName() {
|
|
1430
|
+
return this._role.roleName;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1249
1434
|
class JaypieExpressLambda extends JaypieLambda {
|
|
1250
1435
|
constructor(scope, id, props) {
|
|
1251
1436
|
super(scope, id, {
|
|
@@ -1261,11 +1446,12 @@ const SERVICE = {
|
|
|
1261
1446
|
};
|
|
1262
1447
|
class JaypieHostedZone extends constructs.Construct {
|
|
1263
1448
|
/**
|
|
1264
|
-
* Create a new hosted zone with query logging
|
|
1449
|
+
* Create a new hosted zone with query logging and optional DNS records
|
|
1265
1450
|
*/
|
|
1266
1451
|
constructor(scope, id, props) {
|
|
1267
1452
|
super(scope, id);
|
|
1268
|
-
const {
|
|
1453
|
+
const { zoneName, project } = props;
|
|
1454
|
+
const destination = props.destination ?? true;
|
|
1269
1455
|
const service = props.service || cdk.CDK.SERVICE.INFRASTRUCTURE;
|
|
1270
1456
|
// Create the log group
|
|
1271
1457
|
this.logGroup = new awsLogs.LogGroup(this, "LogGroup", {
|
|
@@ -1282,10 +1468,13 @@ class JaypieHostedZone extends constructs.Construct {
|
|
|
1282
1468
|
}
|
|
1283
1469
|
// Grant Route 53 permissions to write to the log group
|
|
1284
1470
|
this.logGroup.grantWrite(new awsIam.ServicePrincipal(SERVICE.ROUTE53));
|
|
1285
|
-
// Add destination
|
|
1286
|
-
if (destination) {
|
|
1471
|
+
// Add destination based on configuration
|
|
1472
|
+
if (destination !== false) {
|
|
1473
|
+
const lambdaDestination = destination === true
|
|
1474
|
+
? resolveDatadogLoggingDestination(scope)
|
|
1475
|
+
: destination;
|
|
1287
1476
|
this.logGroup.addSubscriptionFilter("DatadogLambdaDestination", {
|
|
1288
|
-
destination,
|
|
1477
|
+
destination: lambdaDestination,
|
|
1289
1478
|
filterPattern: awsLogs.FilterPattern.allEvents(),
|
|
1290
1479
|
});
|
|
1291
1480
|
}
|
|
@@ -1300,6 +1489,21 @@ class JaypieHostedZone extends constructs.Construct {
|
|
|
1300
1489
|
if (project) {
|
|
1301
1490
|
cdk__namespace.Tags.of(this.hostedZone).add(cdk.CDK.TAG.PROJECT, project);
|
|
1302
1491
|
}
|
|
1492
|
+
// Create DNS records if provided
|
|
1493
|
+
this.dnsRecords = [];
|
|
1494
|
+
if (props.records) {
|
|
1495
|
+
props.records.forEach((recordConfig, index) => {
|
|
1496
|
+
const { id, ...recordProps } = recordConfig;
|
|
1497
|
+
// Generate a default ID if not provided
|
|
1498
|
+
const recordId = id ||
|
|
1499
|
+
`${recordProps.type}${recordProps.recordName ? `-${recordProps.recordName}` : ""}-${index}`;
|
|
1500
|
+
const dnsRecord = new JaypieDnsRecord(this, recordId, {
|
|
1501
|
+
...recordProps,
|
|
1502
|
+
zone: this.hostedZone,
|
|
1503
|
+
});
|
|
1504
|
+
this.dnsRecords.push(dnsRecord);
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1303
1507
|
}
|
|
1304
1508
|
}
|
|
1305
1509
|
|
|
@@ -1348,333 +1552,348 @@ class JaypieOpenAiSecret extends JaypieEnvSecret {
|
|
|
1348
1552
|
}
|
|
1349
1553
|
|
|
1350
1554
|
/**
|
|
1351
|
-
*
|
|
1555
|
+
* JaypieSsoPermissions Construct
|
|
1556
|
+
*
|
|
1557
|
+
* Creates and manages AWS IAM Identity Center (SSO) permission sets and assignments
|
|
1558
|
+
*
|
|
1559
|
+
* @example
|
|
1560
|
+
* const permissionSets = new JaypieSsoPermissions(this, "PermissionSets", {
|
|
1561
|
+
* iamIdentityCenterArn: "arn:aws:sso:::instance/...",
|
|
1562
|
+
* administratorGroupId: "b4c8b438-4031-7000-782d-5046945fb956",
|
|
1563
|
+
* analystGroupId: "2488f4e8-d061-708e-abe1-c315f0e30005",
|
|
1564
|
+
* developerGroupId: "b438a4f8-e0e1-707c-c6e8-21841daf9ad1",
|
|
1565
|
+
* administratorAccountAssignments: {
|
|
1566
|
+
* "211125635435": ["Administrator", "Analyst", "Developer"],
|
|
1567
|
+
* "381492033431": ["Administrator", "Analyst"],
|
|
1568
|
+
* },
|
|
1569
|
+
* analystAccountAssignments: {
|
|
1570
|
+
* "211125635435": ["Analyst", "Developer"],
|
|
1571
|
+
* "381492033431": [],
|
|
1572
|
+
* },
|
|
1573
|
+
* developerAccountAssignments: {
|
|
1574
|
+
* "211125635435": ["Analyst", "Developer"],
|
|
1575
|
+
* "381492033431": [],
|
|
1576
|
+
* },
|
|
1577
|
+
* });
|
|
1352
1578
|
*/
|
|
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 {
|
|
1579
|
+
class JaypieSsoPermissions extends constructs.Construct {
|
|
1365
1580
|
constructor(scope, id, props) {
|
|
1366
1581
|
super(scope, id);
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
//
|
|
1375
|
-
this.
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1582
|
+
const { iamIdentityCenterArn, administratorGroupId, analystGroupId, developerGroupId, administratorAccountAssignments, analystAccountAssignments, developerAccountAssignments, } = props;
|
|
1583
|
+
if (!iamIdentityCenterArn) {
|
|
1584
|
+
// If no IAM Identity Center ARN provided, skip SSO setup
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
//
|
|
1588
|
+
// Permission Sets
|
|
1589
|
+
//
|
|
1590
|
+
this.administratorPermissionSet = new awsSso.CfnPermissionSet(this, "AdministratorPermissionSet", {
|
|
1591
|
+
// Required
|
|
1592
|
+
instanceArn: iamIdentityCenterArn,
|
|
1593
|
+
name: "Administrator",
|
|
1594
|
+
// Optional
|
|
1595
|
+
description: "Unrestricted access",
|
|
1596
|
+
inlinePolicy: {
|
|
1597
|
+
Version: "2012-10-17",
|
|
1598
|
+
Statement: [
|
|
1599
|
+
{
|
|
1600
|
+
Effect: "Allow",
|
|
1601
|
+
Action: [
|
|
1602
|
+
"aws-portal:ViewUsage",
|
|
1603
|
+
"aws-portal:ViewBilling",
|
|
1604
|
+
"budgets:*",
|
|
1605
|
+
"cur:DescribeReportDefinitions",
|
|
1606
|
+
"cur:PutReportDefinition",
|
|
1607
|
+
"cur:DeleteReportDefinition",
|
|
1608
|
+
"cur:ModifyReportDefinition",
|
|
1609
|
+
],
|
|
1610
|
+
Resource: "*",
|
|
1611
|
+
},
|
|
1612
|
+
],
|
|
1613
|
+
},
|
|
1614
|
+
managedPolicies: [
|
|
1615
|
+
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AdministratorAccess")
|
|
1616
|
+
.managedPolicyArn,
|
|
1617
|
+
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
|
|
1618
|
+
],
|
|
1619
|
+
sessionDuration: cdk$1.Duration.hours(1).toIsoString(),
|
|
1620
|
+
tags: [
|
|
1385
1621
|
{
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
"aws-portal:*",
|
|
1389
|
-
"budgets:*",
|
|
1390
|
-
"ce:*",
|
|
1391
|
-
"cost-optimization-hub:*",
|
|
1392
|
-
"cur:*",
|
|
1393
|
-
],
|
|
1394
|
-
Resource: "*",
|
|
1622
|
+
key: cdk.CDK.TAG.SERVICE,
|
|
1623
|
+
value: cdk.CDK.SERVICE.SSO,
|
|
1395
1624
|
},
|
|
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
1625
|
{
|
|
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: "*",
|
|
1626
|
+
key: cdk.CDK.TAG.ROLE,
|
|
1627
|
+
value: cdk.CDK.ROLE.SECURITY,
|
|
1470
1628
|
},
|
|
1471
1629
|
],
|
|
1472
|
-
};
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
description: "Read-only access
|
|
1479
|
-
|
|
1630
|
+
});
|
|
1631
|
+
this.analystPermissionSet = new awsSso.CfnPermissionSet(this, "AnalystPermissionSet", {
|
|
1632
|
+
// Required
|
|
1633
|
+
instanceArn: iamIdentityCenterArn,
|
|
1634
|
+
name: "Analyst",
|
|
1635
|
+
// Optional
|
|
1636
|
+
description: "Read-only access; may expand to limited write access",
|
|
1637
|
+
inlinePolicy: {
|
|
1638
|
+
Version: "2012-10-17",
|
|
1639
|
+
Statement: [
|
|
1640
|
+
{
|
|
1641
|
+
Effect: "Allow",
|
|
1642
|
+
Action: [
|
|
1643
|
+
"aws-portal:ViewUsage",
|
|
1644
|
+
"aws-portal:ViewBilling",
|
|
1645
|
+
"budgets:Describe*",
|
|
1646
|
+
"budgets:View*",
|
|
1647
|
+
"ce:Get*",
|
|
1648
|
+
"ce:List*",
|
|
1649
|
+
"cloudformation:Describe*",
|
|
1650
|
+
"cloudformation:Get*",
|
|
1651
|
+
"cloudformation:List*",
|
|
1652
|
+
"cloudwatch:BatchGet*",
|
|
1653
|
+
"cloudwatch:Get*",
|
|
1654
|
+
"cloudwatch:List*",
|
|
1655
|
+
"cost-optimization-hub:Get*",
|
|
1656
|
+
"cost-optimization-hub:List*",
|
|
1657
|
+
"ec2:Describe*",
|
|
1658
|
+
"ec2:Get*",
|
|
1659
|
+
"ec2:List*",
|
|
1660
|
+
"ec2:Search*",
|
|
1661
|
+
"iam:Get*",
|
|
1662
|
+
"iam:List*",
|
|
1663
|
+
"iam:PassRole",
|
|
1664
|
+
"lambda:Get*",
|
|
1665
|
+
"lambda:List*",
|
|
1666
|
+
"logs:Describe*",
|
|
1667
|
+
"logs:Get*",
|
|
1668
|
+
"logs:List*",
|
|
1669
|
+
"pipes:Describe*",
|
|
1670
|
+
"pipes:List*",
|
|
1671
|
+
"s3:Get*",
|
|
1672
|
+
"s3:List*",
|
|
1673
|
+
"secretsmanager:GetRandomPassword",
|
|
1674
|
+
"secretsmanager:GetResourcePolicy",
|
|
1675
|
+
"secretsmanager:List*",
|
|
1676
|
+
"securityhub:Describe*",
|
|
1677
|
+
"securityhub:Get*",
|
|
1678
|
+
"securityhub:List*",
|
|
1679
|
+
"servicecatalog:Describe*",
|
|
1680
|
+
"sns:Get*",
|
|
1681
|
+
"sns:List*",
|
|
1682
|
+
"sqs:Get*",
|
|
1683
|
+
"sqs:List*",
|
|
1684
|
+
"states:Describe*",
|
|
1685
|
+
"states:Get*",
|
|
1686
|
+
"states:List*",
|
|
1687
|
+
"tag:*",
|
|
1688
|
+
"xray:*",
|
|
1689
|
+
],
|
|
1690
|
+
Resource: "*",
|
|
1691
|
+
},
|
|
1692
|
+
],
|
|
1693
|
+
},
|
|
1480
1694
|
managedPolicies: [
|
|
1481
1695
|
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AmazonQDeveloperAccess")
|
|
1482
1696
|
.managedPolicyArn,
|
|
1697
|
+
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
|
|
1483
1698
|
awsIam.ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess")
|
|
1484
1699
|
.managedPolicyArn,
|
|
1485
1700
|
],
|
|
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: [
|
|
1701
|
+
sessionDuration: cdk$1.Duration.hours(12).toIsoString(),
|
|
1702
|
+
tags: [
|
|
1499
1703
|
{
|
|
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: "*",
|
|
1704
|
+
key: cdk.CDK.TAG.SERVICE,
|
|
1705
|
+
value: cdk.CDK.SERVICE.SSO,
|
|
1525
1706
|
},
|
|
1526
1707
|
{
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
"iam:*User*",
|
|
1530
|
-
"iam:*Role*",
|
|
1531
|
-
"iam:*Policy*",
|
|
1532
|
-
"organizations:*",
|
|
1533
|
-
"account:*",
|
|
1534
|
-
],
|
|
1535
|
-
Resource: "*",
|
|
1708
|
+
key: cdk.CDK.TAG.ROLE,
|
|
1709
|
+
value: cdk.CDK.ROLE.SECURITY,
|
|
1536
1710
|
},
|
|
1537
1711
|
],
|
|
1538
|
-
};
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
description: "
|
|
1545
|
-
|
|
1712
|
+
});
|
|
1713
|
+
this.developerPermissionSet = new awsSso.CfnPermissionSet(this, "DeveloperPermissionSet", {
|
|
1714
|
+
// Required
|
|
1715
|
+
instanceArn: iamIdentityCenterArn,
|
|
1716
|
+
name: "Developer",
|
|
1717
|
+
// Optional
|
|
1718
|
+
description: "Administrative access with limited restrictions",
|
|
1719
|
+
inlinePolicy: {
|
|
1720
|
+
Version: "2012-10-17",
|
|
1721
|
+
Statement: [
|
|
1722
|
+
{
|
|
1723
|
+
Effect: "Allow",
|
|
1724
|
+
Action: [
|
|
1725
|
+
"budgets:*",
|
|
1726
|
+
"ce:*",
|
|
1727
|
+
"cloudformation:*",
|
|
1728
|
+
"cloudwatch:*",
|
|
1729
|
+
"cost-optimization-hub:*",
|
|
1730
|
+
"ec2:*",
|
|
1731
|
+
"iam:Get*",
|
|
1732
|
+
"iam:List*",
|
|
1733
|
+
"iam:PassRole",
|
|
1734
|
+
"lambda:*",
|
|
1735
|
+
"logs:*",
|
|
1736
|
+
"pipes:*",
|
|
1737
|
+
"s3:*",
|
|
1738
|
+
"secretsmanager:*",
|
|
1739
|
+
"securityhub:*",
|
|
1740
|
+
"servicecatalog:*",
|
|
1741
|
+
"sns:*",
|
|
1742
|
+
"sqs:*",
|
|
1743
|
+
"states:*",
|
|
1744
|
+
"tag:*",
|
|
1745
|
+
"xray:*",
|
|
1746
|
+
],
|
|
1747
|
+
Resource: "*",
|
|
1748
|
+
},
|
|
1749
|
+
],
|
|
1750
|
+
},
|
|
1546
1751
|
managedPolicies: [
|
|
1547
1752
|
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AmazonQDeveloperAccess")
|
|
1548
1753
|
.managedPolicyArn,
|
|
1754
|
+
awsIam.ManagedPolicy.fromAwsManagedPolicyName("AWSManagementConsoleBasicUserAccess").managedPolicyArn,
|
|
1549
1755
|
awsIam.ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess")
|
|
1550
1756
|
.managedPolicyArn,
|
|
1551
1757
|
awsIam.ManagedPolicy.fromAwsManagedPolicyName("job-function/SystemAdministrator").managedPolicyArn,
|
|
1552
1758
|
],
|
|
1553
|
-
|
|
1759
|
+
sessionDuration: cdk$1.Duration.hours(4).toIsoString(),
|
|
1760
|
+
tags: [
|
|
1761
|
+
{
|
|
1762
|
+
key: cdk.CDK.TAG.SERVICE,
|
|
1763
|
+
value: cdk.CDK.SERVICE.SSO,
|
|
1764
|
+
},
|
|
1765
|
+
{
|
|
1766
|
+
key: cdk.CDK.TAG.ROLE,
|
|
1767
|
+
value: cdk.CDK.ROLE.SECURITY,
|
|
1768
|
+
},
|
|
1769
|
+
],
|
|
1554
1770
|
});
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1771
|
+
// Map permission set names to their ARNs and labels
|
|
1772
|
+
const permissionSetMap = {
|
|
1773
|
+
Administrator: {
|
|
1774
|
+
arn: this.administratorPermissionSet.attrPermissionSetArn,
|
|
1775
|
+
label: "Administrator",
|
|
1776
|
+
},
|
|
1777
|
+
Analyst: {
|
|
1778
|
+
arn: this.analystPermissionSet.attrPermissionSetArn,
|
|
1779
|
+
label: "Analyst",
|
|
1780
|
+
},
|
|
1781
|
+
Developer: {
|
|
1782
|
+
arn: this.developerPermissionSet.attrPermissionSetArn,
|
|
1783
|
+
label: "Developer",
|
|
1784
|
+
},
|
|
1785
|
+
};
|
|
1786
|
+
//
|
|
1787
|
+
// Assignments
|
|
1788
|
+
//
|
|
1789
|
+
// Helper function to create assignments for a group
|
|
1790
|
+
const createAssignments = (groupId, accountAssignments) => {
|
|
1791
|
+
if (!groupId || !accountAssignments) {
|
|
1792
|
+
return; // Skip if group ID or assignments not provided
|
|
1793
|
+
}
|
|
1794
|
+
Object.keys(accountAssignments).forEach((accountId) => {
|
|
1795
|
+
const permissionSetNames = accountAssignments[accountId];
|
|
1796
|
+
permissionSetNames.forEach((permissionSetName) => {
|
|
1797
|
+
const permissionSet = permissionSetMap[permissionSetName];
|
|
1798
|
+
if (!permissionSet) {
|
|
1799
|
+
throw new cdk.ConfigurationError(`Unknown permission set: ${permissionSetName}. Valid options: ${Object.keys(permissionSetMap).join(", ")}`);
|
|
1800
|
+
}
|
|
1801
|
+
const accountAssignment = new awsSso.CfnAssignment(this, `AccountAssignment-${accountId}-${permissionSet.label}Role-${groupId}Group`, {
|
|
1802
|
+
// Required
|
|
1803
|
+
instanceArn: iamIdentityCenterArn,
|
|
1804
|
+
permissionSetArn: permissionSet.arn,
|
|
1805
|
+
principalId: groupId,
|
|
1806
|
+
principalType: cdk.CDK.PRINCIPAL_TYPE.GROUP,
|
|
1807
|
+
targetId: accountId,
|
|
1808
|
+
targetType: cdk.CDK.TARGET_TYPE.AWS_ACCOUNT,
|
|
1809
|
+
});
|
|
1810
|
+
cdk$1.Tags.of(accountAssignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
|
|
1811
|
+
cdk$1.Tags.of(accountAssignment).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.SECURITY);
|
|
1812
|
+
});
|
|
1813
|
+
});
|
|
1814
|
+
};
|
|
1815
|
+
// Create assignments for each group
|
|
1816
|
+
createAssignments(administratorGroupId, administratorAccountAssignments);
|
|
1817
|
+
createAssignments(analystGroupId, analystAccountAssignments);
|
|
1818
|
+
createAssignments(developerGroupId, developerAccountAssignments);
|
|
1563
1819
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
//
|
|
1823
|
+
//
|
|
1824
|
+
// Constants
|
|
1825
|
+
//
|
|
1826
|
+
const DEFAULT_APPLICATION_ID = "arn:aws:serverlessrepo:us-east-2:004480582608:applications/SSOSync";
|
|
1827
|
+
const DEFAULT_APPLICATION_VERSION = "2.3.3";
|
|
1828
|
+
const DEFAULT_GOOGLE_GROUP_MATCH = "name:AWS*";
|
|
1829
|
+
//
|
|
1830
|
+
//
|
|
1831
|
+
// Class
|
|
1832
|
+
//
|
|
1833
|
+
class JaypieSsoSyncApplication extends constructs.Construct {
|
|
1834
|
+
constructor(scope, id = "SSOSyncApplication", props = {}) {
|
|
1835
|
+
super(scope, id);
|
|
1836
|
+
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;
|
|
1837
|
+
// Resolve all values from props or environment variables
|
|
1838
|
+
const resolvedGoogleAdminEmail = googleAdminEmail || process.env[googleAdminEmailEnvKey];
|
|
1839
|
+
const resolvedGoogleCredentials = googleCredentials || process.env[googleCredentialsEnvKey];
|
|
1840
|
+
const resolvedGoogleGroupMatch = googleGroupMatch ||
|
|
1841
|
+
process.env[googleGroupMatchEnvKey] ||
|
|
1842
|
+
DEFAULT_GOOGLE_GROUP_MATCH;
|
|
1843
|
+
const resolvedIdentityStoreId = identityStoreId || process.env[identityStoreIdEnvKey];
|
|
1844
|
+
const resolvedScimEndpointAccessToken = scimEndpointAccessToken || process.env[scimEndpointAccessTokenEnvKey];
|
|
1845
|
+
const resolvedScimEndpointUrl = scimEndpointUrl || process.env[scimEndpointUrlEnvKey];
|
|
1846
|
+
const resolvedSemanticVersion = semanticVersion ||
|
|
1847
|
+
process.env[semanticVersionEnvKey] ||
|
|
1848
|
+
DEFAULT_APPLICATION_VERSION;
|
|
1849
|
+
// Validate required parameters
|
|
1850
|
+
const missingParams = [];
|
|
1851
|
+
if (!resolvedGoogleAdminEmail) {
|
|
1852
|
+
missingParams.push(`googleAdminEmail or ${googleAdminEmailEnvKey} environment variable`);
|
|
1574
1853
|
}
|
|
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");
|
|
1854
|
+
if (!resolvedGoogleCredentials) {
|
|
1855
|
+
missingParams.push(`googleCredentials or ${googleCredentialsEnvKey} environment variable`);
|
|
1856
|
+
}
|
|
1857
|
+
if (!resolvedIdentityStoreId) {
|
|
1858
|
+
missingParams.push(`identityStoreId or ${identityStoreIdEnvKey} environment variable`);
|
|
1859
|
+
}
|
|
1860
|
+
if (!resolvedScimEndpointAccessToken) {
|
|
1861
|
+
missingParams.push(`scimEndpointAccessToken or ${scimEndpointAccessTokenEnvKey} environment variable`);
|
|
1862
|
+
}
|
|
1863
|
+
if (!resolvedScimEndpointUrl) {
|
|
1864
|
+
missingParams.push(`scimEndpointUrl or ${scimEndpointUrlEnvKey} environment variable`);
|
|
1865
|
+
}
|
|
1866
|
+
if (missingParams.length > 0) {
|
|
1867
|
+
throw new errors.ConfigurationError(`JaypieSsoSyncApplication missing required configuration: ${missingParams.join(", ")}`);
|
|
1868
|
+
}
|
|
1869
|
+
// Create the SSO Sync Application
|
|
1870
|
+
// Type assertion is safe because we validated all required values above
|
|
1871
|
+
this._application = new awsSam.CfnApplication(this, "Application", {
|
|
1872
|
+
location: {
|
|
1873
|
+
applicationId: ssoSyncApplicationId,
|
|
1874
|
+
semanticVersion: resolvedSemanticVersion,
|
|
1875
|
+
},
|
|
1876
|
+
parameters: {
|
|
1877
|
+
GoogleAdminEmail: resolvedGoogleAdminEmail,
|
|
1878
|
+
GoogleCredentials: resolvedGoogleCredentials,
|
|
1879
|
+
GoogleGroupMatch: resolvedGoogleGroupMatch,
|
|
1880
|
+
IdentityStoreID: resolvedIdentityStoreId,
|
|
1881
|
+
Region: cdk$1.Stack.of(this).region,
|
|
1882
|
+
SCIMEndpointAccessToken: resolvedScimEndpointAccessToken,
|
|
1883
|
+
SCIMEndpointUrl: resolvedScimEndpointUrl,
|
|
1884
|
+
},
|
|
1624
1885
|
});
|
|
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");
|
|
1886
|
+
// Add tags
|
|
1887
|
+
const defaultTags = {
|
|
1888
|
+
[cdk.CDK.TAG.ROLE]: cdk.CDK.ROLE.SECURITY,
|
|
1889
|
+
};
|
|
1890
|
+
const allTags = { ...defaultTags, ...tags };
|
|
1891
|
+
Object.entries(allTags).forEach(([key, value]) => {
|
|
1892
|
+
cdk$1.Tags.of(this._application).add(key, value);
|
|
1651
1893
|
});
|
|
1652
1894
|
}
|
|
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
|
-
});
|
|
1895
|
+
get application() {
|
|
1896
|
+
return this._application;
|
|
1678
1897
|
}
|
|
1679
1898
|
}
|
|
1680
1899
|
|
|
@@ -1936,21 +2155,34 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
|
|
|
1936
2155
|
applyRemovalPolicy(policy) {
|
|
1937
2156
|
this.bucket.applyRemovalPolicy(policy);
|
|
1938
2157
|
}
|
|
2158
|
+
get bucketRef() {
|
|
2159
|
+
return {
|
|
2160
|
+
bucketArn: this.bucket.bucketArn,
|
|
2161
|
+
bucketName: this.bucket.bucketName,
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
1939
2164
|
}
|
|
1940
2165
|
|
|
2166
|
+
Object.defineProperty(exports, "CDK", {
|
|
2167
|
+
enumerable: true,
|
|
2168
|
+
get: function () { return cdk.CDK; }
|
|
2169
|
+
});
|
|
1941
2170
|
exports.JaypieApiGateway = JaypieApiGateway;
|
|
1942
2171
|
exports.JaypieAppStack = JaypieAppStack;
|
|
1943
2172
|
exports.JaypieBucketQueuedLambda = JaypieBucketQueuedLambda;
|
|
1944
2173
|
exports.JaypieDatadogSecret = JaypieDatadogSecret;
|
|
2174
|
+
exports.JaypieDnsRecord = JaypieDnsRecord;
|
|
1945
2175
|
exports.JaypieEnvSecret = JaypieEnvSecret;
|
|
1946
2176
|
exports.JaypieExpressLambda = JaypieExpressLambda;
|
|
2177
|
+
exports.JaypieGitHubDeployRole = JaypieGitHubDeployRole;
|
|
1947
2178
|
exports.JaypieHostedZone = JaypieHostedZone;
|
|
1948
2179
|
exports.JaypieInfrastructureStack = JaypieInfrastructureStack;
|
|
1949
2180
|
exports.JaypieLambda = JaypieLambda;
|
|
1950
2181
|
exports.JaypieMongoDbSecret = JaypieMongoDbSecret;
|
|
1951
2182
|
exports.JaypieOpenAiSecret = JaypieOpenAiSecret;
|
|
1952
2183
|
exports.JaypieQueuedLambda = JaypieQueuedLambda;
|
|
1953
|
-
exports.
|
|
2184
|
+
exports.JaypieSsoPermissions = JaypieSsoPermissions;
|
|
2185
|
+
exports.JaypieSsoSyncApplication = JaypieSsoSyncApplication;
|
|
1954
2186
|
exports.JaypieStack = JaypieStack;
|
|
1955
2187
|
exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
|
|
1956
2188
|
exports.JaypieWebDeploymentBucket = JaypieWebDeploymentBucket;
|
|
@@ -1963,7 +2195,9 @@ exports.isEnv = isEnv;
|
|
|
1963
2195
|
exports.isProductionEnv = isProductionEnv;
|
|
1964
2196
|
exports.isSandboxEnv = isSandboxEnv;
|
|
1965
2197
|
exports.jaypieLambdaEnv = jaypieLambdaEnv;
|
|
2198
|
+
exports.resolveDatadogForwarderFunction = resolveDatadogForwarderFunction;
|
|
1966
2199
|
exports.resolveDatadogLayers = resolveDatadogLayers;
|
|
2200
|
+
exports.resolveDatadogLoggingDestination = resolveDatadogLoggingDestination;
|
|
1967
2201
|
exports.resolveHostedZone = resolveHostedZone;
|
|
1968
2202
|
exports.resolveParamsAndSecrets = resolveParamsAndSecrets;
|
|
1969
2203
|
//# sourceMappingURL=index.cjs.map
|