Skip to content

Commit

Permalink
terraform: helper to decrypt state
Browse files Browse the repository at this point in the history
  • Loading branch information
siddarthkay committed Jan 22, 2025
1 parent 6bee16b commit aa3ccbe
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ roles-check:
roles-update:
@ansible/roles.py --update

decrypt-tf-state:
@ansible/decrypt_tf_state.py

roles: roles-install roles-check

$(PROVISIONER_PATH):
Expand Down
71 changes: 71 additions & 0 deletions ansible/decrypt_tf_backup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python

import os
import sys
import json
import base64
import hashlib
from pathlib import Path
from cryptography.fernet import Fernet
import shutil
from datetime import datetime

def get_encryption_key():
"""Generate encryption key using CONSUL_HTTP_TOKEN"""
consul_token = os.environ.get('CONSUL_HTTP_TOKEN')
if not consul_token:
raise ValueError("CONSUL_HTTP_TOKEN environment variable is required for state decryption")

hashed = hashlib.sha256(consul_token.encode()).digest()
key = base64.urlsafe_b64encode(hashed)
return key

def decrypt_backup(backup_path=None, view_only=False):
"""Decrypt the Terraform state backup and restore it by default
Args:
backup_path: Optional path to backup file
view_only: If True, only prints the decrypted state without modifying files
"""
if not backup_path:
terraform_dir = os.environ.get('ANSIBLE_TF_DIR', os.getcwd())
backup_path = Path(terraform_dir) / '.terraform' / 'terraform.tfstate.backup'
else:
backup_path = Path(backup_path)

if not backup_path.exists():
print(f"Error: Backup file not found at {backup_path}")
sys.exit(1)

try:
encrypted_data = backup_path.read_bytes()
key = get_encryption_key()
cipher = Fernet(key)
decrypted_data = cipher.decrypt(encrypted_data)
state = json.loads(decrypted_data.decode())

if view_only:
print(json.dumps(state, indent=2))
else:
backup_path.write_text(json.dumps(state, indent=2))
backup_path.chmod(0o600)
print(f"Successfully restored decrypted state to: {backup_path}")

except ValueError as ve:
print(f"Error: {str(ve)}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Error processing backup: {str(e)}", file=sys.stderr)
sys.exit(1)

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser(description='Decrypt and restore Terraform state backup')
parser.add_argument('--file', '-f', help='Path to backup file (optional)')
parser.add_argument('--view', '-v', action='store_true',
help='Only view the decrypted state without restoring')

args = parser.parse_args()

decrypt_backup(args.file, args.view)

0 comments on commit aa3ccbe

Please sign in to comment.