Skip to content

Comprehensive AWS management solution integrating account factory, AWS Identity Center, Logging, Organizations & SCP, security tools like AWS Config & VPN, financial ops.

Notifications You must be signed in to change notification settings

leheriss/aws-platform

Repository files navigation

AWS Platform project

This project is a Typescript CDK project to deploy an AWS Platform components.

It is trying to follow CDK best practices as much as possible. The cdk.json file tells CDK Toolkit how to execute your app.

Useful commands


  • npm run cdk:deploy deploys these stacks to the specified AWS account/region
  • npm run cdk:diff compares deployed stack with current state
  • npm run cdk:synth emits the synthesized CloudFormation template
  • cdk watch watches for changes and deploy on the fly (ONLY IN DEV ENV)

🧰 Prerequisite

  • πŸ›  AWS CLI Installed & Configured
  • πŸ›  AWS CDK version 2.x Installed & Configured
  • node runtime with npm
  • Create an AWS account if you never created one: this will be your management account.
  • Enable AWS Organization and AWS Identity Center 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.

βš™οΈ Setting up the environment

  • Run npm i from the root folder
  • Set your CDK context variables: either in the cdk.context.json, in the command line or as CDKCONTEXT (see documentation about context)
  • Run yarn prepare to enable husky pre-commit/pre-push actions

Context variables

  • adminEmailsParameterName: The AWS Parameter Store parameter containing your admin email

    Must be created before deploy the CDK app

  • managementAccountId: The account Id of your AWS management account

  • ssoInstanceArn: The instance ID of you Identity Center instance

  • identityStoreId: The ID of your Identity Center Identity Store

  • rootOuId: The ID of your Root Organization (should look like this: r-12345)

  • awsOrganizationsId: The ID of your AWS Organizations (should look like this: o-12345678)

πŸš€ Deployment using cdk

# Make sure you in root directory
npm i

# Check what will be deployed and deploy
npm run cdk:diff
# If changes are relevant, then deploy
npm run cdk:deploy

🧹 CleanUp

If 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.

cdk destroy *

This is not an exhaustive list, please carry out other necessary steps as maybe applicable to your needs.

Be aware that in this particular case:

  • you need to first empty the deployed buckets.
  • You need to empty every Organization Units deployed by the project because non-empty OU cannot be deleted.
  • If you have some CloudFormation StackSets, you must remove StackSet instances before destroying

⚠️ AWS Organizations does not support doing 2 operations at the same time on the same SCP πŸ€·β€β™€οΈ . So you may experience trouble deleting those resources.

πŸ—οΈ Architecture


This project manages :

  • The account factory: Account provisionning and deprovisionning
  • Organization Units (OU) creation/deletion
  • Service Control Policies (SCP) creation/deletion
  • Organizations management tools (Budgets, organization trails ...)
  • AWS Identity Center resources (permission sets and groups)

For more information on AWS Organizations concepts, please refer to AWS documentation and best practices.

🚧 Constructs and resources

Budgets

This construct extends the AWS CDK Budget Construct which is a L1 construct.

In 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.

For example:

new Budget(this, 'APIGatewayBudget', {
  limitAmountUSD: 3000,
  emails: adminEmails,
  costFilters: {
    Service: ['Amazon API Gateway'],
  },
});

Each of those budget is created with an amount limit USD and with 3 notifications.

Notifications are sent to administrators, stored in a parameter of the Parameter Store (ADMIN_EMAILS_PARAMETER_NAME environment variable).

You can find budget declarations in the FinOps stack.

Organization Trail

This resource allows to log everything actions from all the AWS account of your organization. It needs a S3 trail bucket and a CloudTrail organization trail.

You can find this in the Logging stack.

Be careful if you want to delete this stack, the bucket must be emptied before.

AWS Lambda functions

This construct extends the AWS CDK NodeJS Lambda Construct.

SSO Permission Set

The SSOPermissionSet extends the CfnPermissionSet CDK construct. It fixes a default name and a default session duration. Of course, those two attributes can be overwritten.

All permission sets are declared in another construct : SSOPermissionSets. Indeed, it is just to separate this part from the stack (pure esthetic stuff) and avoid having a 5000 lines file.

All inline policies are declare in ./policies folder.

SSO Assignment

The SSOAssignment takes a list of assignments and create a CDK CfnAssignment.

An assignment is the link between an AWS SSO group and a list of permission sets. As an assignment MUST target an AWS account, each permission set is associated to an account and this forms an AccountPermissionSet.

For example:

{
  groupId: <GroupId>,
  groupName: <GroupName>,
  accountPermissionSets: [
    {
      permissionSet: <permissionSet>,
      account: 123456789101,
    },
  ],
},

This is an Assignment. It associates the Admin SSO group to the admin permission set for 123456789101 account. If I add an item to accountPermissionSets, like this:

{
  groupId: <GroupId>,
  groupName: <GroupName>,
  accountPermissionSets: [
    {
      permissionSet: permissionSets.admin,
      account: 123456789101,
    },
    {
      permissionSet: permissionSets.viewOnly,
      account: 918203837466,
    },
  ],
},

This will give to the Admin group the admin permission to 123456789101 account and the viewOnly permission to 918203837466 account.

SSO groups

SSO groups are created in the AwsIdentityCenter Stack using a custom construct:

const group = new IdentityCenterGroup(this, 'group', {
  groupName: 'GroupName',
  identityStoreId,
});

Stacks

Multiple CloudFormation stacks are deployed by this project.

🏭 aws-account-factory

This stack deploys:

  • createAccount: Creates the AWS account => waits for its creation => adds it to the right OU depending on the accountType parameter given => adds the billing alternate contact
  • deleteAccount: Fetches the OU id of the account we want to delete, using the accountId given parameter => moves the account to the PENDING-DELETION OU => closes the account.

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.

For more information on what implies "closing account" in AWS, please refer to the AWS documentation.

You can find Lambda Typescript code in the lambda folder. And their CDK declaration in the accountFactory stack

πŸ’° finops

This stack deploys billing related resources as budgets for example.

πŸ‘€ logging

This stack deploys monitoring related resources. For now it only deploys a Global Organization trail.

πŸ«€ aws-organizations

This stack deploys AWS Organizations resources such as:

  • Service Control Policies
  • Organization Units

Those resources must be described in a Yaml file that you have to give to the stask like this:

const organizationsStack = new AwsOrganizationsStack(app, 'AwsOrganizationsStack', {
  rootOrganizationId: rootOuId,
  accountId: managementAccountId,
  configFilePath: './config/organizations.yaml',
});

The file must contain 2 keys: serviceControlPolicies and organizationUnits:

organizationUnits:
  - name: App
    parentName: root
serviceControlPolicies:
  - name: DenyLeaveOrganization
    description: 'Policy forbidding leaving the Organization'
    targetOUNames:
      - root
    contentFile: scps/denyLeaveOrganization.json
  - name: DenyActions
    description: 'Policy denying specific actions'
    targetOUNames:
      - root
    contentFile: scps/denyActions.json

The 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.

SCP content must be referenced either as a file: you must give the file path. Or directly the content if you prefer.

There 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.

πŸͺͺ aws-identity-center

This stack:

  • instantiates all permission sets
  • declares all assignment of groups to permission set/account
  • create SSO groups

Those resources are described in a YAML file and the file path must be givent to the stack:

new AwsIdentityCenterStack(app, 'AwsIdentityCenterStack', {
  accountId: managementAccountId,
  ssoInstanceArn,
  identityStoreId,
  configFilePath: './config/identityCenter.yaml',
});

The 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:

groups:
  - name: Administrators
  - name: ReadOnly
permissionSets:
  - name: Administrators
    managedPolicies:
      - 'arn:aws:iam::aws:policy/AdministratorAccess'
  - name: ViewOnly
    managedPolicies:
      - 'arn:aws:iam::aws:policy/job-function/ViewOnlyAccess'
assignments:
  - accountId: 'xxxxxx'
    permissions:
      - groupName: ReadOnly
        permissionSets:
          - ViewOnly
      - groupName: Administrators
        permissionSets:
          - Administrators

To create an assignment, you must give the account ID (this is why the config file is not to be commited).

The permissionSet can also contain a description, an inlinePolicy (as a file path or directly the content) and a duration.

Unit tests


CDK's unit tests are in ./test directory. The unit test library used is jest and its configuration is here.

About

Comprehensive AWS management solution integrating account factory, AWS Identity Center, Logging, Organizations & SCP, security tools like AWS Config & VPN, financial ops.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published