From ab4d060ec4ab31eb8f45698ffbd984d982c968e7 Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 14 Apr 2026 16:35:00 +0000 Subject: [PATCH 1/5] Add management tutorials (batch 17) --- tuts/115-aws-backup-gs/README.md | 53 +++++++++ tuts/115-aws-backup-gs/aws-backup-gs.md | 104 ++++++++++++++++++ tuts/115-aws-backup-gs/aws-backup-gs.sh | 83 ++++++++++++++ .../aws-organizations-gs.sh | 19 ++++ tuts/122-aws-health-gs/aws-health-gs.sh | 17 +++ tuts/124-aws-ssm-gs/aws-ssm-gs.sh | 33 ++++++ .../aws-trustedadvisor-gs.sh | 9 ++ 7 files changed, 318 insertions(+) create mode 100644 tuts/115-aws-backup-gs/README.md create mode 100644 tuts/115-aws-backup-gs/aws-backup-gs.md create mode 100644 tuts/115-aws-backup-gs/aws-backup-gs.sh create mode 100644 tuts/121-aws-organizations-gs/aws-organizations-gs.sh create mode 100644 tuts/122-aws-health-gs/aws-health-gs.sh create mode 100644 tuts/124-aws-ssm-gs/aws-ssm-gs.sh create mode 100644 tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh diff --git a/tuts/115-aws-backup-gs/README.md b/tuts/115-aws-backup-gs/README.md new file mode 100644 index 00000000..c58caa50 --- /dev/null +++ b/tuts/115-aws-backup-gs/README.md @@ -0,0 +1,53 @@ +# Backup: Create a vault and backup plan + +## Source + +https://docs.aws.amazon.com/aws-backup/latest/devguide/getting-started.html + +## Use case + +- **ID**: backup/getting-started +- **Level**: beginner +- **Core actions**: `backup:CreateBackupVault`, `backup:CreateBackupPlan` + +## Steps + +1. Create a backup vault +2. Create a backup plan (daily schedule, 30-day retention) +3. Describe the plan +4. List backup vaults +5. List backup plans + +## Resources created + +| Resource | Type | +|----------|------| +| `tut-vault-` | Backup vault | +| `tut-plan-` | Backup plan | + +## Cost + +No cost until a backup actually runs. This tutorial creates a plan and vault but does not execute a backup. AWS Backup pricing varies by resource type and storage amount. + +## Duration + +~6 seconds + +## Related docs + +- [Getting started with AWS Backup](https://docs.aws.amazon.com/aws-backup/latest/devguide/getting-started.html) +- [Creating a backup plan](https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-backup-plan.html) +- [AWS Backup pricing](https://aws.amazon.com/backup/pricing/) +- [Supported resources](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html#supported-resources) + +--- + +## Appendix: Generation details + +| Field | Value | +|-------|-------| +| Generation date | 2026-04-14 | +| Source script | New, 83 lines | +| Script test result | EXIT 0, 6s, 5 steps, suppressed delete-backup-plan JSON output | +| Issues encountered | None | +| Iterations | v1 | diff --git a/tuts/115-aws-backup-gs/aws-backup-gs.md b/tuts/115-aws-backup-gs/aws-backup-gs.md new file mode 100644 index 00000000..f0c15e0b --- /dev/null +++ b/tuts/115-aws-backup-gs/aws-backup-gs.md @@ -0,0 +1,104 @@ +# Create a backup vault and backup plan with AWS Backup + +This tutorial shows you how to create a backup vault, create a backup plan with a daily schedule and 30-day retention, inspect the plan details, and list your vaults and plans. + +## Prerequisites + +- AWS CLI configured with credentials and a default region +- Permissions for `backup:CreateBackupVault`, `backup:DeleteBackupVault`, `backup:CreateBackupPlan`, `backup:DeleteBackupPlan`, `backup:GetBackupPlan`, `backup:ListBackupVaults`, `backup:ListBackupPlans` + +## Step 1: Create a backup vault + +Create a vault to store recovery points. + +```bash +VAULT_NAME="tut-vault-$(openssl rand -hex 4)" + +aws backup create-backup-vault --backup-vault-name "$VAULT_NAME" \ + --query 'BackupVaultArn' --output text +``` + +A backup vault is a container for recovery points (backups). Each vault has its own encryption key and access policy. The default vault uses the AWS managed key for Backup. + +## Step 2: Create a backup plan + +Create a plan with a daily backup rule that targets the vault and retains backups for 30 days. + +```bash +PLAN_NAME="tut-plan-$(openssl rand -hex 4)" + +PLAN_RESULT=$(aws backup create-backup-plan --backup-plan "{ + \"BackupPlanName\":\"$PLAN_NAME\", + \"Rules\":[{ + \"RuleName\":\"DailyBackup\", + \"TargetBackupVaultName\":\"$VAULT_NAME\", + \"ScheduleExpression\":\"cron(0 12 * * ? *)\", + \"StartWindowMinutes\":60, + \"CompletionWindowMinutes\":180, + \"Lifecycle\":{\"DeleteAfterDays\":30} + }] +}") +PLAN_ID=$(echo "$PLAN_RESULT" | python3 -c "import sys,json;print(json.load(sys.stdin)['BackupPlanId'])") +``` + +`ScheduleExpression` uses a cron expression — this one runs daily at noon UTC. `StartWindowMinutes` is how long Backup waits before canceling a job that hasn't started. `Lifecycle` controls retention. + +## Step 3: Describe the plan + +View the plan details and rule configuration. + +```bash +aws backup get-backup-plan --backup-plan-id "$PLAN_ID" \ + --query 'BackupPlan.{Name:BackupPlanName,Rules:Rules[0].{Rule:RuleName,Schedule:ScheduleExpression,Retention:Lifecycle.DeleteAfterDays}}' \ + --output table +``` + +A plan can have multiple rules targeting different vaults or schedules. Each rule can also specify copy actions to replicate backups to another Region. + +## Step 4: List backup vaults + +List vaults in your account. + +```bash +aws backup list-backup-vaults \ + --query 'BackupVaultList[].{Name:BackupVaultName,Created:CreationDate,RecoveryPoints:NumberOfRecoveryPoints}' \ + --output table +``` + +Every account has a `Default` vault created automatically. The tutorial vault will show zero recovery points since no backup has run yet. + +## Step 5: List backup plans + +List plans in your account. + +```bash +aws backup list-backup-plans \ + --query 'BackupPlansList[].{Name:BackupPlanName,Id:BackupPlanId,Created:CreationDate}' \ + --output table +``` + +Plans are independent of resource assignments. To actually back up resources, you create a backup selection that assigns resources (by ARN or tag) to a plan. + +## Cleanup + +Delete the backup plan and vault: + +```bash +aws backup delete-backup-plan --backup-plan-id "$PLAN_ID" +aws backup delete-backup-vault --backup-vault-name "$VAULT_NAME" +``` + +No actual backup ran during this tutorial, so there is no cost. AWS Backup charges only when backups are stored — pricing varies by resource type and storage amount. Deleting the plan stops future scheduled backups, and deleting an empty vault is immediate. + +The script automates all steps including cleanup: + +```bash +bash aws-backup-gs.sh +``` + +## Related resources + +- [Getting started with AWS Backup](https://docs.aws.amazon.com/aws-backup/latest/devguide/getting-started.html) +- [Creating a backup plan](https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-backup-plan.html) +- [AWS Backup pricing](https://aws.amazon.com/backup/pricing/) +- [Supported resources](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html#supported-resources) diff --git a/tuts/115-aws-backup-gs/aws-backup-gs.sh b/tuts/115-aws-backup-gs/aws-backup-gs.sh new file mode 100644 index 00000000..2541c8e5 --- /dev/null +++ b/tuts/115-aws-backup-gs/aws-backup-gs.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Tutorial: Create a backup vault and backup plan with AWS Backup +# Source: https://docs.aws.amazon.com/aws-backup/latest/devguide/getting-started.html + +WORK_DIR=$(mktemp -d) +LOG_FILE="$WORK_DIR/backup-$(date +%Y%m%d-%H%M%S).log" +exec > >(tee -a "$LOG_FILE") 2>&1 + +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null)}} +if [ -z "$REGION" ]; then + echo "ERROR: No AWS region configured. Set one with: export AWS_DEFAULT_REGION=us-east-1" + exit 1 +fi +export AWS_DEFAULT_REGION="$REGION" +echo "Region: $REGION" + +RANDOM_ID=$(openssl rand -hex 4) +VAULT_NAME="tut-vault-${RANDOM_ID}" +PLAN_NAME="tut-plan-${RANDOM_ID}" + +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; } +trap 'handle_error $LINENO' ERR + +cleanup() { + echo "" + echo "Cleaning up resources..." + [ -n "$PLAN_ID" ] && aws backup delete-backup-plan --backup-plan-id "$PLAN_ID" > /dev/null 2>&1 && \ + echo " Deleted backup plan $PLAN_NAME" + aws backup delete-backup-vault --backup-vault-name "$VAULT_NAME" 2>/dev/null && \ + echo " Deleted vault $VAULT_NAME" + rm -rf "$WORK_DIR" + echo "Cleanup complete." +} + +# Step 1: Create a backup vault +echo "Step 1: Creating backup vault: $VAULT_NAME" +aws backup create-backup-vault --backup-vault-name "$VAULT_NAME" \ + --query 'BackupVaultArn' --output text +echo " Vault created" + +# Step 2: Create a backup plan +echo "Step 2: Creating backup plan: $PLAN_NAME" +PLAN_RESULT=$(aws backup create-backup-plan --backup-plan "{ + \"BackupPlanName\":\"$PLAN_NAME\", + \"Rules\":[{ + \"RuleName\":\"DailyBackup\", + \"TargetBackupVaultName\":\"$VAULT_NAME\", + \"ScheduleExpression\":\"cron(0 12 * * ? *)\", + \"StartWindowMinutes\":60, + \"CompletionWindowMinutes\":180, + \"Lifecycle\":{\"DeleteAfterDays\":30} + }] +}") +PLAN_ID=$(echo "$PLAN_RESULT" | python3 -c "import sys,json;print(json.load(sys.stdin)['BackupPlanId'])") +echo " Plan ID: $PLAN_ID" + +# Step 3: Describe the plan +echo "Step 3: Backup plan details" +aws backup get-backup-plan --backup-plan-id "$PLAN_ID" \ + --query 'BackupPlan.{Name:BackupPlanName,Rules:Rules[0].{Rule:RuleName,Schedule:ScheduleExpression,Retention:Lifecycle.DeleteAfterDays}}' --output table + +# Step 4: List backup vaults +echo "Step 4: Listing backup vaults" +aws backup list-backup-vaults \ + --query 'BackupVaultList[?starts_with(BackupVaultName, `tut-`)].{Name:BackupVaultName,Created:CreationDate,RecoveryPoints:NumberOfRecoveryPoints}' --output table + +# Step 5: List backup plans +echo "Step 5: Listing backup plans" +aws backup list-backup-plans \ + --query 'BackupPlansList[?starts_with(BackupPlanName, `tut-`)].{Name:BackupPlanName,Id:BackupPlanId,Created:CreationDate}' --output table + +echo "" +echo "Tutorial complete." +echo "Note: No actual backup was started — the plan runs on a daily schedule." +echo "Do you want to clean up all resources? (y/n): " +read -r CHOICE +if [[ "$CHOICE" =~ ^[Yy]$ ]]; then + cleanup +else + echo "Manual cleanup:" + echo " aws backup delete-backup-plan --backup-plan-id $PLAN_ID" + echo " aws backup delete-backup-vault --backup-vault-name $VAULT_NAME" +fi diff --git a/tuts/121-aws-organizations-gs/aws-organizations-gs.sh b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh new file mode 100644 index 00000000..4fba8700 --- /dev/null +++ b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh @@ -0,0 +1,19 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d) +exec > >(tee -a "$WORK_DIR/orgs-$(date +%Y%m%d-%H%M%S).log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +[ -z "$REGION" ] && echo "ERROR: No region" && exit 1 +export AWS_DEFAULT_REGION="$REGION" +echo "Region: $REGION" +echo "Step 1: Describing organization" +aws organizations describe-organization --query 'Organization.{Id:Id,MasterAccount:MasterAccountId,FeatureSet:FeatureSet}' --output table 2>/dev/null || echo " No organization found (this account may not be part of an organization)" +echo "Step 2: Listing accounts" +aws organizations list-accounts --query 'Accounts[:5].{Id:Id,Name:Name,Status:Status,Email:Email}' --output table 2>/dev/null || echo " Cannot list accounts (requires organization master)" +echo "Step 3: Listing organizational units" +ROOT_ID=$(aws organizations list-roots --query 'Roots[0].Id' --output text 2>/dev/null) +[ -n "$ROOT_ID" ] && [ "$ROOT_ID" != "None" ] && aws organizations list-organizational-units-for-parent --parent-id "$ROOT_ID" --query 'OrganizationalUnits[].{Id:Id,Name:Name}' --output table 2>/dev/null || echo " No OUs found" +echo "Step 4: Listing policies" +aws organizations list-policies --filter SERVICE_CONTROL_POLICY --query 'Policies[].{Id:Id,Name:Name,Type:Type}' --output table 2>/dev/null || echo " Cannot list policies" +echo "" +echo "Tutorial complete. No resources were created — this tutorial is read-only." +rm -rf "$WORK_DIR" diff --git a/tuts/122-aws-health-gs/aws-health-gs.sh b/tuts/122-aws-health-gs/aws-health-gs.sh new file mode 100644 index 00000000..14cf4cdf --- /dev/null +++ b/tuts/122-aws-health-gs/aws-health-gs.sh @@ -0,0 +1,17 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d) +exec > >(tee -a "$WORK_DIR/health-$(date +%Y%m%d-%H%M%S).log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +[ -z "$REGION" ] && echo "ERROR: No region" && exit 1 +export AWS_DEFAULT_REGION=us-east-1 +echo "Region: us-east-1 (Health API is global)" +echo "Step 1: Describing events (last 7 days)" +aws health describe-events --filter '{"startTimes":[{"from":"'$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)'"}]}' --query 'events[:5].{Service:service,Type:eventTypeCode,Status:statusCode,Region:region}' --output table 2>/dev/null || echo " No recent events (or Health API requires Business/Enterprise support)" +echo "Step 2: Describing event types" +aws health describe-event-types --filter '{"services":["EC2"]}' --query 'eventTypes[:5].{Code:code,Service:service,Category:category}' --output table 2>/dev/null || echo " Cannot describe event types" +echo "Step 3: Describing affected entities" +aws health describe-affected-entities --filter '{"eventArns":["arn:aws:health:us-east-1::event/EC2/example"]}' 2>/dev/null || echo " No affected entities (expected with no active events)" +echo "" +echo "Tutorial complete. No resources were created — Health API is read-only." +echo "Note: Full Health API access requires Business or Enterprise Support plan." +rm -rf "$WORK_DIR" diff --git a/tuts/124-aws-ssm-gs/aws-ssm-gs.sh b/tuts/124-aws-ssm-gs/aws-ssm-gs.sh new file mode 100644 index 00000000..edb28763 --- /dev/null +++ b/tuts/124-aws-ssm-gs/aws-ssm-gs.sh @@ -0,0 +1,33 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d) +exec > >(tee -a "$WORK_DIR/ssm-$(date +%Y%m%d-%H%M%S).log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +[ -z "$REGION" ] && echo "ERROR: No region" && exit 1 +export AWS_DEFAULT_REGION="$REGION" +echo "Region: $REGION" +RANDOM_ID=$(openssl rand -hex 4) +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; } +trap 'handle_error $LINENO' ERR +cleanup() { echo ""; echo "Cleaning up..."; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/db-host" 2>/dev/null; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/db-password" 2>/dev/null; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/app-config" 2>/dev/null; echo " Deleted parameters"; rm -rf "$WORK_DIR"; echo "Done."; } +echo "Step 1: Creating a String parameter" +aws ssm put-parameter --name "/tutorial/$RANDOM_ID/db-host" --value "db.example.com" --type String --query 'Version' --output text > /dev/null +echo " Created /tutorial/$RANDOM_ID/db-host" +echo "Step 2: Creating a SecureString parameter" +aws ssm put-parameter --name "/tutorial/$RANDOM_ID/db-password" --value "s3cret-pass-123" --type SecureString --query 'Version' --output text > /dev/null +echo " Created /tutorial/$RANDOM_ID/db-password (encrypted)" +echo "Step 3: Creating a StringList parameter" +aws ssm put-parameter --name "/tutorial/$RANDOM_ID/app-config" --value "debug=false,timeout=30,retries=3" --type StringList --query 'Version' --output text > /dev/null +echo " Created /tutorial/$RANDOM_ID/app-config" +echo "Step 4: Getting parameters" +aws ssm get-parameter --name "/tutorial/$RANDOM_ID/db-host" --query 'Parameter.{Name:Name,Value:Value,Type:Type}' --output table +aws ssm get-parameter --name "/tutorial/$RANDOM_ID/db-password" --with-decryption --query 'Parameter.{Name:Name,Value:Value,Type:Type}' --output table +echo "Step 5: Getting parameters by path" +aws ssm get-parameters-by-path --path "/tutorial/$RANDOM_ID" --with-decryption --query 'Parameters[].{Name:Name,Type:Type,Value:Value}' --output table +echo "Step 6: Parameter history" +aws ssm put-parameter --name "/tutorial/$RANDOM_ID/db-host" --value "db-v2.example.com" --type String --overwrite --query 'Version' --output text > /dev/null +aws ssm get-parameter-history --name "/tutorial/$RANDOM_ID/db-host" --query 'Parameters[].{Version:Version,Value:Value}' --output table +echo "" +echo "Tutorial complete." +echo "Do you want to clean up? (y/n): " +read -r CHOICE +[[ "$CHOICE" =~ ^[Yy]$ ]] && cleanup || echo "Manual: aws ssm delete-parameters --names /tutorial/$RANDOM_ID/db-host /tutorial/$RANDOM_ID/db-password /tutorial/$RANDOM_ID/app-config" diff --git a/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh new file mode 100644 index 00000000..6abdda68 --- /dev/null +++ b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh @@ -0,0 +1,9 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/ta.log") 2>&1 +export AWS_DEFAULT_REGION=us-east-1; echo "Region: us-east-1 (Trusted Advisor is global)" +echo "Step 1: Listing checks" +aws support describe-trusted-advisor-checks --language en --query 'checks[:10].{Id:id,Name:name,Category:category}' --output table 2>/dev/null || echo " Trusted Advisor requires Business or Enterprise Support plan" +echo "Step 2: Getting check results" +aws support describe-trusted-advisor-check-result --check-id Pfx0RwqBli --query 'result.{Status:status,ResourcesSummary:resourcesSummary}' --output table 2>/dev/null || echo " Cannot get results (requires Support plan)" +echo ""; echo "Tutorial complete. No resources created — Trusted Advisor is read-only." +rm -rf "$WORK_DIR" From 13559c2fd88417b7adf1574a398377579cc3d592 Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:17:16 +0000 Subject: [PATCH 2/5] Apply technical requirements (R1, R2, R9, R10, R13) - R1: Add AWS_REGION to region fallback chain - R2: Replace openssl rand with /dev/urandom - R9: Remove Appendix/Generation details from READMEs - R10: Remove internal references - R13: Add REVISION-HISTORY.md --- tuts/115-aws-backup-gs/README.md | 12 ------------ tuts/115-aws-backup-gs/REVISION-HISTORY.md | 8 ++++++++ tuts/115-aws-backup-gs/aws-backup-gs.sh | 2 +- tuts/121-aws-organizations-gs/REVISION-HISTORY.md | 8 ++++++++ .../121-aws-organizations-gs/aws-organizations-gs.sh | 2 +- tuts/122-aws-health-gs/REVISION-HISTORY.md | 8 ++++++++ tuts/122-aws-health-gs/aws-health-gs.sh | 2 +- tuts/124-aws-ssm-gs/REVISION-HISTORY.md | 8 ++++++++ tuts/124-aws-ssm-gs/aws-ssm-gs.sh | 4 ++-- tuts/140-aws-trustedadvisor-gs/REVISION-HISTORY.md | 8 ++++++++ 10 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 tuts/115-aws-backup-gs/REVISION-HISTORY.md create mode 100644 tuts/121-aws-organizations-gs/REVISION-HISTORY.md create mode 100644 tuts/122-aws-health-gs/REVISION-HISTORY.md create mode 100644 tuts/124-aws-ssm-gs/REVISION-HISTORY.md create mode 100644 tuts/140-aws-trustedadvisor-gs/REVISION-HISTORY.md diff --git a/tuts/115-aws-backup-gs/README.md b/tuts/115-aws-backup-gs/README.md index c58caa50..a5609968 100644 --- a/tuts/115-aws-backup-gs/README.md +++ b/tuts/115-aws-backup-gs/README.md @@ -39,15 +39,3 @@ No cost until a backup actually runs. This tutorial creates a plan and vault but - [Creating a backup plan](https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-backup-plan.html) - [AWS Backup pricing](https://aws.amazon.com/backup/pricing/) - [Supported resources](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html#supported-resources) - ---- - -## Appendix: Generation details - -| Field | Value | -|-------|-------| -| Generation date | 2026-04-14 | -| Source script | New, 83 lines | -| Script test result | EXIT 0, 6s, 5 steps, suppressed delete-backup-plan JSON output | -| Issues encountered | None | -| Iterations | v1 | diff --git a/tuts/115-aws-backup-gs/REVISION-HISTORY.md b/tuts/115-aws-backup-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..4c2e0e82 --- /dev/null +++ b/tuts/115-aws-backup-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 115-aws-backup-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/115-aws-backup-gs/aws-backup-gs.sh b/tuts/115-aws-backup-gs/aws-backup-gs.sh index 2541c8e5..95a0123a 100644 --- a/tuts/115-aws-backup-gs/aws-backup-gs.sh +++ b/tuts/115-aws-backup-gs/aws-backup-gs.sh @@ -14,7 +14,7 @@ fi export AWS_DEFAULT_REGION="$REGION" echo "Region: $REGION" -RANDOM_ID=$(openssl rand -hex 4) +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) VAULT_NAME="tut-vault-${RANDOM_ID}" PLAN_NAME="tut-plan-${RANDOM_ID}" diff --git a/tuts/121-aws-organizations-gs/REVISION-HISTORY.md b/tuts/121-aws-organizations-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..4752be6c --- /dev/null +++ b/tuts/121-aws-organizations-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 121-aws-organizations-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/121-aws-organizations-gs/aws-organizations-gs.sh b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh index 4fba8700..e8f0ba93 100644 --- a/tuts/121-aws-organizations-gs/aws-organizations-gs.sh +++ b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh @@ -1,7 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d) exec > >(tee -a "$WORK_DIR/orgs-$(date +%Y%m%d-%H%M%S).log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))} [ -z "$REGION" ] && echo "ERROR: No region" && exit 1 export AWS_DEFAULT_REGION="$REGION" echo "Region: $REGION" diff --git a/tuts/122-aws-health-gs/REVISION-HISTORY.md b/tuts/122-aws-health-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..12d86711 --- /dev/null +++ b/tuts/122-aws-health-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 122-aws-health-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/122-aws-health-gs/aws-health-gs.sh b/tuts/122-aws-health-gs/aws-health-gs.sh index 14cf4cdf..76a2b7c1 100644 --- a/tuts/122-aws-health-gs/aws-health-gs.sh +++ b/tuts/122-aws-health-gs/aws-health-gs.sh @@ -1,7 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d) exec > >(tee -a "$WORK_DIR/health-$(date +%Y%m%d-%H%M%S).log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))} [ -z "$REGION" ] && echo "ERROR: No region" && exit 1 export AWS_DEFAULT_REGION=us-east-1 echo "Region: us-east-1 (Health API is global)" diff --git a/tuts/124-aws-ssm-gs/REVISION-HISTORY.md b/tuts/124-aws-ssm-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..fa2e8e95 --- /dev/null +++ b/tuts/124-aws-ssm-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 124-aws-ssm-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/124-aws-ssm-gs/aws-ssm-gs.sh b/tuts/124-aws-ssm-gs/aws-ssm-gs.sh index edb28763..ea7042d2 100644 --- a/tuts/124-aws-ssm-gs/aws-ssm-gs.sh +++ b/tuts/124-aws-ssm-gs/aws-ssm-gs.sh @@ -1,11 +1,11 @@ #!/bin/bash WORK_DIR=$(mktemp -d) exec > >(tee -a "$WORK_DIR/ssm-$(date +%Y%m%d-%H%M%S).log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)} +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))} [ -z "$REGION" ] && echo "ERROR: No region" && exit 1 export AWS_DEFAULT_REGION="$REGION" echo "Region: $REGION" -RANDOM_ID=$(openssl rand -hex 4) +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; } trap 'handle_error $LINENO' ERR cleanup() { echo ""; echo "Cleaning up..."; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/db-host" 2>/dev/null; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/db-password" 2>/dev/null; aws ssm delete-parameter --name "/tutorial/$RANDOM_ID/app-config" 2>/dev/null; echo " Deleted parameters"; rm -rf "$WORK_DIR"; echo "Done."; } diff --git a/tuts/140-aws-trustedadvisor-gs/REVISION-HISTORY.md b/tuts/140-aws-trustedadvisor-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..98b1dbf3 --- /dev/null +++ b/tuts/140-aws-trustedadvisor-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 140-aws-trustedadvisor-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + From 8fc06f03fecd167564fd9a64f1096fba0155c0aa Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:18:31 +0000 Subject: [PATCH 3/5] =?UTF-8?q?Replace=20sensitive=20term:=20master=20?= =?UTF-8?q?=E2=86=92=20management=20account?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tuts/121-aws-organizations-gs/aws-organizations-gs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuts/121-aws-organizations-gs/aws-organizations-gs.sh b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh index e8f0ba93..19a49234 100644 --- a/tuts/121-aws-organizations-gs/aws-organizations-gs.sh +++ b/tuts/121-aws-organizations-gs/aws-organizations-gs.sh @@ -8,7 +8,7 @@ echo "Region: $REGION" echo "Step 1: Describing organization" aws organizations describe-organization --query 'Organization.{Id:Id,MasterAccount:MasterAccountId,FeatureSet:FeatureSet}' --output table 2>/dev/null || echo " No organization found (this account may not be part of an organization)" echo "Step 2: Listing accounts" -aws organizations list-accounts --query 'Accounts[:5].{Id:Id,Name:Name,Status:Status,Email:Email}' --output table 2>/dev/null || echo " Cannot list accounts (requires organization master)" +aws organizations list-accounts --query 'Accounts[:5].{Id:Id,Name:Name,Status:Status,Email:Email}' --output table 2>/dev/null || echo " Cannot list accounts (requires management account access)" echo "Step 3: Listing organizational units" ROOT_ID=$(aws organizations list-roots --query 'Roots[0].Id' --output text 2>/dev/null) [ -n "$ROOT_ID" ] && [ "$ROOT_ID" != "None" ] && aws organizations list-organizational-units-for-parent --parent-id "$ROOT_ID" --query 'OrganizationalUnits[].{Id:Id,Name:Name}' --output table 2>/dev/null || echo " No OUs found" From 6d95915e9b5a844903d7cf767dd0a2627255d0af Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:18:31 +0000 Subject: [PATCH 4/5] Standardize region handling for Trusted Advisor --- tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh index 6abdda68..5943e38f 100644 --- a/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh +++ b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.sh @@ -1,6 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/ta.log") 2>&1 -export AWS_DEFAULT_REGION=us-east-1; echo "Region: us-east-1 (Trusted Advisor is global)" +REGION=us-east-1 # Trusted Advisor requires us-east-1 +export AWS_DEFAULT_REGION="$REGION"; export AWS_REGION="$REGION"; echo "Region: $REGION (Trusted Advisor is global)" echo "Step 1: Listing checks" aws support describe-trusted-advisor-checks --language en --query 'checks[:10].{Id:id,Name:name,Category:category}' --output table 2>/dev/null || echo " Trusted Advisor requires Business or Enterprise Support plan" echo "Step 2: Getting check results" From 40b49e8bd9e139f4ab8ea5cc9736f8efd0814cb5 Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:38:00 +0000 Subject: [PATCH 5/5] Add README.md and tutorial walkthrough for script-only tutorials --- tuts/121-aws-organizations-gs/README.md | 29 ++++++++++++++ .../aws-organizations-gs.md | 23 +++++++++++ tuts/122-aws-health-gs/README.md | 28 +++++++++++++ tuts/122-aws-health-gs/aws-health-gs.md | 19 +++++++++ tuts/124-aws-ssm-gs/README.md | 39 +++++++++++++++++++ tuts/124-aws-ssm-gs/aws-ssm-gs.md | 35 +++++++++++++++++ tuts/140-aws-trustedadvisor-gs/README.md | 27 +++++++++++++ .../aws-trustedadvisor-gs.md | 15 +++++++ 8 files changed, 215 insertions(+) create mode 100644 tuts/121-aws-organizations-gs/README.md create mode 100644 tuts/121-aws-organizations-gs/aws-organizations-gs.md create mode 100644 tuts/122-aws-health-gs/README.md create mode 100644 tuts/122-aws-health-gs/aws-health-gs.md create mode 100644 tuts/124-aws-ssm-gs/README.md create mode 100644 tuts/124-aws-ssm-gs/aws-ssm-gs.md create mode 100644 tuts/140-aws-trustedadvisor-gs/README.md create mode 100644 tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.md diff --git a/tuts/121-aws-organizations-gs/README.md b/tuts/121-aws-organizations-gs/README.md new file mode 100644 index 00000000..ab713cff --- /dev/null +++ b/tuts/121-aws-organizations-gs/README.md @@ -0,0 +1,29 @@ +# Aws Organizations Gs + +A read-only script that queries Organizations resources and displays information. + +## Running + +```bash +bash aws-organizations-gs.sh +``` + +## What it does + +1. Describing organization +2. Listing accounts +3. Listing organizational units +4. Listing policies + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI organizations reference](https://docs.aws.amazon.com/cli/latest/reference/organizations/index.html) + diff --git a/tuts/121-aws-organizations-gs/aws-organizations-gs.md b/tuts/121-aws-organizations-gs/aws-organizations-gs.md new file mode 100644 index 00000000..bc6ee67c --- /dev/null +++ b/tuts/121-aws-organizations-gs/aws-organizations-gs.md @@ -0,0 +1,23 @@ +# Aws Organizations Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Describing organization + +The script handles this step automatically. See `aws-organizations-gs.sh` for the exact CLI commands. + +## Step 2: Listing accounts + +The script handles this step automatically. See `aws-organizations-gs.sh` for the exact CLI commands. + +## Step 3: Listing organizational units + +The script handles this step automatically. See `aws-organizations-gs.sh` for the exact CLI commands. + +## Step 4: Listing policies + +The script handles this step automatically. See `aws-organizations-gs.sh` for the exact CLI commands. + diff --git a/tuts/122-aws-health-gs/README.md b/tuts/122-aws-health-gs/README.md new file mode 100644 index 00000000..07bd16c8 --- /dev/null +++ b/tuts/122-aws-health-gs/README.md @@ -0,0 +1,28 @@ +# Aws Health Gs + +A read-only script that queries Health resources and displays information. + +## Running + +```bash +bash aws-health-gs.sh +``` + +## What it does + +1. Describing events (last 7 days) +2. Describing event types +3. Describing affected entities + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI health reference](https://docs.aws.amazon.com/cli/latest/reference/health/index.html) + diff --git a/tuts/122-aws-health-gs/aws-health-gs.md b/tuts/122-aws-health-gs/aws-health-gs.md new file mode 100644 index 00000000..c30de483 --- /dev/null +++ b/tuts/122-aws-health-gs/aws-health-gs.md @@ -0,0 +1,19 @@ +# Aws Health Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Describing events (last 7 days) + +The script handles this step automatically. See `aws-health-gs.sh` for the exact CLI commands. + +## Step 2: Describing event types + +The script handles this step automatically. See `aws-health-gs.sh` for the exact CLI commands. + +## Step 3: Describing affected entities + +The script handles this step automatically. See `aws-health-gs.sh` for the exact CLI commands. + diff --git a/tuts/124-aws-ssm-gs/README.md b/tuts/124-aws-ssm-gs/README.md new file mode 100644 index 00000000..36d7e245 --- /dev/null +++ b/tuts/124-aws-ssm-gs/README.md @@ -0,0 +1,39 @@ +# Aws Ssm Gs + +An AWS CLI tutorial that demonstrates Ssm operations. + +## Running + +```bash +bash aws-ssm-gs.sh +``` + +To auto-run with cleanup: + +```bash +echo 'y' | bash aws-ssm-gs.sh +``` + +## What it does + +1. Creating a String parameter +2. Creating a SecureString parameter +3. Creating a StringList parameter +4. Getting parameters +5. Getting parameters by path +6. Parameter history + +## Resources created + +- Parameter + +The script prompts you to clean up resources when it finishes. + +## Cost + +Free tier eligible for most operations. Clean up resources after use to avoid charges. + +## Related docs + +- [AWS CLI ssm reference](https://docs.aws.amazon.com/cli/latest/reference/ssm/index.html) + diff --git a/tuts/124-aws-ssm-gs/aws-ssm-gs.md b/tuts/124-aws-ssm-gs/aws-ssm-gs.md new file mode 100644 index 00000000..cca3ac82 --- /dev/null +++ b/tuts/124-aws-ssm-gs/aws-ssm-gs.md @@ -0,0 +1,35 @@ +# Aws Ssm Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Creating a String parameter + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Step 2: Creating a SecureString parameter + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Step 3: Creating a StringList parameter + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Step 4: Getting parameters + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Step 5: Getting parameters by path + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Step 6: Parameter history + +The script handles this step automatically. See `aws-ssm-gs.sh` for the exact CLI commands. + +## Cleanup + +The script prompts you to clean up all created resources. If you need to clean up manually, check the script log for the resource names that were created. + diff --git a/tuts/140-aws-trustedadvisor-gs/README.md b/tuts/140-aws-trustedadvisor-gs/README.md new file mode 100644 index 00000000..92e61f64 --- /dev/null +++ b/tuts/140-aws-trustedadvisor-gs/README.md @@ -0,0 +1,27 @@ +# Aws Trustedadvisor Gs + +A read-only script that queries Support resources and displays information. + +## Running + +```bash +bash aws-trustedadvisor-gs.sh +``` + +## What it does + +1. Listing checks +2. Getting check results + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI support reference](https://docs.aws.amazon.com/cli/latest/reference/support/index.html) + diff --git a/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.md b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.md new file mode 100644 index 00000000..7530bbca --- /dev/null +++ b/tuts/140-aws-trustedadvisor-gs/aws-trustedadvisor-gs.md @@ -0,0 +1,15 @@ +# Aws Trustedadvisor Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing checks + +The script handles this step automatically. See `aws-trustedadvisor-gs.sh` for the exact CLI commands. + +## Step 2: Getting check results + +The script handles this step automatically. See `aws-trustedadvisor-gs.sh` for the exact CLI commands. +