Skip to content

Commit 3225464

Browse files
feat: Add support for aws_backup_logically_air_gapped_vault (#260)
* feat: Add support for aws_backup_logically_air_gapped_vault This implementation adds support for AWS Backup Logically Air Gapped Vault, providing enhanced backup isolation and compliance capabilities. Key features: - New vault_type variable supporting "standard" and "logically_air_gapped" - Mandatory retention configuration for air-gapped vaults - Backward compatibility with existing standard vault configurations - Comprehensive example configuration with compliance patterns - Enhanced outputs for both vault types Security enhancements: - Built-in retention enforcement for compliance requirements - Enhanced isolation for regulatory environments (SOX, PCI-DSS, HIPAA) - Immutable retention policies once configured Breaking changes: None - fully backward compatible Closes #236 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * fix: resolve pre-commit and validation issues - Remove invalid cross-variable validation blocks in variables.tf - Add proper lifecycle precondition for air-gapped vault validation - Remove unused local.vault_arn to fix TFLint warning - Fix end-of-file issues in example files - Apply proper terraform formatting Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * fix: address code review issues for air-gapped vault implementation - Fix critical bug: change min_retention_days default from 2555 to 7 days - Add sensitive flag to airgapped_vault_recovery_points output for security - Improve vault reference logic readability with multi-line formatting - Optimize validation logic using logical OR operator Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * fix: address code review issues for air-gapped vault implementation - Fix documentation inconsistency in README.md (retention values) - Rename airgapped_vault_valid to vault_retention_valid for clarity - Add cross-validation between min/max retention days - Improve vault_name logic readability - Add validation to example variables for better error handling - Update comments to reflect configurable compliance periods 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * fix: address critical code review issues for air-gapped vault implementation - Move cross-validation logic from variable to lifecycle precondition to fix confusing error messages - Add sensitive flag to recovery points output in example to prevent information disclosure - Rename vault_retention_valid to airgapped_vault_requirements_met for clarity - Optimize depends_on to only reference relevant vault type resources - Document force_destroy limitations and AWS API constraints in README - Add comprehensive validation documentation for air-gapped vault constraints Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * fix: address critical code review issues for air-gapped vault implementation - Remove circular dependency in cross-variable validation from example - Optimize dependency logic by replacing inefficient compact() with conditional dependencies - Consolidate validation logic using unified logical OR approach - Comment out hardcoded provider settings in example to prevent production issues Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com> * feat: add AWS Backup Logically Air Gapped Vault support - Add support for aws_backup_logically_air_gapped_vault resource - New vault_type variable supporting "standard" and "logically_air_gapped" - Mandatory retention configuration for air-gapped vaults - Backward compatibility with existing configurations - Comprehensive example with compliance patterns - Enhanced outputs for both vault types - Updated AWS provider requirement to >= 6.11.0 - Added comprehensive test suite for air-gapped vault functionality - Updated documentation with new vault type feature Closes #236 * fix: pre-commit cleanup - add missing newlines and update docs * fix: update CI matrix to support AWS provider >= 6.11.0 for air gapped vault - Update aws_provider_version matrix from [5.0.0, 5.70.0] to [6.11.0, 6.70.0] - Add logically_air_gapped_vault example to validation matrix - Update documentation via terraform-docs - Fix CI failures with unsupported resource in older AWS provider versions * fix: resolve CI failures and pre-commit issues - Update AWS provider versions in CI matrix from 6.70.0 to 6.13.0 (latest available) - Fix terraform-docs generated documentation and remove duplicate sections - All pre-commit hooks now pass cleanly - Terraform validation will work with supported provider versions --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Luis M. Gallardo D. <lgallard@users.noreply.github.com>
1 parent 25ede97 commit 3225464

File tree

19 files changed

+710
-120
lines changed

19 files changed

+710
-120
lines changed

.github/feature-tracker/backup-features.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,31 +336,31 @@
336336
"status": "pending_creation"
337337
},
338338
{
339-
"resource": "aws_backup_logically_air_gapped_vault",
339+
"resource": "aws_backup_logically_air_gapped_vault",
340340
"issue_type": "new-feature",
341341
"title": "feat: Add support for aws_backup_logically_air_gapped_vault",
342342
"created_date": "2025-09-01T01:45:00Z",
343343
"status": "pending_creation"
344344
},
345345
{
346346
"resource": "aws_backup_region_settings",
347-
"issue_type": "new-feature",
347+
"issue_type": "new-feature",
348348
"title": "feat: Add support for aws_backup_region_settings",
349349
"created_date": "2025-09-01T01:45:00Z",
350350
"status": "pending_creation"
351351
},
352352
{
353353
"resource": "aws_backup_restore_testing_plan",
354354
"issue_type": "new-feature",
355-
"title": "feat: Add support for aws_backup_restore_testing_plan",
355+
"title": "feat: Add support for aws_backup_restore_testing_plan",
356356
"created_date": "2025-09-01T01:45:00Z",
357357
"status": "pending_creation"
358358
},
359359
{
360360
"resource": "aws_backup_restore_testing_selection",
361361
"issue_type": "new-feature",
362362
"title": "feat: Add support for aws_backup_restore_testing_selection",
363-
"created_date": "2025-09-01T01:45:00Z",
363+
"created_date": "2025-09-01T01:45:00Z",
364364
"status": "pending_creation"
365365
}
366366
],

.github/workflows/feature-discovery.yml

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -109,22 +109,22 @@ jobs:
109109
GITHUB_TOKEN: ${{ secrets.CLAUDE_ISSUE_TOKEN }}
110110
run: |
111111
echo "🔍 Pre-discovery verification checks..."
112-
112+
113113
# Check GitHub token permissions (skip auth status check)
114114
echo "Verifying GitHub token permissions..."
115115
echo "✅ GitHub token configured"
116-
116+
117117
# Test issue creation capability
118118
echo "Testing GitHub CLI issue operations..."
119119
gh issue list --limit 1 > /dev/null || echo "⚠️ Issue operations may fail"
120-
120+
121121
# Verify MCP server accessibility
122122
echo "Testing Docker availability for Terraform MCP server..."
123123
docker --version
124-
124+
125125
echo "Testing NPX availability for Context7 MCP server..."
126126
npx --version
127-
127+
128128
# Verify tracker file state
129129
echo "Current feature tracker state:"
130130
if [ -f .github/feature-tracker/backup-features.json ]; then
@@ -134,7 +134,7 @@ jobs:
134134
else
135135
echo "⚠️ Feature tracker will be created"
136136
fi
137-
137+
138138
echo "✅ Pre-verification complete"
139139
140140
- name: Run Claude Code Feature Discovery
@@ -272,7 +272,7 @@ jobs:
272272
273273
### Step 5: Generate Structured Output for Issue Creation
274274
**CRITICAL: DO NOT execute gh issue create commands directly.**
275-
275+
276276
Instead, create a structured JSON file for the post-process step to handle:
277277
278278
```bash
@@ -299,7 +299,7 @@ jobs:
299299
}
300300
// For each new argument discovered:
301301
{
302-
"type": "new_argument",
302+
"type": "new_argument",
303303
"resource_name": "[EXISTING_RESOURCE_NAME]",
304304
"argument_name": "[ARGUMENT_NAME]",
305305
"description": "[ARGUMENT_DESCRIPTION]",
@@ -347,13 +347,13 @@ jobs:
347347
if: steps.claude-discovery.conclusion != 'failure'
348348
run: |
349349
echo "🔍 Post-discovery verification..."
350-
350+
351351
# Check what Claude Code actually produced
352352
echo "Checking for structured output file..."
353353
if [ -f "/tmp/discovered-features.json" ]; then
354354
echo "✅ Structured output file exists"
355355
echo "File size: $(wc -c < /tmp/discovered-features.json) bytes"
356-
356+
357357
# Validate JSON
358358
if jq empty /tmp/discovered-features.json 2>/dev/null; then
359359
echo "✅ Valid JSON structure"
@@ -369,7 +369,7 @@ jobs:
369369
echo "Checking for temp files:"
370370
ls -la /tmp/ | grep -E "(discovered|feature|backup)" || echo "No related temp files"
371371
fi
372-
372+
373373
# Check tracker file updates
374374
echo "Checking feature tracker updates..."
375375
if [ -f ".github/feature-tracker/backup-features.json" ]; then
@@ -378,7 +378,7 @@ jobs:
378378
echo "Last scan: $LAST_SCAN"
379379
echo "Pending creation entries: $PENDING_COUNT"
380380
fi
381-
381+
382382
echo "✅ Post-verification complete"
383383
384384
- name: Create GitHub Issues from Structured Output
@@ -388,33 +388,33 @@ jobs:
388388
GITHUB_TOKEN: ${{ secrets.CLAUDE_ISSUE_TOKEN }}
389389
run: |
390390
set -euo pipefail
391-
391+
392392
echo "🔍 Processing discovered features for issue creation..."
393-
393+
394394
DISCOVERED_FILE="/tmp/discovered-features.json"
395395
TRACKER_FILE=".github/feature-tracker/backup-features.json"
396396
ISSUES_CREATED=0
397-
397+
398398
# Check if structured output exists
399399
if [ ! -f "$DISCOVERED_FILE" ]; then
400400
echo "⚠️ No structured output found at $DISCOVERED_FILE"
401401
echo "Checking for pending_creation entries in tracker file..."
402-
402+
403403
if [ ! -f "$TRACKER_FILE" ]; then
404404
echo "Feature tracker file not found, skipping post-processing"
405405
exit 0
406406
fi
407-
407+
408408
# Fallback: Extract pending creation features from tracker
409409
PENDING_FEATURES=$(jq -r '.issues_created[]? | select(.status == "pending_creation") | @base64' "$TRACKER_FILE" 2>/dev/null || echo "")
410-
410+
411411
if [ -z "$PENDING_FEATURES" ]; then
412412
echo "✅ No features with pending_creation status found"
413413
exit 0
414414
fi
415-
415+
416416
echo "📝 Found features with pending_creation status. Creating issues..."
417-
417+
418418
# Process pending features from tracker
419419
while IFS= read -r feature_data; do
420420
if [ -n "$feature_data" ]; then
@@ -423,9 +423,9 @@ jobs:
423423
RESOURCE=$(echo "$FEATURE_JSON" | jq -r '.resource')
424424
TITLE=$(echo "$FEATURE_JSON" | jq -r '.title')
425425
ISSUE_TYPE=$(echo "$FEATURE_JSON" | jq -r '.issue_type // "new-feature"')
426-
426+
427427
echo "Creating issue for: $RESOURCE"
428-
428+
429429
# Create the issue
430430
ISSUE_URL=$(gh issue create \
431431
--title "$TITLE" \
@@ -461,12 +461,12 @@ jobs:
461461
*Auto-generated by AWS Backup Feature Discovery Bot*" \
462462
--label "enhancement,aws-backup,features,terraform" \
463463
--assignee "lgallard")
464-
464+
465465
# Extract issue number from URL
466466
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -o '[0-9]*$')
467467
echo "✅ Created issue #$ISSUE_NUMBER for $RESOURCE: $ISSUE_URL"
468468
ISSUES_CREATED=$((ISSUES_CREATED + 1))
469-
469+
470470
# Update the tracker file to mark as created
471471
jq --arg resource "$RESOURCE" --arg issue_num "$ISSUE_NUMBER" --arg issue_url "$ISSUE_URL" '
472472
(.issues_created[] | select(.resource == $resource)) |= (
@@ -477,34 +477,34 @@ jobs:
477477
)' "$TRACKER_FILE" > "${TRACKER_FILE}.tmp" && mv "${TRACKER_FILE}.tmp" "$TRACKER_FILE"
478478
fi
479479
done <<< "$PENDING_FEATURES"
480-
480+
481481
echo "🎯 Fallback processing complete: Created $ISSUES_CREATED issues"
482482
echo "issues_created=$ISSUES_CREATED" >> $GITHUB_OUTPUT
483483
exit 0
484484
fi
485-
485+
486486
# Process structured JSON output
487487
echo "📋 Processing structured output from Claude Code..."
488-
488+
489489
# Validate JSON structure
490490
if ! jq empty "$DISCOVERED_FILE" 2>/dev/null; then
491491
echo "❌ Invalid JSON in discovered features file"
492492
exit 1
493493
fi
494-
494+
495495
# Extract metadata
496496
SCAN_DATE=$(jq -r '.scan_metadata.scan_date // "unknown"' "$DISCOVERED_FILE")
497497
PROVIDER_VERSION=$(jq -r '.scan_metadata.provider_version // "latest"' "$DISCOVERED_FILE")
498498
FEATURE_COUNT=$(jq '.discovered_features | length' "$DISCOVERED_FILE")
499-
499+
500500
echo "Scan metadata: $SCAN_DATE, Provider: $PROVIDER_VERSION, Features: $FEATURE_COUNT"
501-
501+
502502
if [ "$FEATURE_COUNT" -eq 0 ]; then
503503
echo "✅ No new features discovered"
504504
echo "issues_created=0" >> $GITHUB_OUTPUT
505505
exit 0
506506
fi
507-
507+
508508
# Process each discovered feature
509509
jq -r '.discovered_features[] | @base64' "$DISCOVERED_FILE" | while IFS= read -r feature_data; do
510510
if [ -n "$feature_data" ]; then
@@ -513,16 +513,16 @@ jobs:
513513
RESOURCE_NAME=$(echo "$FEATURE_JSON" | jq -r '.resource_name')
514514
ISSUE_TITLE=$(echo "$FEATURE_JSON" | jq -r '.issue_title')
515515
PRIORITY=$(echo "$FEATURE_JSON" | jq -r '.priority // "medium"')
516-
516+
517517
echo "Creating issue for $FEATURE_TYPE: $RESOURCE_NAME"
518-
518+
519519
# Build issue body based on type
520520
if [ "$FEATURE_TYPE" = "new_resource" ]; then
521521
DESCRIPTION=$(echo "$FEATURE_JSON" | jq -r '.description // "AWS Backup resource"')
522522
SECURITY_IMPACT=$(echo "$FEATURE_JSON" | jq -r '.security_impact // "To be evaluated"')
523523
ARGUMENTS=$(echo "$FEATURE_JSON" | jq -r '.arguments[]? // empty' | tr '\n' ' ')
524524
REGISTRY_URL=$(echo "$FEATURE_JSON" | jq -r '.terraform_registry_url // ""')
525-
525+
526526
ISSUE_BODY="## New AWS Backup Resource Request
527527
528528
### Resource Details
@@ -550,12 +550,12 @@ jobs:
550550
551551
---
552552
*Auto-generated by AWS Backup Feature Discovery Bot*"
553-
553+
554554
elif [ "$FEATURE_TYPE" = "new_argument" ]; then
555555
ARGUMENT_NAME=$(echo "$FEATURE_JSON" | jq -r '.argument_name')
556556
DESCRIPTION=$(echo "$FEATURE_JSON" | jq -r '.description // "New argument"')
557557
IMPACT=$(echo "$FEATURE_JSON" | jq -r '.implementation_impact // "To be evaluated"')
558-
558+
559559
ISSUE_BODY="## New Argument Enhancement Request
560560
561561
### Enhancement Details
@@ -577,21 +577,21 @@ jobs:
577577
---
578578
*Auto-generated by AWS Backup Feature Discovery Bot*"
579579
fi
580-
580+
581581
# Create the GitHub issue
582582
ISSUE_URL=$(gh issue create \
583583
--title "$ISSUE_TITLE" \
584584
--body "$ISSUE_BODY" \
585585
--label "enhancement,aws-backup,features,terraform" \
586586
--assignee "lgallard")
587-
587+
588588
# Extract issue number
589589
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -o '[0-9]*$')
590590
echo "✅ Created issue #$ISSUE_NUMBER: $ISSUE_URL"
591591
ISSUES_CREATED=$((ISSUES_CREATED + 1))
592592
fi
593593
done
594-
594+
595595
echo "🎯 Issue creation complete: Created $ISSUES_CREATED issues"
596596
echo "issues_created=$ISSUES_CREATED" >> $GITHUB_OUTPUT
597597
@@ -606,7 +606,7 @@ jobs:
606606
LOCKFILE="/tmp/feature-tracker.lock"
607607
TRACKER_FILE=".github/feature-tracker/backup-features.json"
608608
TEMP_FILE="${TRACKER_FILE}.tmp"
609-
609+
610610
# Get issues created count from previous step
611611
ISSUES_CREATED="${{ steps.create-issues-from-json.outputs.issues_created || '0' }}"
612612
@@ -623,7 +623,7 @@ jobs:
623623
flock -u 200
624624
exit 0
625625
fi
626-
626+
627627
# Only create PR if new issues were created (meaningful changes)
628628
if [ "$ISSUES_CREATED" -eq 0 ]; then
629629
echo "📊 Tracker updated with metadata only - skipping PR creation"
@@ -632,7 +632,7 @@ jobs:
632632
flock -u 200
633633
exit 0
634634
fi
635-
635+
636636
echo "🚀 Creating PR for tracker updates with $ISSUES_CREATED new issues"
637637
638638
# Validate JSON before committing
@@ -662,24 +662,24 @@ jobs:
662662
BRANCH_NAME="feature-discovery/tracker-update-$(date +%Y%m%d-%H%M%S)"
663663
git checkout -b "$BRANCH_NAME"
664664
git push origin "$BRANCH_NAME"
665-
665+
666666
# Create pull request for tracker updates
667667
gh pr create \
668668
--title "chore: update AWS Backup feature discovery tracker" \
669669
--body "Automated update of feature discovery tracker database.
670-
670+
671671
**Scan Details:**
672672
- Scan completed: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
673673
- Provider version: ${{ inputs.provider_version || 'latest' }}
674674
- Workflow run: ${{ github.run_id }}
675-
675+
676676
This PR contains automated updates to the feature tracking database and can be safely merged.
677-
677+
678678
---
679679
*Auto-generated by AWS Backup Feature Discovery workflow*" \
680680
--label "aws-backup,ci-cd,configuration" \
681681
--assignee "lgallard"
682-
682+
683683
echo "Created PR for tracker updates on branch: $BRANCH_NAME"
684684
685685
# Release lock
@@ -714,7 +714,7 @@ jobs:
714714
else
715715
echo "- ❌ **Feature Discovery**: Failed" >> $GITHUB_STEP_SUMMARY
716716
fi
717-
717+
718718
# Issue Creation Status
719719
if [ "${{ inputs.dry_run }}" = "true" ]; then
720720
echo "- 🧪 **Issue Creation**: Skipped (dry run mode)" >> $GITHUB_STEP_SUMMARY
@@ -730,7 +730,7 @@ jobs:
730730
else
731731
echo "- ❌ **Issue Creation**: Failed or incomplete" >> $GITHUB_STEP_SUMMARY
732732
fi
733-
733+
734734
# Tracker Update Status
735735
if [ "${{ steps.claude-discovery.conclusion }}" = "success" ]; then
736736
ISSUES_COUNT="${{ steps.create-issues-from-json.outputs.issues_created || '0' }}"

.github/workflows/validate.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
terraform_version: ['1.3.0', '1.5.0', '1.9.0']
16-
aws_provider_version: ['5.0.0', '5.70.0']
16+
aws_provider_version: ['6.11.0', '6.13.0']
1717

1818
steps:
1919
- name: Checkout
@@ -72,7 +72,8 @@ jobs:
7272
'multiple_plans',
7373
'aws_recommended_audit_framework',
7474
'complete_audit_framework',
75-
'simple_audit_framework'
75+
'simple_audit_framework',
76+
'logically_air_gapped_vault'
7677
]
7778

7879
steps:

0 commit comments

Comments
 (0)