{"id":31078090,"url":"https://github.com/itsnotsagar/aws-tf-close-account","last_synced_at":"2025-10-10T09:13:00.383Z","repository":{"id":314938273,"uuid":"1057405093","full_name":"itsnotsagar/aws-tf-close-account","owner":"itsnotsagar","description":"Automated AWS account closure solution using Terraform and Lambda. Integrates with AWS Control Tower and AFT to securely close accounts, terminate Service Catalog products, and move accounts to suspended OUs via GitLab CI/CD pipeline.","archived":false,"fork":false,"pushed_at":"2025-09-15T18:03:13.000Z","size":275,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-15T19:30:48.045Z","etag":null,"topics":["aft","aws","controltower","gitlab","lambda","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itsnotsagar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-15T17:22:07.000Z","updated_at":"2025-09-15T18:02:50.000Z","dependencies_parsed_at":"2025-09-15T19:30:57.227Z","dependency_job_id":null,"html_url":"https://github.com/itsnotsagar/aws-tf-close-account","commit_stats":null,"previous_names":["itsnotsagar/aws-tf-close-account"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/itsnotsagar/aws-tf-close-account","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itsnotsagar%2Faws-tf-close-account","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itsnotsagar%2Faws-tf-close-account/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itsnotsagar%2Faws-tf-close-account/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itsnotsagar%2Faws-tf-close-account/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itsnotsagar","download_url":"https://codeload.github.com/itsnotsagar/aws-tf-close-account/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itsnotsagar%2Faws-tf-close-account/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275384116,"owners_count":25454910,"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","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["aft","aws","controltower","gitlab","lambda","terraform"],"created_at":"2025-09-16T08:02:57.843Z","updated_at":"2025-09-16T08:03:26.073Z","avatar_url":"https://github.com/itsnotsagar.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AWS Terraform Account Closure Automation\n\nAn automated solution for closing and suspending AWS accounts in AWS Control Tower environments using Terraform and Lambda functions. This project provides a secure, event-driven approach to account lifecycle management with proper governance controls.\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Architecture](#architecture)\n- [Features](#features)\n- [Prerequisites](#prerequisites)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n- [Deployment](#deployment)\n- [How It Works](#how-it-works)\n- [Security](#security)\n- [Monitoring](#monitoring)\n- [Troubleshooting](#troubleshooting)\n- [Best Practices](#best-practices)\n- [Contributing](#contributing)\n\n## Overview\n\nThis solution automates the process of closing AWS accounts within an AWS Control Tower environment. When an account removal request is detected in the AFT (Account Factory for Terraform) audit trail, the system automatically:\n\n1. Terminates the Service Catalog provisioned product\n2. Moves the account to a SUSPENDED organizational unit\n3. Closes the AWS account permanently\n\nThe automation ensures proper governance, audit trails, and secure cross-account operations.\n\n## Architecture\n\n```\n┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐\n│   AFT Account   │    │  Control Tower   │    │   Target OU     │\n│                 │    │    Account       │    │  (SUSPENDED)    │\n├─────────────────┤    ├──────────────────┤    ├─────────────────┤\n│ DynamoDB Stream │───▶│ Lambda Function  │───▶│ Closed Account  │\n│ (Audit Trail)   │    │ (Account Closer) │    │                 │\n│                 │    │                  │    │                 │\n│ IAM Role        │    │ Service Catalog  │    │                 │\n│ (Lambda Exec)   │    │ Organizations    │    │                 │\n└─────────────────┘    └──────────────────┘    └─────────────────┘\n```\n\n### Components\n\n- **AFT Account**: Contains the Lambda function and DynamoDB stream trigger\n- **Control Tower Account**: Provides cross-account role for account operations\n- **Lambda Function**: Processes account closure requests\n- **DynamoDB Stream**: Triggers automation on audit trail changes\n- **IAM Roles**: Secure cross-account access with least privilege\n\n## Features\n\n- **Event-Driven**: Automatically triggered by AFT audit trail changes\n- **Secure**: Cross-account role assumption with minimal permissions\n- **Auditable**: Comprehensive logging and CloudWatch integration\n- **Resilient**: Error handling and retry mechanisms\n- **Configurable**: Customizable organizational units and timeouts\n- **Code Signing**: Lambda functions are signed for security\n- **Monitoring**: CloudWatch logs with configurable retention\n\n## Prerequisites\n\nBefore deploying this solution, ensure you have:\n\n### AWS Environment\n- AWS Control Tower deployed and configured\n- Account Factory for Terraform (AFT) set up\n- Appropriate AWS Organizations structure with SUSPENDED OU\n- Cross-account trust relationships configured\n\n### Permissions\n- Administrative access to AFT management account\n- Administrative access to Control Tower management account\n- Permissions to create IAM roles and policies\n- Permissions to deploy Lambda functions\n\n### Tools\n- Terraform \u003e= 1.0\n- AWS CLI configured\n- Python 3.11 (for Lambda runtime)\n\n## Quick Start\n\n### Prerequisites Setup\n\n1. **GitLab Runner Configuration:**\n   ```bash\n   # Ensure runner has required tags\n   tags: [\"test-runner\"]\n   \n   # Install required tools on runner\n   terraform --version  # \u003e= 0.15.0\n   aws --version        # Latest AWS CLI\n   ```\n\n2. **AWS Credentials:**\n   ```bash\n   # Configure runner with appropriate AWS credentials\n   # Must have access to assume roles in both AFT and CT accounts\n   export AWS_ACCESS_KEY_ID=\"your-access-key\"\n   export AWS_SECRET_ACCESS_KEY=\"your-secret-key\"\n   export AWS_DEFAULT_REGION=\"eu-west-1\"\n   ```\n\n### Deployment via GitLab CI/CD\n\n1. **Clone and configure:**\n   ```bash\n   git clone \u003crepository-url\u003e\n   cd aws-tf-close-account\n   ```\n\n2. **Update configuration:**\n   ```bash\n   # Edit close-and-suspend/configuration/main.tf\n   # Update account IDs, OUs, and other environment-specific values\n   ```\n\n3. **Deploy via pipeline:**\n   ```bash\n   git add .\n   git commit -m \"Configure account closure automation\"\n   git push origin main\n   ```\n\n4. **Monitor deployment:**\n   - Navigate to GitLab → CI/CD → Pipelines\n   - Review terraform-plan-close-and-suspend job output\n   - Verify terraform-apply-close-and-suspend completes successfully\n\n5. **Verify deployment:**\n   - Check AWS Lambda console for `aft-close-account-lambda`\n   - Verify IAM roles in both AFT and CT accounts\n   - Review CloudWatch logs for any initialization issues\n\n### Manual Deployment (Alternative)\n\nIf you prefer manual deployment or need to troubleshoot:\n\n1. **Local setup:**\n   ```bash\n   cd close-and-suspend/configuration\n   terraform init\n   ```\n\n2. **Plan and apply:**\n   ```bash\n   terraform plan -out=tfplan\n   terraform apply tfplan\n   ```\n\n3. **Cleanup (if needed):**\n   ```bash\n   terraform destroy\n   ```\n\n## Configuration\n\n### Required Variables\n\nEdit `close-and-suspend/configuration/main.tf` with your environment-specific values:\n\n```hcl\nmodule \"offboarding_lambda\" {\n  source = \"../module\"\n  \n  # CloudWatch Configuration\n  cloudwatch_log_group_retention = \"90\"  # Days to retain logs\n  \n  # AWS Configuration\n  region         = \"eu-west-1\"           # Primary region\n  aft_account_id = \"123456789012\"        # AFT management account ID\n  ct_account_id  = \"210987654321\"        # Control Tower management account ID\n  \n  # Organizational Units\n  ct_destination_ou = \"ou-juup-d1e061ao\" # SUSPENDED OU ID\n  ct_root_ou_id     = \"r-juup\"           # Root OU ID\n  \n  # DynamoDB Configuration\n  aft-request-audit-table-encrption-key-id = \"arn:aws:kms:eu-west-1:123456789012:key/...\"\n  aft-request-audit-table-stream-arn       = \"arn:aws:dynamodb:eu-west-1:123456789012:table/aft-request-audit/stream/...\"\n  \n  # Tagging\n  default_tags = {\n    Environment = \"AFT\"\n    Project     = \"Offboarding Automation\"\n  }\n}\n```\n\n### Environment Variables\n\nThe Lambda function uses these environment variables:\n\n- `REGION`: AWS region for operations\n- `CT_ACCOUNT`: Control Tower management account ID\n- `DESTINATIONOU`: Target OU for suspended accounts\n- `ROOTOU_ID`: Root organizational unit ID\n\n## GitLab CI/CD Pipeline\n\n### Pipeline Overview\n\nThe GitLab CI/CD pipeline provides automated, secure deployment of the account closure infrastructure with proper state management and cross-account role assumptions.\n\n### Pipeline Stages\n\n#### 1. Terraform Plan (`terraform-plan-close-and-suspend`)\n\n**Purpose**: Creates and validates Terraform execution plan\n\n**Triggers**:\n- Commits to `main` branch\n- Changes in `close-and-suspend/configuration/**/*`\n- Changes in `close-and-suspend/module/**/*`\n\n**Process**:\n```bash\ncd close-and-suspend/configuration\nterraform init\nterraform plan -out=tfplan\n```\n\n**Artifacts**:\n- `tfplan`: Terraform execution plan\n- `aft-close-account.zip`: Lambda deployment package\n- Expiration: 3 hours\n\n#### 2. Terraform Apply (`terraform-apply-close-and-suspend`)\n\n**Purpose**: Applies the validated Terraform plan\n\n**Dependencies**: Requires successful plan stage\n\n**Process**:\n```bash\ncd close-and-suspend/configuration\nterraform init\nterraform apply -auto-approve tfplan\n```\n\n**Safety Features**:\n- Uses pre-validated plan from artifacts\n- No interactive approval required\n- Automatic rollback on failure\n\n#### 3. Terraform Destroy (`terraform-destroy-close-and-suspend`)\n\n**Purpose**: Removes all infrastructure (manual trigger only)\n\n**Trigger**: Manual execution only\n\n**Process**:\n```bash\ncd close-and-suspend/configuration\nterraform init\nterraform destroy -auto-approve\n```\n\n**Safety**: Manual trigger prevents accidental destruction\n\n### Runner Configuration\n\n#### Required Tags\n```yaml\ntags:\n  - test-runner\n```\n\n#### Required Software\n- Terraform \u003e= 0.15.0\n- AWS CLI (latest version)\n- Git\n- Bash/Shell access\n\n#### AWS Permissions\nThe runner must have permissions to:\n- Assume `AWSAFTExecution` role in AFT account\n- Assume `AWSAFTExecution` role in CT account\n- Access S3 backend bucket\n- DynamoDB state locking\n\n### State Management\n\n#### S3 Backend Configuration\n```hcl\nbackend \"s3\" {\n  bucket               = \"aft-management-gitlab-runner-tfstate\"\n  key                  = \"offboarding-module.tfstate\"\n  region               = \"eu-west-1\"\n  use_lockfile         = true    # S3 native locking\n  encrypt              = true    # State encryption\n  workspace_key_prefix = \"offboarding-module\"\n}\n```\n\n#### State Security Features\n- **Encryption**: All state files encrypted at rest\n- **Locking**: Prevents concurrent modifications\n- **Versioning**: S3 versioning for state history\n- **Access Control**: IAM-based access restrictions\n\n### Pipeline Variables\n\n#### GitLab CI Variables (Optional)\nSet these in GitLab → Settings → CI/CD → Variables:\n\n```bash\n# AWS Credentials (if not using IAM roles)\nAWS_ACCESS_KEY_ID: \"your-access-key\"\nAWS_SECRET_ACCESS_KEY: \"your-secret-key\"\nAWS_DEFAULT_REGION: \"eu-west-1\"\n\n# Terraform Variables (if overriding defaults)\nTF_VAR_region: \"eu-west-1\"\nTF_VAR_aft_account_id: \"123456789012\"\nTF_VAR_ct_account_id: \"210987654321\"\n```\n\n### Pipeline Monitoring\n\n#### Success Indicators\n- ✅ Plan stage completes without errors\n- ✅ Apply stage creates all resources\n- ✅ Lambda function is deployed and active\n- ✅ IAM roles created in both accounts\n\n#### Failure Scenarios\n- ❌ Terraform validation errors\n- ❌ AWS permission issues\n- ❌ Cross-account role assumption failures\n- ❌ Resource creation conflicts\n\n#### Troubleshooting Pipeline Issues\n\n**Plan Stage Failures**:\n```bash\n# Check Terraform syntax\nterraform validate\n\n# Verify AWS credentials\naws sts get-caller-identity\n\n# Test role assumptions\naws sts assume-role --role-arn arn:aws:iam::123456789012:role/AWSAFTExecution --role-session-name test\n```\n\n**Apply Stage Failures**:\n```bash\n# Check resource conflicts\nterraform state list\n\n# Verify permissions\naws iam simulate-principal-policy --policy-source-arn arn:aws:iam::123456789012:role/AWSAFTExecution --action-names lambda:CreateFunction\n\n# Review CloudWatch logs\naws logs describe-log-groups --log-group-name-prefix /aws/lambda/aft-close-account\n```\n\n### Pipeline Best Practices\n\n#### Development Workflow\n1. Create feature branch for changes\n2. Test changes in development environment\n3. Create merge request to main\n4. Review pipeline output before merging\n5. Monitor production deployment\n\n#### Security Practices\n- Use IAM roles instead of access keys when possible\n- Regularly rotate access credentials\n- Monitor pipeline execution logs\n- Implement proper approval workflows for sensitive changes\n- Use branch protection rules\n\n#### Operational Practices\n- Monitor pipeline execution times\n- Set up notifications for pipeline failures\n- Regularly review and update runner configurations\n- Maintain backup of Terraform state\n- Document any manual interventions\n\n## Deployment\n\n### GitLab CI/CD Pipeline\n\nThis project uses GitLab CI/CD for automated deployment with a three-stage pipeline:\n\n```yaml\nstages:\n  - terraform-plan\n  - terraform-apply\n  - terraform-destroy\n```\n\n#### Pipeline Configuration\n\nThe pipeline is configured in `.gitlab-ci.yml` with the following jobs:\n\n**Planning Stage:**\n- `terraform-plan-close-and-suspend`: Creates Terraform execution plan\n- Triggers on changes to `close-and-suspend/` directory\n- Stores plan artifacts for apply stage\n\n**Apply Stage:**\n- `terraform-apply-close-and-suspend`: Applies the Terraform plan\n- Requires successful planning stage\n- Automatically applies on main branch\n\n**Destroy Stage:**\n- `terraform-destroy-close-and-suspend`: Destroys infrastructure\n- Manual trigger only for safety\n\n### Pipeline Execution Flow\n\n1. **Trigger Conditions:**\n   ```yaml\n   rules:\n     - if: $CI_COMMIT_BRANCH == \"main\"\n       changes:\n         - close-and-suspend/configuration/**/*\n         - close-and-suspend/module/**/*\n   ```\n\n2. **Artifact Management:**\n   - Terraform plans stored as artifacts\n   - Lambda deployment packages included\n   - 3-hour expiration for security\n\n3. **Runner Requirements:**\n   - Tagged with `test-runner`\n   - Must have AWS credentials configured\n   - Terraform and AWS CLI installed\n\n### Backend Configuration\n\nThe solution uses S3 backend for state management:\n\n```hcl\nbackend \"s3\" {\n  bucket               = \"aft-management-gitlab-runner-tfstate\"\n  key                  = \"offboarding-module.tfstate\"\n  region               = \"eu-west-1\"\n  use_lockfile         = true\n  encrypt              = true\n  workspace_key_prefix = \"offboarding-module\"\n}\n```\n\n### Multi-Provider Setup\n\nThe configuration uses multiple AWS providers for cross-account deployment:\n\n```hcl\n# Default provider\nprovider \"aws\" {\n  region = var.region\n}\n\n# AFT Management Account\nprovider \"aws\" {\n  alias  = \"aft\"\n  region = var.region\n  assume_role {\n    role_arn    = \"arn:aws:iam::123456789012:role/AWSAFTExecution\"\n    external_id = \"ASSUME_ROLE_ON_TARGET_ACC\"\n  }\n}\n\n# Control Tower Management Account\nprovider \"aws\" {\n  alias  = \"ct\"\n  region = var.region\n  assume_role {\n    role_arn    = \"arn:aws:iam::210987654321:role/AWSAFTExecution\"\n    external_id = \"ASSUME_ROLE_ON_TARGET_ACC\"\n  }\n}\n```\n\n### Deployment Methods\n\n#### Option 1: GitLab CI/CD (Recommended)\n\n1. **Push changes to repository:**\n   ```bash\n   git add .\n   git commit -m \"Update account closure configuration\"\n   git push origin main\n   ```\n\n2. **Monitor pipeline:**\n   - Navigate to GitLab CI/CD → Pipelines\n   - Review plan output in planning stage\n   - Verify successful apply stage\n\n3. **Manual destroy (if needed):**\n   - Navigate to GitLab CI/CD → Pipelines\n   - Click \"Run pipeline\" → Select \"terraform-destroy-close-and-suspend\"\n\n#### Option 2: Manual Deployment\n\n1. **Configure AWS credentials:**\n   ```bash\n   # Set up profiles for both accounts\n   aws configure --profile aft-account\n   aws configure --profile ct-account\n   ```\n\n2. **Initialize and deploy:**\n   ```bash\n   cd close-and-suspend/configuration\n   terraform init\n   terraform plan -out=tfplan\n   terraform apply tfplan\n   ```\n\n3. **Verify deployment:**\n   ```bash\n   # Check Lambda function\n   aws lambda get-function --function-name aft-close-account-lambda --profile aft-account\n   \n   # Check CT role\n   aws iam get-role --role-name aft-account-closure-role --profile ct-account\n   ```\n\n### Multi-Account Resource Distribution\n\n**AFT Management Account (123456789012):**\n- Lambda function (`aft-close-account-lambda`)\n- Lambda execution role (`aft-close-account-lambda-role`)\n- CloudWatch log group (`/aws/lambda/aft-close-account-lambda`)\n- DynamoDB stream event source mapping\n- Code signing configuration and profile\n\n**Control Tower Management Account (210987654321):**\n- Cross-account IAM role (`aft-account-closure-role`)\n- Service Catalog and Organizations permissions\n- Account closure execution permissions\n\n### Pipeline Security\n\n- **State Encryption**: Terraform state encrypted in S3\n- **State Locking**: DynamoDB locking prevents concurrent runs\n- **Role Assumption**: Cross-account access via IAM roles\n- **Artifact Security**: Limited artifact expiration (3 hours)\n- **Manual Destroy**: Destroy operations require manual approval\n\n## How It Works\n\n### Workflow Overview\n\n1. **Trigger**: AFT audit trail DynamoDB stream detects account removal request\n2. **Processing**: Lambda function processes the stream event\n3. **Validation**: Verifies account details and permissions\n4. **Service Catalog**: Terminates the provisioned product\n5. **Organizations**: Moves account to SUSPENDED OU\n6. **Closure**: Initiates AWS account closure\n7. **Logging**: Records all operations in CloudWatch\n\n### Event Processing\n\nThe Lambda function processes DynamoDB stream events:\n\n```python\n# Event structure\n{\n    \"Records\": [\n        {\n            \"eventName\": \"INSERT\",\n            \"dynamodb\": {\n                \"NewImage\": {\n                    \"control_tower_parameters\": {\n                        \"M\": {\n                            \"AccountName\": {\"S\": \"test-account\"},\n                            \"AccountEmail\": {\"S\": \"test@example.com\"},\n                            \"ManagedOrganizationalUnit\": {\"S\": \"ou-source\"}\n                        }\n                    },\n                    \"ddb_event_name\": {\"S\": \"REMOVE\"}\n                }\n            }\n        }\n    ]\n}\n```\n\n### Account Closure Process\n\n1. **Account Lookup**: Query AFT metadata table by email\n2. **Role Assumption**: Assume cross-account role in CT account\n3. **Product Termination**: Terminate Service Catalog product\n4. **Account Movement**: Move from current OU to SUSPENDED OU\n5. **Account Closure**: Call Organizations CloseAccount API\n6. **Verification**: Confirm successful closure\n\n## Security\n\n### IAM Permissions\n\n**Lambda Execution Role (AFT Account):**\n- CloudWatch Logs access\n- DynamoDB stream and table access\n- SSM parameter access\n- KMS decrypt permissions\n- Cross-account role assumption\n\n**Account Closure Role (CT Account):**\n- Service Catalog terminate permissions\n- Organizations account management\n- Limited to specific operations only\n\n### Security Features\n\n- **Code Signing**: Lambda functions are signed for integrity\n- **Least Privilege**: Minimal required permissions only\n- **Cross-Account**: Secure role assumption between accounts\n- **Encryption**: KMS encryption for DynamoDB streams\n- **Audit Trail**: Comprehensive logging of all operations\n\n### Network Security\n\n- Lambda functions run in AWS managed VPC\n- No internet access required for core functionality\n- All AWS API calls use service endpoints\n\n## Monitoring\n\n### CloudWatch Logs\n\nThe Lambda function creates detailed logs:\n\n```\n/aws/lambda/aft-close-account-lambda\n```\n\nLog retention is configurable (default: 90 days).\n\n### Key Metrics to Monitor\n\n- Lambda function invocations\n- Lambda function errors\n- Lambda function duration\n- DynamoDB stream processing lag\n- Account closure success/failure rates\n\n### Alerting\n\nConsider setting up CloudWatch alarms for:\n\n```bash\n# Lambda errors\naws cloudwatch put-metric-alarm \\\n  --alarm-name \"AFT-Account-Closure-Errors\" \\\n  --alarm-description \"Lambda function errors\" \\\n  --metric-name Errors \\\n  --namespace AWS/Lambda \\\n  --statistic Sum \\\n  --period 300 \\\n  --threshold 1 \\\n  --comparison-operator GreaterThanOrEqualToThreshold\n```\n\n## Troubleshooting\n\n### Common Issues\n\n#### Lambda Function Timeout\n**Symptom**: Function times out during execution\n**Solution**: Increase timeout value (current: 900 seconds)\n\n#### Permission Denied\n**Symptom**: Cross-account role assumption fails\n**Solution**: Verify trust relationship and IAM policies\n\n#### Account Not Found\n**Symptom**: Cannot find account in AFT metadata\n**Solution**: Verify account email and AFT table structure\n\n#### Service Catalog Product Not Found\n**Symptom**: Cannot terminate provisioned product\n**Solution**: Verify product name matches account name exactly\n\n### Debugging Steps\n\n#### Pipeline Debugging\n\n1. **Check pipeline logs:**\n   ```bash\n   # In GitLab UI: CI/CD → Pipelines → Select pipeline → View job logs\n   # Look for specific error messages in plan/apply stages\n   ```\n\n2. **Verify runner configuration:**\n   ```bash\n   # On GitLab runner\n   gitlab-runner verify\n   terraform --version\n   aws --version\n   aws sts get-caller-identity\n   ```\n\n3. **Test Terraform locally:**\n   ```bash\n   cd close-and-suspend/configuration\n   terraform init\n   terraform validate\n   terraform plan\n   ```\n\n#### Application Debugging\n\n4. **Check Lambda logs:**\n   ```bash\n   aws logs filter-log-events \\\n     --log-group-name /aws/lambda/aft-close-account-lambda \\\n     --start-time $(date -d '1 hour ago' +%s)000 \\\n     --profile aft-account\n   ```\n\n5. **Verify DynamoDB stream:**\n   ```bash\n   aws dynamodb describe-table \\\n     --table-name aft-request-audit \\\n     --query 'Table.StreamSpecification' \\\n     --profile aft-account\n   ```\n\n6. **Test cross-account role assumption:**\n   ```bash\n   aws sts assume-role \\\n     --role-arn arn:aws:iam::210987654321:role/aft-account-closure-role \\\n     --role-session-name test-session \\\n     --profile aft-account\n   ```\n\n#### State Management Debugging\n\n7. **Check Terraform state:**\n   ```bash\n   # List state resources\n   terraform state list\n   \n   # Check specific resource\n   terraform state show aws_lambda_function.aft-close-account-lambda\n   \n   # Verify backend connectivity\n   terraform init -backend-config=\"bucket=aft-management-gitlab-runner-tfstate\"\n   ```\n\n### Error Codes\n\n#### Pipeline Errors\n- `terraform init failed`: Backend configuration or credentials issue\n- `terraform plan failed`: Configuration validation or permission errors\n- `terraform apply failed`: Resource creation or dependency issues\n- `Job failed: exit code 1`: General Terraform execution failure\n- `Runner system failure`: GitLab runner connectivity or resource issues\n\n#### Application Errors\n- `ResourceNotFoundException`: Account or Service Catalog product not found\n- `AccessDeniedException`: Insufficient permissions for AWS operations\n- `ValidationException`: Invalid parameters passed to AWS APIs\n- `ThrottlingException`: API rate limits exceeded\n- `AssumeRoleFailure`: Cross-account role assumption failed\n- `LambdaTimeoutException`: Function execution exceeded 900 seconds\n\n## Best Practices\n\n### Operational\n- Test in non-production environment first\n- Use GitLab CI/CD for consistent deployments\n- Monitor both pipeline and CloudWatch logs regularly\n- Set up appropriate alerting for pipeline failures\n- Document account closure procedures and pipeline workflows\n- Maintain audit trails for all deployments\n- Regularly review and update GitLab runner configurations\n- Implement proper backup strategies for Terraform state\n\n### Security\n- Regularly review IAM permissions\n- Use least privilege principles\n- Enable CloudTrail logging\n- Implement proper backup procedures\n- Regular security assessments\n\n### Development\n- Use infrastructure as code\n- Version control all configurations\n- Implement proper testing\n- Document all changes\n- Follow AWS Well-Architected principles\n\n### Account Management\n- Maintain accurate OU structure\n- Document account lifecycle processes\n- Implement proper approval workflows\n- Regular compliance reviews\n- Backup critical account data before closure\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Update documentation\n6. Submit a pull request\n\n### Development Guidelines\n\n- Follow Terraform best practices\n- Use consistent naming conventions\n- Add appropriate comments\n- Update README for any changes\n- Test in development environment\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Support\n\nFor questions or issues:\n- Create an issue in this repository\n- Review AWS Control Tower documentation\n- Consult AWS Organizations documentation\n- Check AWS Lambda best practices\n\n## References\n\n- [AWS Control Tower Documentation](https://docs.aws.amazon.com/controltower/)\n- [AWS Organizations Documentation](https://docs.aws.amazon.com/organizations/)\n- [Account Factory for Terraform](https://docs.aws.amazon.com/controltower/latest/userguide/aft-overview.html)\n- [AWS Lambda Documentation](https://docs.aws.amazon.com/lambda/)\n- [Terraform AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)\n\n## Changelog\n\n### Version 1.0.0\n- Initial release\n- Basic account closure automation\n- Cross-account role support\n- CloudWatch logging integration\n- Code signing implementation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitsnotsagar%2Faws-tf-close-account","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitsnotsagar%2Faws-tf-close-account","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitsnotsagar%2Faws-tf-close-account/lists"}