{"id":14155794,"url":"https://github.com/leheriss/aws-platform","last_synced_at":"2025-08-06T01:33:44.639Z","repository":{"id":209424176,"uuid":"720526682","full_name":"leheriss/aws-platform","owner":"leheriss","description":"Comprehensive AWS management solution integrating account factory, AWS Identity Center, Logging, Organizations \u0026 SCP, security tools like AWS Config \u0026 VPN, financial ops.","archived":false,"fork":false,"pushed_at":"2023-12-27T18:07:10.000Z","size":392,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-12-28T18:50:38.207Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leheriss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-11-18T18:55:58.000Z","updated_at":"2023-12-25T17:10:09.000Z","dependencies_parsed_at":"2023-12-26T16:58:38.843Z","dependency_job_id":null,"html_url":"https://github.com/leheriss/aws-platform","commit_stats":null,"previous_names":["leheriss/aws-platform"],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leheriss%2Faws-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leheriss%2Faws-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leheriss%2Faws-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leheriss%2Faws-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leheriss","download_url":"https://codeload.github.com/leheriss/aws-platform/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":215735860,"owners_count":15923388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-17T08:05:00.253Z","updated_at":"2024-08-17T08:06:02.124Z","avatar_url":"https://github.com/leheriss.png","language":"TypeScript","readme":"# AWS Platform project\n\nThis project is a Typescript CDK project to deploy an AWS Platform components.\n\nIt is trying to follow [CDK best practices](https://docs.aws.amazon.com/cdk/v2/guide/best-practices.html) as much as possible.\nThe `cdk.json` file tells CDK Toolkit how to execute your app.\n\n## Useful commands\n\n---\n\n- `npm run cdk:deploy` deploys these stacks to the specified AWS account/region\n- `npm run cdk:diff` compares deployed stack with current state\n- `npm run cdk:synth` emits the synthesized CloudFormation template\n- `cdk watch` watches for changes and deploy on the fly (ONLY IN DEV ENV)\n\n## 🧰 Prerequisite\n\n- 🛠 AWS CLI Installed \u0026 Configured\n- 🛠 AWS CDK version 2.x Installed \u0026 Configured\n- [node](https://nodejs.org/en/) runtime with [npm](https://npmjs.com/)\n- [Create an AWS account](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-creating.html) if you never created one: this will be your management account.\n- [Enable AWS Organization](https://docs.aws.amazon.com/accounts/latest/reference/using-orgs.html) and [AWS Identity Center](https://docs.aws.amazon.com/SetUp/latest/UserGuide/setup-enableIdC.html) in your AWS management account: The AWS Organizations and SSO instance are not created by this tool. SSO instances are **regional**, so please create it in `eu-west-1`.\n\n## ⚙️ Setting up the environment\n\n- Run `npm i` from the root folder\n- Set your CDK context variables: either in the cdk.context.json, in the command line or as CDK*CONTEXT*\u003cvariable\u003e (see [documentation about context](https://docs.aws.amazon.com/cdk/v2/guide/context.html))\n- Run `yarn prepare` to enable husky pre-commit/pre-push actions\n\n## Context variables\n\n- adminEmailsParameterName: The AWS Parameter Store parameter containing your admin email\n\n  \u003e Must be created before deploy the CDK app\n\n- managementAccountId: The account Id of your AWS management account\n\n- ssoInstanceArn: The instance ID of you Identity Center instance\n\n- identityStoreId: The ID of your Identity Center Identity Store\n\n- rootOuId: The ID of your Root Organization (should look like this: `r-12345`)\n\n- awsOrganizationsId: The ID of your AWS Organizations (should look like this: `o-12345678`)\n\n## 🚀 Deployment using cdk\n\n```bash\n# Make sure you in root directory\nnpm i\n\n# Check what will be deployed and deploy\nnpm run cdk:diff\n# If changes are relevant, then deploy\nnpm run cdk:deploy\n```\n\n## 🧹 CleanUp\n\nIf you want to destroy all the resources created by the stack, Execute the below command to delete the stack, or _you can delete the stack from console as well_.\n\n```bash\ncdk destroy *\n```\n\nThis is not an exhaustive list, please carry out other necessary steps as maybe applicable to your needs.\n\nBe aware that in this particular case:\n\n- you need to first **empty the deployed buckets**.\n- You need to **empty every Organization Units** deployed by the project because non-empty OU cannot be deleted.\n- If you have some CloudFormation StackSets, you must remove StackSet instances before destroying\n\n\u003e ⚠️ AWS Organizations does not support doing 2 operations at the same time on the same SCP 🤷‍♀️ . So you may experience trouble deleting those resources.\n\n## 🏗️ Architecture\n\n---\n\nThis project manages :\n\n- The account factory: Account provisionning and deprovisionning\n- Organization Units (OU) creation/deletion\n- Service Control Policies (SCP) creation/deletion\n- Organizations management tools (Budgets, organization trails ...)\n- AWS Identity Center resources (permission sets and groups)\n\nFor more information on AWS Organizations concepts, please refer to [AWS documentation and best practices](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_getting-started_concepts.html).\n\n### 🚧 Constructs and resources\n\n#### **Budgets**\n\nThis [construct](./constructs/budget.ts) extends the AWS CDK [Budget Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_budgets.CfnBudget.html) which is a L1 construct.\n\nIn the management account, we create 1 budget for now which is a global Budget: to sum up all cost in every platform's accounts. But it is possible to add others targetting specific services.\n\nFor example:\n\n```js\nnew Budget(this, 'APIGatewayBudget', {\n  limitAmountUSD: 3000,\n  emails: adminEmails,\n  costFilters: {\n    Service: ['Amazon API Gateway'],\n  },\n});\n```\n\nEach of those budget is created with an amount limit USD and with 3 notifications.\n\nNotifications are sent to administrators, stored in a parameter of the Parameter Store (ADMIN_EMAILS_PARAMETER_NAME environment variable).\n\nYou can find budget declarations in the [FinOps stack](./stacks/finops.ts).\n\n#### **Organization Trail**\n\nThis resource allows to log everything actions from all the AWS account of your organization.\nIt needs a S3 trail bucket and a CloudTrail organization trail.\n\nYou can find this in the [Logging stack](./stacks/logging.ts).\n\n\u003e Be careful if you want to delete this stack, the bucket must be emptied before.\n\n#### **AWS Lambda functions**\n\nThis [construct](./lib/constructs/lambda.ts) extends the AWS CDK [NodeJS Lambda Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html).\n\n#### **SSO Permission Set**\n\nThe [SSOPermissionSet](./lib/constructs/ssoPermissionSet.ts) extends the [CfnPermissionSet](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sso.CfnPermissionSet.html) CDK construct. It fixes a default name and a default session duration. Of course, those two attributes can be overwritten.\n\nAll permission sets are declared in another construct : [SSOPermissionSets](./lib/constructs/ssoPermissionSets.ts). Indeed, it is just to separate this part from the stack (pure esthetic stuff) and avoid having a 5000 lines file.\n\nAll inline policies are declare in [./policies](./lib/policies/) folder.\n\n#### **SSO Assignment**\n\nThe [SSOAssignment](./lib/constructs/ssoAssignments.ts) takes a list of [assignments](./lib/types.ts) and create a CDK [CfnAssignment](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sso.CfnAssignment.html).\n\nAn assignment is the link between an AWS SSO group and a list of permission sets.\nAs an assignment MUST target an AWS account, each permission set is associated to an account and this forms an [AccountPermissionSet](./lib/types.ts).\n\nFor example:\n\n```js\n{\n  groupId: \u003cGroupId\u003e,\n  groupName: \u003cGroupName\u003e,\n  accountPermissionSets: [\n    {\n      permissionSet: \u003cpermissionSet\u003e,\n      account: 123456789101,\n    },\n  ],\n},\n```\n\nThis is an Assignment. It associates the Admin SSO group to the `admin` permission set for `123456789101` account.\nIf I add an item to accountPermissionSets, like this:\n\n```js\n{\n  groupId: \u003cGroupId\u003e,\n  groupName: \u003cGroupName\u003e,\n  accountPermissionSets: [\n    {\n      permissionSet: permissionSets.admin,\n      account: 123456789101,\n    },\n    {\n      permissionSet: permissionSets.viewOnly,\n      account: 918203837466,\n    },\n  ],\n},\n```\n\nThis will give to the `Admin` group the `admin` permission to `123456789101` account and the `viewOnly` permission to `918203837466` account.\n\n#### SSO groups\n\nSSO groups are created in the [AwsIdentityCenter Stack](./stacks/aws-identity-center.ts) using a [custom construct](./constructs/identityCenterGroup.ts):\n\n```javascript\nconst group = new IdentityCenterGroup(this, 'group', {\n  groupName: 'GroupName',\n  identityStoreId,\n});\n```\n\n### Stacks\n\nMultiple CloudFormation stacks are deployed by this project.\n\n#### 🏭 **aws-account-factory**\n\nThis [stack](./stacks/aws-account-factory.ts) deploys:\n\n- `createAccount`:\n  Creates the AWS account =\u003e waits for its creation =\u003e adds it to the right OU depending on the `accountType` parameter given =\u003e adds the billing alternate contact\n- `deleteAccount`:\n  Fetches the OU id of the account we want to delete, using the `accountId` given parameter =\u003e moves the account to the `PENDING-DELETION` OU =\u003e closes the account.\n\n\u003e Be aware that there is a quota for the number of deletable account in a month (20% of the total number of accounts). So you might get the `ConstraintViolationException` with the error message `You have exceeded close account quota for the past 30 days.`. In that case, the `delete-account` lambda will just put the account in the `Pending Deletion` Organizational Unit where the `Deny Actions` SCP blocks every action but the one to close the account. You'll have to retry to delete the account the next month.\n\n\u003e For more information on what implies \"closing account\" in AWS, please refer to the [AWS documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_close.html).\n\n\u003e You can find Lambda Typescript code in the [lambda folder](./lambdas). And their CDK declaration in the [accountFactory stack](./stacks/aws-account-factory.ts)\n\n#### 💰 **finops**\n\nThis [stack](./stacks/finops.ts) deploys billing related resources as budgets for example.\n\n#### 👀 **logging**\n\nThis [stack](./stacks/logging.ts) deploys monitoring related resources. For now it only deploys a Global Organization trail.\n\n#### 🫀 **aws-organizations**\n\nThis [stack](./stacks/aws-organizations.ts) deploys AWS Organizations resources such as:\n\n- Service Control Policies\n- Organization Units\n\nThose resources must be described in a Yaml file that you have to give to the stask like this:\n\n```javascript\nconst organizationsStack = new AwsOrganizationsStack(app, 'AwsOrganizationsStack', {\n  rootOrganizationId: rootOuId,\n  accountId: managementAccountId,\n  configFilePath: './config/organizations.yaml',\n});\n```\n\nThe file must contain 2 keys: `serviceControlPolicies` and `organizationUnits`:\n\n```yaml\norganizationUnits:\n  - name: App\n    parentName: root\nserviceControlPolicies:\n  - name: DenyLeaveOrganization\n    description: 'Policy forbidding leaving the Organization'\n    targetOUNames:\n      - root\n    contentFile: scps/denyLeaveOrganization.json\n  - name: DenyActions\n    description: 'Policy denying specific actions'\n    targetOUNames:\n      - root\n    contentFile: scps/denyActions.json\n```\n\nThe root OU must not be defined in this file, it already exists by default. If you need to reference it as a parent OU for one of your Organization Units OR as a targetOU for your SCP, it must be called `root`.\n\nSCP content must be referenced either as a file: you must give the file path. Or directly the content if you prefer.\n\nThere is one Organization Unit created by default that you cannot touch in terms of SCP: the `Pendind Deletion` OU, it is used by the delete account lambdas to store the account while it is suspended or scheduled for deletion.\n\n#### 🪪 **aws-identity-center**\n\nThis [stack](./stacks/aws-identiry-center.ts):\n\n- instantiates all permission sets\n- declares all assignment of groups to permission set/account\n- create SSO groups\n\nThose resources are described in a YAML file and the file path must be givent to the stack:\n\n```javascript\nnew AwsIdentityCenterStack(app, 'AwsIdentityCenterStack', {\n  accountId: managementAccountId,\n  ssoInstanceArn,\n  identityStoreId,\n  configFilePath: './config/identityCenter.yaml',\n});\n```\n\nThe file can contain this 3 keys: `group` and `permissionSets` and `assignment`. To create the assignment, the group and permissionSet referenced must be created in the group and permissionSets sections:\n\n```yaml\ngroups:\n  - name: Administrators\n  - name: ReadOnly\npermissionSets:\n  - name: Administrators\n    managedPolicies:\n      - 'arn:aws:iam::aws:policy/AdministratorAccess'\n  - name: ViewOnly\n    managedPolicies:\n      - 'arn:aws:iam::aws:policy/job-function/ViewOnlyAccess'\nassignments:\n  - accountId: 'xxxxxx'\n    permissions:\n      - groupName: ReadOnly\n        permissionSets:\n          - ViewOnly\n      - groupName: Administrators\n        permissionSets:\n          - Administrators\n```\n\nTo create an assignment, you must give the account ID (this is why the config file is not to be commited).\n\nThe permissionSet can also contain a `description`, an `inlinePolicy` (as a file path or directly the content) and a `duration`.\n\n## Unit tests\n\n---\n\nCDK's unit tests are in [./test](./test/aws-sso.test.ts) directory.\nThe unit test library used is [jest](https://jestjs.io/docs/getting-started) and its configuration is [here](./jest.config.js).\n","funding_links":[],"categories":["others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleheriss%2Faws-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleheriss%2Faws-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleheriss%2Faws-platform/lists"}