From b3604025e0a40decaaa286fdbc6fbca7bf9343ea Mon Sep 17 00:00:00 2001 From: "Philip M. Gollucci" Date: Sun, 10 Nov 2024 19:14:47 -0500 Subject: [PATCH] feat: bin/deploy.ts -> src/deploy.ts; bin/p6lzctl --- .deps/p6aws | 1 + .deps/p6common | 1 + bin/p6lzctl | 134 +++++++++++++++++++++++++++++++++++++++++ cdk.json | 5 +- src/audit.ts | 8 +++ src/avm.ts | 9 ++- {bin => src}/deploy.ts | 13 +++- tsconfig.json | 2 +- 8 files changed, 165 insertions(+), 8 deletions(-) create mode 120000 .deps/p6aws create mode 120000 .deps/p6common create mode 100755 bin/p6lzctl create mode 100644 src/audit.ts rename {bin => src}/deploy.ts (53%) diff --git a/.deps/p6aws b/.deps/p6aws new file mode 120000 index 0000000..b598c8f --- /dev/null +++ b/.deps/p6aws @@ -0,0 +1 @@ +/Users/pgollucci/.p6/p6m7g8-dotfiles/p6aws \ No newline at end of file diff --git a/.deps/p6common b/.deps/p6common new file mode 120000 index 0000000..fff052b --- /dev/null +++ b/.deps/p6common @@ -0,0 +1 @@ +/Users/pgollucci/.p6/p6m7g8-dotfiles/p6common \ No newline at end of file diff --git a/bin/p6lzctl b/bin/p6lzctl new file mode 100755 index 0000000..e095854 --- /dev/null +++ b/bin/p6lzctl @@ -0,0 +1,134 @@ +#!/bin/sh + +# shellcheck shell=bash + +###################################################################### +#< +# +# Function: p6_lz_main() +# +# Environment: LC_ALL OPTIND SHELL TERM +#> +#/ Synopsis +#/ The entry point for bin/p6lzctl +#/ +###################################################################### +p6_lz_main() { + + # sanitize env + LC_ALL=C + unset SHELL + unset TERM + + local file=".deps/p6common/lib/_bootstrap.sh" + . $file + p6_bootstrap ".deps/p6common" + p6_bootstrap ".deps/p6aws" + + # default options + local flag_debug=0 + + # parse options + local flag + while getopts "dD" flag; do + case $flag in + D) flag_debug=0 ;; + d) flag_debug=1 ;; + *) p6_lz_usage 1 "invalid flag" ;; + esac + done + shift $((OPTIND - 1)) + + # grab command + local cmd="$1" + shift 1 + + # security 101: only allow valid comamnds + case $cmd in + boostrap) ;; + deploy) ;; + esac + + # setup -x based on flag_debug + [ ${flag_debug} = 1 ] && set -x + # exit if any cli errors w/ >0 return code + # the commands can still disable locally if needed + set -e + p6_lz_cmd_"${cmd}" "$@" + set +e + [ ${flag_debug} = 1 ] && set +x + + return 0 +} + +###################################################################### +#< +# +# Function: p6_lz_cmd_bootstrap(...) +# +# Args: +# ... - +# +#> +###################################################################### +p6_lz_cmd_bootstrap() { + shift 0 + + pnpm cdk bootstrap +} + +###################################################################### +#< +# +# Function: p6_lz_cmd_deploy(...) +# +# Args: +# ... - +# +#> +###################################################################### +p6_lz_cmd_deploy() { + shift 0 + + p6_lz_cmd_bootstrap + + pnpm cdk deploy p6-lz-organization p6-lz-avm --require-approval never + + local mgmt_account_id=$(p6_lz_util_mgmt_account_id_get) + local account_ids=$(p6_lz_util_account_ids_get "$mgmt_account_id") + local account_id + for account_id in ${account_ids}; do + p6_aws_svc_organizations_sts_su $account_id + pnpm cdk bootstrap aws://$account_id/us-east-1 --trust $mgmt_account_id --trust-for-lookup $mgmt_account_id --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess + p6_aws_svc_organizations_sts_su_un + done + + pnpm cdk deploy p6-lz-audit --require-approval never + # pnpm cdk deploy p6-lz-logarchive --require-approval never + # pnpm cdk deploy p6-lz-shared --require-approval never +} + +p6_lz_util_account_ids_get() { + local mgmt_account_id="$1" + + local account_ids=$(aws organizations list-accounts --query "Accounts[?Status=='ACTIVE'].Id" | jq -r ".[]" | grep -v "${mgmt_account_id}") + + echo "${account_ids}" +} + +p6_lz_util_mgmt_account_id_get() { + shift 0 + + local account_id=$(aws organizations describe-organization --query "Organization.MasterAccountId" --output text) + + echo "${account_id}" +} + +###################################################################### +#< +# +# Function: p6_lz_main() +# +#> +###################################################################### +p6_lz_main "$@" diff --git a/cdk.json b/cdk.json index 95781cd..b22ce22 100644 --- a/cdk.json +++ b/cdk.json @@ -1,9 +1,10 @@ { - "app": "npx ts-node -P tsconfig.json --prefer-ts-exts bin/deploy.ts", + "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/deploy.ts", "watch": { "include": [ "bin/deploy.ts", - "src/stack.ts" + "src/organization.ts", + "src/avm.ts" ], "exclude": [ "README.md", diff --git a/src/audit.ts b/src/audit.ts new file mode 100644 index 0000000..2e07484 --- /dev/null +++ b/src/audit.ts @@ -0,0 +1,8 @@ +import type { Construct } from 'constructs' +import * as cdk from 'aws-cdk-lib' + +export class AuditAccountStack extends cdk.Stack { + constructor(scope: Construct, id: string, props: cdk.StackProps) { + super(scope, id, props) + } +} diff --git a/src/avm.ts b/src/avm.ts index d184cbb..05e5cf1 100644 --- a/src/avm.ts +++ b/src/avm.ts @@ -25,7 +25,9 @@ function parseAccountsYamlFile(filePath: string): MyAccounts { return yamlData } -export class AccountVendingMachineStack extends cdk.Stack { +export class AVMStack extends cdk.Stack { + public auditAccountId: string = '0' + constructor(scope: Construct, id: string, props: cdk.StackProps) { super(scope, id, props) @@ -47,11 +49,14 @@ export class AccountVendingMachineStack extends cdk.Stack { if (!ou) { throw new Error(`Organizational Unit ${ouName} not found`) } - new CfnAccount(this, `Account-${account.Name!}`, { + const act = new CfnAccount(this, `Account-${account.Name!}`, { accountName: account.Name!, email: account.Email!, parentIds: [ou.ref], }) + if (account.Name === 'p6m7g8-audit') { + this.auditAccountId = act.ref + } }) } } diff --git a/bin/deploy.ts b/src/deploy.ts similarity index 53% rename from bin/deploy.ts rename to src/deploy.ts index 5fd925c..54ac4ae 100644 --- a/bin/deploy.ts +++ b/src/deploy.ts @@ -2,8 +2,9 @@ import process from 'node:process' import * as cdk from 'aws-cdk-lib' -import { AccountVendingMachineStack } from '../src/avm' -import { OrganizationStack } from '../src/organization' +import { AuditAccountStack } from './audit' +import { AVMStack } from './avm' +import { OrganizationStack } from './organization' const env = { account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, @@ -12,5 +13,11 @@ const env = { const app = new cdk.App() new OrganizationStack(app, 'p6-lz-organization', { env }) -new AccountVendingMachineStack(app, 'p6-lz-avm', { env }) +const avmStack = new AVMStack(app, 'p6-lz-avm', { env }) +new AuditAccountStack(app, 'p6-lz-audit', { + env: { + account: avmStack.auditAccountId, + region: env.region, + }, +}) app.synth() diff --git a/tsconfig.json b/tsconfig.json index 71bb214..7470d36 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,7 +30,7 @@ "skipLibCheck": true }, "include": [ - "bin/deploy.ts", + "src/deploy.ts", "jest.config.ts", "src/**/*.ts", "src/**/*.tsx",