@jaypie/constructs 1.1.18 → 1.1.20

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/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Finlayson Studio, LLC
3
+ Copyright (c) 2025 Finlayson Studio, LLC
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,121 @@
1
+ import { Construct } from "constructs";
2
+ import * as sso from "aws-cdk-lib/aws-sso";
3
+ /**
4
+ * Account categories for SSO group assignments
5
+ */
6
+ export interface JaypieSsoAccountMap {
7
+ development: string[];
8
+ management: string[];
9
+ operations: string[];
10
+ production: string[];
11
+ sandbox: string[];
12
+ security: string[];
13
+ stage: string[];
14
+ }
15
+ /**
16
+ * Mapping of group types to Google Workspace group GUIDs
17
+ */
18
+ export interface JaypieSsoGroupMap {
19
+ administrators: string;
20
+ analysts: string;
21
+ developers: string;
22
+ }
23
+ /**
24
+ * IAM Policy Statement structure for inline policies
25
+ */
26
+ export interface PolicyStatement {
27
+ Effect: "Allow" | "Deny";
28
+ Action: string[] | string;
29
+ Resource: string[] | string;
30
+ Condition?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Properties for the JaypieSsoGroups construct
34
+ */
35
+ export interface JaypieSsoGroupsProps {
36
+ /**
37
+ * ARN of the IAM Identity Center instance
38
+ */
39
+ instanceArn: string;
40
+ /**
41
+ * Mapping of account categories to AWS account IDs
42
+ */
43
+ accountMap: JaypieSsoAccountMap;
44
+ /**
45
+ * Mapping of group types to Google Workspace group GUIDs
46
+ */
47
+ groupMap: JaypieSsoGroupMap;
48
+ /**
49
+ * Additional inline policy statements to append to each group's permission set
50
+ * Each group can have its own set of policy statements that will be merged
51
+ * with the default policies.
52
+ */
53
+ inlinePolicyStatements?: {
54
+ administrators?: PolicyStatement[];
55
+ analysts?: PolicyStatement[];
56
+ developers?: PolicyStatement[];
57
+ };
58
+ }
59
+ /**
60
+ * Permission set types with corresponding AWS managed policies
61
+ */
62
+ export declare enum PermissionSetType {
63
+ ADMINISTRATOR = "Administrator",
64
+ ANALYST = "Analyst",
65
+ DEVELOPER = "Developer"
66
+ }
67
+ /**
68
+ * Construct to simplify AWS SSO group management.
69
+ * This construct encapsulates the complexity of creating permission sets
70
+ * and assigning them to groups across multiple AWS accounts.
71
+ */
72
+ export declare class JaypieSsoGroups extends Construct {
73
+ private readonly permissionSets;
74
+ private readonly instanceArn;
75
+ private readonly props;
76
+ constructor(scope: Construct, id: string, props: JaypieSsoGroupsProps);
77
+ /**
78
+ * Creates the Administrator permission set with AdministratorAccess policy
79
+ * and billing access
80
+ */
81
+ private createAdministratorPermissionSet;
82
+ /**
83
+ * Creates the Analyst permission set with ReadOnlyAccess policy
84
+ * and limited write access
85
+ */
86
+ private createAnalystPermissionSet;
87
+ /**
88
+ * Creates the Developer permission set with SystemAdministrator policy
89
+ * and expanded write access
90
+ */
91
+ private createDeveloperPermissionSet;
92
+ /**
93
+ * Gets the permission set for the specified type
94
+ */
95
+ getPermissionSet(type: PermissionSetType): sso.CfnPermissionSet;
96
+ /**
97
+ * Merges default inline policies with additional user-provided policy statements
98
+ *
99
+ * @param defaultPolicy - The default policy object with Version and Statement properties
100
+ * @param additionalStatements - Optional additional policy statements to merge
101
+ * @returns The merged policy object
102
+ */
103
+ private mergeInlinePolicies;
104
+ /**
105
+ * Creates assignments between permission sets, groups, and accounts
106
+ * based on the provided configuration
107
+ */
108
+ private createPermissionSetAssignments;
109
+ /**
110
+ * Assigns Administrator permissions to appropriate accounts
111
+ */
112
+ private assignAdministratorPermissions;
113
+ /**
114
+ * Assigns Analyst permissions to appropriate accounts
115
+ */
116
+ private assignAnalystPermissions;
117
+ /**
118
+ * Assigns Developer permissions to appropriate accounts
119
+ */
120
+ private assignDeveloperPermissions;
121
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -10,6 +10,7 @@ var awsRoute53 = require('aws-cdk-lib/aws-route53');
10
10
  var lambda = require('aws-cdk-lib/aws-lambda');
11
11
  var sqs = require('aws-cdk-lib/aws-sqs');
12
12
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
13
+ var sso = require('aws-cdk-lib/aws-sso');
13
14
 
14
15
  function _interopNamespaceDefault(e) {
15
16
  var n = Object.create(null);
@@ -33,6 +34,7 @@ var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsman
33
34
  var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
34
35
  var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
35
36
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
37
+ var sso__namespace = /*#__PURE__*/_interopNamespaceDefault(sso);
36
38
 
37
39
  // It is a consumer if the environment is ephemeral
38
40
  function checkEnvIsConsumer(env = process.env) {
@@ -473,6 +475,282 @@ class JaypieQueuedLambda extends constructs.Construct {
473
475
  }
474
476
  }
475
477
 
478
+ /**
479
+ * Permission set types with corresponding AWS managed policies
480
+ */
481
+ exports.PermissionSetType = void 0;
482
+ (function (PermissionSetType) {
483
+ PermissionSetType["ADMINISTRATOR"] = "Administrator";
484
+ PermissionSetType["ANALYST"] = "Analyst";
485
+ PermissionSetType["DEVELOPER"] = "Developer";
486
+ })(exports.PermissionSetType || (exports.PermissionSetType = {}));
487
+ /**
488
+ * Construct to simplify AWS SSO group management.
489
+ * This construct encapsulates the complexity of creating permission sets
490
+ * and assigning them to groups across multiple AWS accounts.
491
+ */
492
+ class JaypieSsoGroups extends constructs.Construct {
493
+ constructor(scope, id, props) {
494
+ super(scope, id);
495
+ this.permissionSets = {};
496
+ this.instanceArn = props.instanceArn;
497
+ this.props = props;
498
+ // Create the permission sets
499
+ this.createAdministratorPermissionSet();
500
+ this.createAnalystPermissionSet();
501
+ this.createDeveloperPermissionSet();
502
+ // Create the assignments
503
+ this.createPermissionSetAssignments(props);
504
+ }
505
+ /**
506
+ * Creates the Administrator permission set with AdministratorAccess policy
507
+ * and billing access
508
+ */
509
+ createAdministratorPermissionSet() {
510
+ const defaultInlinePolicy = {
511
+ Version: "2012-10-17",
512
+ Statement: [
513
+ {
514
+ Effect: "Allow",
515
+ Action: [
516
+ "aws-portal:ViewBilling",
517
+ "aws-portal:ModifyBilling",
518
+ "aws-portal:ViewAccount",
519
+ "aws-portal:ModifyAccount",
520
+ "budgets:ViewBudget",
521
+ "budgets:ModifyBudget",
522
+ ],
523
+ Resource: "*",
524
+ },
525
+ ],
526
+ };
527
+ // Merge with any additional policy statements provided for administrators
528
+ const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.administrators);
529
+ const permissionSet = new sso__namespace.CfnPermissionSet(this, "AdministratorPermissionSet", {
530
+ instanceArn: this.instanceArn,
531
+ name: exports.PermissionSetType.ADMINISTRATOR,
532
+ description: "Full administrative access to all AWS services and resources",
533
+ sessionDuration: cdk.Duration.hours(8).toIsoString(),
534
+ managedPolicies: ["arn:aws:iam::aws:policy/AdministratorAccess"],
535
+ inlinePolicy: mergedPolicy,
536
+ });
537
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
538
+ this.permissionSets[exports.PermissionSetType.ADMINISTRATOR] = permissionSet;
539
+ }
540
+ /**
541
+ * Creates the Analyst permission set with ReadOnlyAccess policy
542
+ * and limited write access
543
+ */
544
+ createAnalystPermissionSet() {
545
+ const defaultInlinePolicy = {
546
+ Version: "2012-10-17",
547
+ Statement: [
548
+ {
549
+ Effect: "Allow",
550
+ Action: [
551
+ "aws-portal:ViewBilling",
552
+ "aws-portal:ViewAccount",
553
+ "budgets:ViewBudget",
554
+ "cloudwatch:PutDashboard",
555
+ "cloudwatch:PutMetricData",
556
+ "s3:PutObject",
557
+ "s3:GetObject",
558
+ "s3:ListBucket",
559
+ ],
560
+ Resource: "*",
561
+ },
562
+ ],
563
+ };
564
+ // Merge with any additional policy statements provided for analysts
565
+ const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.analysts);
566
+ const permissionSet = new sso__namespace.CfnPermissionSet(this, "AnalystPermissionSet", {
567
+ instanceArn: this.instanceArn,
568
+ name: exports.PermissionSetType.ANALYST,
569
+ description: "Read-only access with billing visibility and limited write access",
570
+ sessionDuration: cdk.Duration.hours(4).toIsoString(),
571
+ managedPolicies: ["arn:aws:iam::aws:policy/ReadOnlyAccess"],
572
+ inlinePolicy: mergedPolicy,
573
+ });
574
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
575
+ this.permissionSets[exports.PermissionSetType.ANALYST] = permissionSet;
576
+ }
577
+ /**
578
+ * Creates the Developer permission set with SystemAdministrator policy
579
+ * and expanded write access
580
+ */
581
+ createDeveloperPermissionSet() {
582
+ const defaultInlinePolicy = {
583
+ Version: "2012-10-17",
584
+ Statement: [
585
+ {
586
+ Effect: "Allow",
587
+ Action: [
588
+ "cloudwatch:*",
589
+ "logs:*",
590
+ "lambda:*",
591
+ "apigateway:*",
592
+ "dynamodb:*",
593
+ "s3:*",
594
+ "sns:*",
595
+ "sqs:*",
596
+ "events:*",
597
+ "ecr:*",
598
+ "ecs:*",
599
+ "codebuild:*",
600
+ ],
601
+ Resource: "*",
602
+ },
603
+ {
604
+ Effect: "Deny",
605
+ Action: [
606
+ "iam:*User*",
607
+ "iam:*Role*",
608
+ "iam:*Policy*",
609
+ "organizations:*",
610
+ "account:*",
611
+ ],
612
+ Resource: "*",
613
+ },
614
+ ],
615
+ };
616
+ // Merge with any additional policy statements provided for developers
617
+ const mergedPolicy = this.mergeInlinePolicies(defaultInlinePolicy, this.props?.inlinePolicyStatements?.developers);
618
+ const permissionSet = new sso__namespace.CfnPermissionSet(this, "DeveloperPermissionSet", {
619
+ instanceArn: this.instanceArn,
620
+ name: exports.PermissionSetType.DEVELOPER,
621
+ description: "System administrator access with expanded write permissions",
622
+ sessionDuration: cdk.Duration.hours(8).toIsoString(),
623
+ managedPolicies: [
624
+ "arn:aws:iam::aws:policy/job-function/SystemAdministrator",
625
+ ],
626
+ inlinePolicy: mergedPolicy,
627
+ });
628
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
629
+ this.permissionSets[exports.PermissionSetType.DEVELOPER] = permissionSet;
630
+ }
631
+ /**
632
+ * Gets the permission set for the specified type
633
+ */
634
+ getPermissionSet(type) {
635
+ return this.permissionSets[type];
636
+ }
637
+ /**
638
+ * Merges default inline policies with additional user-provided policy statements
639
+ *
640
+ * @param defaultPolicy - The default policy object with Version and Statement properties
641
+ * @param additionalStatements - Optional additional policy statements to merge
642
+ * @returns The merged policy object
643
+ */
644
+ mergeInlinePolicies(defaultPolicy, additionalStatements) {
645
+ if (!additionalStatements || additionalStatements.length === 0) {
646
+ return defaultPolicy;
647
+ }
648
+ // Create a deep copy of the default policy to avoid modifying the original
649
+ const mergedPolicy = JSON.parse(JSON.stringify(defaultPolicy));
650
+ // Add the additional statements to the existing statements
651
+ mergedPolicy.Statement = [
652
+ ...mergedPolicy.Statement,
653
+ ...additionalStatements,
654
+ ];
655
+ return mergedPolicy;
656
+ }
657
+ /**
658
+ * Creates assignments between permission sets, groups, and accounts
659
+ * based on the provided configuration
660
+ */
661
+ createPermissionSetAssignments(props) {
662
+ // Administrator assignments
663
+ this.assignAdministratorPermissions(props);
664
+ // Analyst assignments
665
+ this.assignAnalystPermissions(props);
666
+ // Developer assignments
667
+ this.assignDeveloperPermissions(props);
668
+ }
669
+ /**
670
+ * Assigns Administrator permissions to appropriate accounts
671
+ */
672
+ assignAdministratorPermissions(props) {
673
+ const administratorGroup = props.groupMap.administrators;
674
+ const administratorPermissionSet = this.permissionSets[exports.PermissionSetType.ADMINISTRATOR];
675
+ // Administrators get access to all accounts
676
+ const allAccounts = [
677
+ ...props.accountMap.development,
678
+ ...props.accountMap.management,
679
+ ...props.accountMap.operations,
680
+ ...props.accountMap.production,
681
+ ...props.accountMap.sandbox,
682
+ ...props.accountMap.security,
683
+ ...props.accountMap.stage,
684
+ ];
685
+ // Create assignments for each account
686
+ allAccounts.forEach((accountId, index) => {
687
+ const assignment = new sso__namespace.CfnAssignment(this, `AdministratorAssignment${index}`, {
688
+ instanceArn: this.instanceArn,
689
+ permissionSetArn: administratorPermissionSet.attrPermissionSetArn,
690
+ principalId: administratorGroup,
691
+ principalType: "GROUP",
692
+ targetId: accountId,
693
+ targetType: "AWS_ACCOUNT",
694
+ });
695
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
696
+ cdk.Tags.of(assignment).add("Group", "administrators");
697
+ });
698
+ }
699
+ /**
700
+ * Assigns Analyst permissions to appropriate accounts
701
+ */
702
+ assignAnalystPermissions(props) {
703
+ const analystGroup = props.groupMap.analysts;
704
+ const analystPermissionSet = this.permissionSets[exports.PermissionSetType.ANALYST];
705
+ // Analysts get access to development, management, sandbox, and stage accounts
706
+ const analystAccounts = [
707
+ ...props.accountMap.development,
708
+ ...props.accountMap.management,
709
+ ...props.accountMap.sandbox,
710
+ ...props.accountMap.stage,
711
+ ];
712
+ // Create assignments for each account
713
+ analystAccounts.forEach((accountId, index) => {
714
+ const assignment = new sso__namespace.CfnAssignment(this, `AnalystAssignment${index}`, {
715
+ instanceArn: this.instanceArn,
716
+ permissionSetArn: analystPermissionSet.attrPermissionSetArn,
717
+ principalId: analystGroup,
718
+ principalType: "GROUP",
719
+ targetId: accountId,
720
+ targetType: "AWS_ACCOUNT",
721
+ });
722
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
723
+ cdk.Tags.of(assignment).add("Group", "analysts");
724
+ });
725
+ }
726
+ /**
727
+ * Assigns Developer permissions to appropriate accounts
728
+ */
729
+ assignDeveloperPermissions(props) {
730
+ const developerGroup = props.groupMap.developers;
731
+ const developerPermissionSet = this.permissionSets[exports.PermissionSetType.DEVELOPER];
732
+ // Developers get access to development, sandbox, and stage accounts
733
+ const developerAccounts = [
734
+ ...props.accountMap.development,
735
+ ...props.accountMap.sandbox,
736
+ ...props.accountMap.stage,
737
+ ];
738
+ // Create assignments for each account
739
+ developerAccounts.forEach((accountId, index) => {
740
+ const assignment = new sso__namespace.CfnAssignment(this, `DeveloperAssignment${index}`, {
741
+ instanceArn: this.instanceArn,
742
+ permissionSetArn: developerPermissionSet.attrPermissionSetArn,
743
+ principalId: developerGroup,
744
+ principalType: "GROUP",
745
+ targetId: accountId,
746
+ targetType: "AWS_ACCOUNT",
747
+ });
748
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
749
+ cdk.Tags.of(assignment).add("Group", "developers");
750
+ });
751
+ }
752
+ }
753
+
476
754
  class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
477
755
  constructor(scope, id = "TraceSigningKey", props) {
478
756
  const defaultProps = {
@@ -490,5 +768,6 @@ exports.JaypieHostedZone = JaypieHostedZone;
490
768
  exports.JaypieMongoDbSecret = JaypieMongoDbSecret;
491
769
  exports.JaypieOpenAiSecret = JaypieOpenAiSecret;
492
770
  exports.JaypieQueuedLambda = JaypieQueuedLambda;
771
+ exports.JaypieSsoGroups = JaypieSsoGroups;
493
772
  exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
494
773
  //# sourceMappingURL=index.cjs.map