use crate::packs::{DestructivePattern, Pack, SafePattern};
use crate::{destructive_pattern, safe_pattern};
#[must_use]
pub fn create_pack() -> Pack {
Pack {
id: "infrastructure.terraform".to_string(),
name: "Terraform",
description: "Protects against destructive Terraform operations like destroy, \
taint, and apply with -auto-approve",
keywords: &["terraform", "destroy", "taint", "state"],
safe_patterns: create_safe_patterns(),
destructive_patterns: create_destructive_patterns(),
keyword_matcher: None,
safe_regex_set: None,
safe_regex_set_is_complete: false,
}
}
fn create_safe_patterns() -> Vec<SafePattern> {
vec![
safe_pattern!("terraform-plan", r"terraform\s+plan(?!\s+.*-destroy)"),
safe_pattern!("terraform-init", r"terraform\s+init"),
safe_pattern!("terraform-validate", r"terraform\s+validate"),
safe_pattern!("terraform-fmt", r"terraform\s+fmt"),
safe_pattern!("terraform-show", r"terraform\s+show"),
safe_pattern!("terraform-output", r"terraform\s+output"),
safe_pattern!("terraform-state-list", r"terraform\s+state\s+list"),
safe_pattern!("terraform-state-show", r"terraform\s+state\s+show"),
safe_pattern!("terraform-graph", r"terraform\s+graph"),
safe_pattern!("terraform-version", r"terraform\s+version"),
safe_pattern!("terraform-providers", r"terraform\s+providers"),
]
}
fn create_destructive_patterns() -> Vec<DestructivePattern> {
vec![
destructive_pattern!(
"destroy",
r"terraform\s+destroy",
"terraform destroy removes ALL managed infrastructure. Use 'terraform plan -destroy' first.",
Critical,
"terraform destroy removes ALL managed infrastructure:\n\n\
- Every resource in your state file is destroyed\n\
- Cloud resources (VMs, databases, networks) deleted\n\
- Cannot be undone without backups/recreation\n\
- Use -target to destroy specific resources only\n\n\
Preview first: terraform plan -destroy"
),
destructive_pattern!(
"plan-destroy",
r"terraform\s+plan\s+.*-destroy",
"terraform plan -destroy shows what would be destroyed. Review carefully before applying.",
Medium,
"terraform plan -destroy shows destruction preview:\n\n\
- This is a read-only operation (safe to run)\n\
- Shows what WOULD be destroyed if you apply\n\
- Review output carefully before proceeding\n\n\
This is actually the safe way to preview destroy."
),
destructive_pattern!(
"apply-auto-approve",
r"terraform\s+apply\s+.*-auto-approve",
"terraform apply -auto-approve skips confirmation. Remove -auto-approve for safety.",
High,
"terraform apply -auto-approve skips confirmation:\n\n\
- No opportunity to review changes before applying\n\
- Intended for CI/CD, not interactive use\n\
- Changes may destroy or recreate resources\n\n\
For safety: remove -auto-approve and review the plan"
),
destructive_pattern!(
"taint",
r"terraform\s+taint\b",
"terraform taint marks a resource to be destroyed and recreated on next apply.",
High,
"terraform taint marks resource for recreation:\n\n\
- Resource will be destroyed on next apply\n\
- New resource created with same config\n\
- May cause downtime during recreation\n\
- IP addresses and identifiers may change\n\n\
Use -replace in plan/apply instead (Terraform 0.15.2+)"
),
destructive_pattern!(
"state-rm",
r"terraform\s+state\s+rm\b",
"terraform state rm removes resource from state without destroying it. Resource becomes unmanaged.",
High,
"terraform state rm orphans resources:\n\n\
- Resource removed from Terraform state\n\
- Actual cloud resource still exists\n\
- Resource becomes 'unmanaged' (Terraform ignores it)\n\
- May cause drift between state and reality\n\n\
Back up state first: terraform state pull > backup.tfstate"
),
destructive_pattern!(
"state-mv",
r"terraform\s+state\s+mv\b",
"terraform state mv moves resources in state. Incorrect moves can cause resource recreation.",
High,
"terraform state mv moves resources in state:\n\n\
- Renames resource address in state file\n\
- Wrong move can cause destruction/recreation\n\
- Use -dry-run to preview the move first\n\
- Does not affect actual cloud resources\n\n\
Preview first: terraform state mv -dry-run SOURCE DEST"
),
destructive_pattern!(
"force-unlock",
r"terraform\s+force-unlock\b",
"terraform force-unlock removes state lock. Only use if lock is stale.",
High,
"terraform force-unlock removes state locks:\n\n\
- Forces removal of a state lock\n\
- May cause corruption if another process is running\n\
- Only use when you're sure no other operation is active\n\
- Lock ID required to prevent accidents\n\n\
Verify no other operations: check CI/CD pipelines, other users"
),
destructive_pattern!(
"workspace-delete",
r"terraform\s+workspace\s+delete\b",
"terraform workspace delete removes a workspace. Ensure it's not in use.",
Medium,
"terraform workspace delete removes workspace:\n\n\
- Workspace and its state file deleted\n\
- Does NOT destroy actual infrastructure\n\
- Resources become unmanaged (orphaned)\n\
- Cannot be undone without state backup\n\n\
Destroy resources first: terraform destroy, then delete workspace"
),
]
}