22
33Automated bootstrap scripts for AWS multi-account infrastructure supporting GitHub Actions OIDC authentication.
44
5+ ## TL;DR
6+
7+ ** For fresh AWS accounts** :
8+ ``` bash
9+ cd scripts/bootstrap
10+ ./bootstrap-organization.sh # ~8 min - creates accounts
11+ ./bootstrap-foundation.sh # ~12 min - creates OIDC/roles/backends
12+ ./configure-github.sh # ~2 min - configures GitHub repo (optional)
13+ ```
14+
15+ ** For existing AWS Organizations** : See [ Existing Organization] ( #existing-organization-single-stage-bootstrap )
16+
17+ ** Jump to** : [ Prerequisites] ( #prerequisites ) | [ Configuration] ( #configuration ) | [ Security] ( #security-considerations ) | [ Troubleshooting] ( #troubleshooting )
18+
19+ ---
20+
21+ ## Script Directory Navigation
22+
23+ ** 📍 You are here** : ` scripts/bootstrap/ `
24+
25+ ** Workflow** : Bootstrap → Demo → Destroy
26+ - ** [ Bootstrap] ( ../bootstrap/ ) ** - Create AWS infrastructure ** (you are here)**
27+ - ** [ Demo] ( ../demo/ ) ** - Prepare and execute live demonstrations
28+ - ** [ Destroy] ( ../destroy/ ) ** - Clean up AWS resources
29+
30+ ** Related Documentation** :
31+ - [ Project README] ( ../../README.md )
32+ - [ Deployment Guide] ( ../../DEPLOYMENT.md )
33+ - [ Architecture Docs] ( ../../docs/architecture.md )
34+
35+ ---
36+
537## 📋 Overview
638
739This framework automates the creation of foundational AWS infrastructure required for GitHub Actions CI/CD pipelines:
@@ -13,17 +45,45 @@ This framework automates the creation of foundational AWS infrastructure require
1345
1446## 🏗️ Architecture
1547
16- ```
17- Management Account
18- ├── Workloads OU
19- │ └── <project-name> OU (derived from GITHUB_REPO)
20- │ ├── <project-name>-dev (Account)
21- │ ├── <project-name>-staging (Account)
22- │ └── <project-name>-prod (Account)
23- └── Bootstrap Resources
24- ├── OIDC Providers (per account)
25- ├── GitHub Actions Roles (per account)
26- └── Terraform Backends (per account)
48+ ``` mermaid
49+ %%{init: {'theme':'default', 'themeVariables': {'fontSize':'14px'}}}%%
50+ graph TD
51+ accTitle: AWS Organizations Multi-Account Architecture
52+ accDescr: Management account contains workloads organizational unit with project-specific OU derived from GitHub repository name. Project OU contains three member accounts for dev, staging, and production environments. Each account has OIDC providers, GitHub Actions deployment roles, and Terraform state backends.
53+
54+ MA[Management Account]
55+ WOU[Workloads OU]
56+ POU["<project-name> OU<br/><small>(from GITHUB_REPO)</small>"]
57+ DEV["<project-name>-dev<br/><small>(Member Account)</small>"]
58+ STAG["<project-name>-staging<br/><small>(Member Account)</small>"]
59+ PROD["<project-name>-prod<br/><small>(Member Account)</small>"]
60+
61+ BR[Bootstrap Resources<br/>per account]
62+ OIDC[OIDC Provider<br/>token.actions.githubusercontent.com]
63+ ROLES[IAM Roles<br/>GitHubActions-*<br/>ReadOnly-*]
64+ BACKEND[Terraform Backend<br/>S3 + DynamoDB + KMS]
65+
66+ MA --> WOU
67+ WOU --> POU
68+ POU --> DEV
69+ POU --> STAG
70+ POU --> PROD
71+
72+ MA -.-> BR
73+ BR --> OIDC
74+ BR --> ROLES
75+ BR --> BACKEND
76+
77+ style MA fill:#e1f5ff
78+ style WOU fill:#fff4e6
79+ style POU fill:#ffe6f0
80+ style DEV fill:#e6f7e6
81+ style STAG fill:#fff9e6
82+ style PROD fill:#ffe6e6
83+ style BR fill:#f0f0f0
84+ style OIDC fill:#e6f3ff
85+ style ROLES fill:#ffe6f7
86+ style BACKEND fill:#fff0e6
2787```
2888
2989** Note** : The project OU and account names are dynamically derived from the ` GITHUB_REPO ` variable in ` config.sh ` . For example, ` GITHUB_REPO="Celtikill/static-site" ` creates an OU named "static-site" with accounts "static-site-dev", "static-site-staging", and "static-site-prod".
@@ -34,13 +94,15 @@ Management Account
3494scripts/bootstrap/
3595├── config.sh # Central configuration
3696├── lib/ # Function libraries
37- │ ├── common.sh # Logging and utilities
38- │ ├── aws.sh # AWS CLI wrappers
39- │ ├── organization.sh # Organizations management
97+ │ ├── common.sh # Logging, progress, user interaction
98+ │ ├── aws.sh # AWS CLI wrappers with retry logic
99+ │ ├── organization.sh # Organizations, OUs, accounts, SCPs
40100│ ├── oidc.sh # OIDC provider functions
41- │ ├── roles.sh # IAM role management
42- │ ├── backends.sh # Terraform backend creation
43- │ └── verify.sh # Verification and testing
101+ │ ├── roles.sh # IAM role creation
102+ │ ├── policies.sh # IAM policy document generation
103+ │ ├── metadata.sh # AWS account metadata management
104+ │ ├── backends.sh # Terraform state backends (S3, DynamoDB, KMS)
105+ │ └── verify.sh # Verification and validation
44106├── templates/ # CloudFormation templates
45107│ └── oidc-stackset.yaml # OIDC provider StackSet
46108├── output/ # Generated files (git-ignored)
@@ -50,6 +112,7 @@ scripts/bootstrap/
50112├── bootstrap-organization.sh # Step 1: Create org structure
51113├── bootstrap-foundation.sh # Step 2: Create OIDC/roles/backends
52114├── configure-github.sh # Step 3: Configure GitHub repository (optional)
115+ ├── update-role-policy.sh # Maintenance: Update IAM deployment policies
53116├── destroy-foundation.sh # Cleanup bootstrap resources (granular options)
54117├── accounts.json # Account IDs (auto-generated)
55118└── accounts.json.example # Template file
@@ -58,10 +121,22 @@ scripts/bootstrap/
58121
59122### Prerequisites
60123
61- 1. **AWS CLI** installed and configured
62- 2. **Terraform/OpenTofu** installed (v1.6+)
63- 3. **AWS credentials** for management account (admin access)
64- 4. **jq** installed for JSON processing
124+ | Tool | Minimum Version | Installation |
125+ |------|----------------|--------------|
126+ | **AWS CLI** | 2.0+ | `brew install awscli` or [AWS Docs](https://aws.amazon.com/cli/) |
127+ | **Terraform/OpenTofu** | 1.6+ | `brew install opentofu` or [Download](https://opentofu.org/docs/intro/install/) |
128+ | **jq** | 1.6+ | `brew install jq` |
129+ | **GitHub CLI** (Step 3 only) | 2.0+ | `brew install gh` or [GitHub Docs](https://cli.github.com/) |
130+
131+ **Verify installation**:
132+ ```bash
133+ aws --version # Should show 2.x
134+ tofu version # Should show 1.6+
135+ jq --version # Should show 1.6+
136+ gh --version # Should show 2.x (optional)
137+ ```
138+
139+ ** AWS Credentials** : You must have admin access to the management account. Configure with ` aws configure ` or use AWS SSO.
65140
66141### Fresh AWS Account (Three-Step Bootstrap)
67142
@@ -129,7 +204,7 @@ cd scripts/bootstrap
129204%%{init: {'theme':'default', 'themeVariables': {'fontSize':'16px'}}}%%
130205graph TD
131206 accTitle: Bootstrap Path Decision and Workflow
132- accDescr: Two-path bootstrap strategy supporting both fresh AWS accounts and existing AWS Organizations with convergence to common workflow-based operations. Fresh AWS accounts start by running bootstrap-organization.sh creating a new AWS Organization with organizational units, service control policies, and account structure documented in the organizational design. The bootstrap-foundation.sh script then provisions foundational infrastructure including OIDC providers for GitHub Actions authentication, IAM roles for cross-account access, S3 state backends with encryption, and DynamoDB tables for state locking. The accounts.json file is committed to version control documenting account structure and enabling automated workflows. Existing AWS Organizations with established account structures can skip organization creation by manually updating accounts.json with existing account details then joining the common path at foundation bootstrap. After bootstrap completion, all infrastructure changes transition to workflow-based day-2 operations using GitHub Actions for consistency and audit trails. Infrastructure changes follow pull request workflows with peer review, automated testing, and approval gates before merge. Automated deployment via Actions executes after PR approval applying infrastructure changes through the BUILD-TEST-RUN pipeline ensuring security scanning, policy validation, and controlled deployment. This dual-path approach accommodates different starting points while converging to standardized operations enabling teams to adopt modern DevOps practices regardless of initial AWS configuration maturity.
207+ accDescr: Bootstrap path decision flow. Fresh AWS accounts execute bootstrap-organization.sh to create AWS Organization structure, then bootstrap-foundation.sh to provision OIDC providers, IAM roles, and Terraform backends. Existing AWS Organizations skip to foundation bootstrap after updating accounts.json manually. Both paths converge to GitHub Actions workflows for day-2 operations using PR-based reviews, automated testing, and controlled deployment. This dual-path approach supports different starting points while establishing consistent operational practices.
133208
134209 A[Fresh AWS Account] --> B[Run bootstrap-organization.sh]
135210 B --> C[Run bootstrap-foundation.sh]
@@ -364,39 +439,119 @@ EXAMPLES:
364439- Member accounts (unless ` --close-accounts ` is used)
365440- Application infrastructure
366441
367- ## 🔧 Configuration
442+ ### Update IAM Role Policies (Maintenance)
368443
369- ### Environment Variables
444+ Update IAM deployment policies for existing GitHub Actions roles after policy definition changes.
370445
371446``` bash
372- # Execution modes
373- export DRY_RUN=true # Simulate without changes
374- export VERBOSE=true # Enable detailed logging
375- export SKIP_VERIFICATION=true # Skip verification steps
447+ ./update-role-policy.sh [OPTIONS]
448+
449+ OPTIONS:
450+ -e, --environment ENV Target environment (dev, staging, prod, all)
451+ -d, --dry-run Preview policy changes without applying
452+ -v, --verbose Enable detailed output
453+ -h, --help Show help message
454+
455+ EXAMPLES:
456+ ./update-role-policy.sh --environment staging # Update staging role policy
457+ ./update-role-policy.sh --environment all # Update all environments
458+ ./update-role-policy.sh --environment dev --dry-run # Preview dev policy changes
459+ ```
460+
461+ ** When to use:**
462+ - After modifying IAM policy definitions in ` lib/roles.sh `
463+ - When deployment permissions need to be updated
464+ - After AWS service changes require policy adjustments
465+ - To align existing roles with updated security requirements
466+
467+ ** What it does:**
468+ - Retrieves current deployment policy from IAM role
469+ - Generates new policy from templates in ` lib/roles.sh `
470+ - Compares policies and shows differences
471+ - Updates role with new policy (unless ` --dry-run ` )
472+ - Validates policy update succeeded
473+
474+ ** Safety features:**
475+ - Dry-run mode shows policy diff before applying
476+ - Preserves role trust relationships (only updates permissions)
477+ - Validates syntax before applying changes
478+ - Can target specific environment to limit blast radius
479+
480+ ** Output:**
481+ ```
482+ Updating deployment policy for environment: staging
483+ Current policy version: v1
484+ Generated new policy from templates
485+
486+ Policy differences:
487+ + Added: s3:PutBucketPolicy
488+ + Added: cloudfront:CreateInvalidation
489+ - Removed: s3:DeleteBucket
376490
377- # Custom output directory
378- export OUTPUT_DIR=/path/to/output
491+ Apply policy update? [y/N]: y
492+ Policy updated successfully
493+ Validation: ✓ Role can be assumed
379494```
380495
381- ### Project Configuration
496+ ## 🔧 Configuration
497+
498+ ### Configuration Methods (Pick One)
382499
383- Edit ` config.sh ` to customize:
500+ This project supports multiple configuration approaches:
501+
502+ ** 1. Environment Variables** (Recommended for forks):
503+ ``` bash
504+ cp .env.example .env
505+ # Edit .env with your values
506+ source .env
507+ ```
508+
509+ ** 2. Interactive Prompts** (Easiest for first-time setup):
510+ ``` bash
511+ # Scripts will prompt for missing values
512+ ./bootstrap-organization.sh
513+ ```
384514
515+ ** 3. Direct Export** (For automation):
385516``` bash
386- readonly PROJECT_NAME=" <your-project-name>" # Used for resource naming
387- readonly GITHUB_REPO=" <org>/<repo>" # GitHub repository (e.g., "Celtikill/static-site")
388- readonly EXTERNAL_ID=" github-actions-<project>" # External ID for IAM roles
389- readonly AWS_DEFAULT_REGION=" us-east-2" # AWS region (authoritative source for all scripts)
390- readonly MANAGEMENT_ACCOUNT_ID=" <account-id>" # Management account ID
517+ export GITHUB_REPO=" YourOrg/your-repo"
518+ export PROJECT_SHORT_NAME=" your-project"
519+ export PROJECT_NAME=" yourorg-your-project"
391520```
392521
393- ** Important** : PROJECT_NAME should match your repository name for consistency. The project OU and account names will be derived from GITHUB_REPO.
522+ See [ .env.example] ( ../../.env.example ) for all available options.
523+
524+ ### Required Variables
525+
526+ | Variable | Description | Example |
527+ | ----------| -------------| ---------|
528+ | ` GITHUB_REPO ` | Repository in owner/repo format | ` "Celtikill/static-site" ` |
529+ | ` PROJECT_SHORT_NAME ` | Abbreviated name for IAM roles | ` "static-site" ` |
530+ | ` PROJECT_NAME ` | Full name for S3 buckets (must be globally unique) | ` "celtikill-static-site" ` |
531+
532+ ### Optional Variables
533+
534+ All optional variables have sensible defaults. See [ .env.example] ( ../../.env.example ) for the complete list:
535+
536+ - ` AWS_DEFAULT_REGION ` - AWS region (default: ` us-east-1 ` )
537+ - ` MANAGEMENT_ACCOUNT_ID ` - Auto-detected if not set
538+ - Account IDs - Loaded from ` accounts.json ` after organization bootstrap
539+
540+ ### Execution Mode Overrides
541+
542+ ``` bash
543+ # Override behavior without editing config
544+ export DRY_RUN=true # Simulate without changes
545+ export VERBOSE=true # Enable detailed logging
546+ export SKIP_VERIFICATION=true # Skip verification steps
547+ export OUTPUT_DIR=/custom/path # Custom output directory
548+ ```
394549
395550### Account Emails
396551
397- Default account creation emails (modify in ` lib/organization.sh ` ):
552+ Account creation emails (modify in ` lib/organization.sh ` if needed ):
398553``` bash
399- # Pattern : aws+<project-name>-<env>@example.com
554+ # Default pattern : aws+<project-name>-<env>@example.com
400555Dev: aws+< project-name> -dev@example.com
401556Staging: aws+< project-name> -staging@example.com
402557Prod: aws+< project-name> -prod@example.com
0 commit comments