awslabs.terraform-mcp-server 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of awslabs.terraform-mcp-server might be problematic. Click here for more details.

Files changed (36) hide show
  1. awslabs_terraform_mcp_server-0.0.1/.gitignore +59 -0
  2. awslabs_terraform_mcp_server-0.0.1/.pre-commit-config.yaml +14 -0
  3. awslabs_terraform_mcp_server-0.0.1/.python-version +1 -0
  4. awslabs_terraform_mcp_server-0.0.1/CHANGELOG.md +12 -0
  5. awslabs_terraform_mcp_server-0.0.1/PKG-INFO +97 -0
  6. awslabs_terraform_mcp_server-0.0.1/README.md +82 -0
  7. awslabs_terraform_mcp_server-0.0.1/awslabs/__init__.py +2 -0
  8. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/__init__.py +3 -0
  9. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/resources/__init__.py +11 -0
  10. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py +52 -0
  11. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py +55 -0
  12. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/__init__.py +15 -0
  13. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py +206 -0
  14. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py +359 -0
  15. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py +677 -0
  16. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py +627 -0
  17. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py +444 -0
  18. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/impl/tools/utils.py +558 -0
  19. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/models/__init__.py +27 -0
  20. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/models/models.py +260 -0
  21. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py +1224 -0
  22. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py +1020 -0
  23. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py +129 -0
  24. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/server.py +329 -0
  25. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md +3125 -0
  26. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md +3833 -0
  27. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md +2523 -0
  28. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md +126 -0
  29. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md +198 -0
  30. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/static/__init__.py +22 -0
  31. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/tests/__init__.py +1 -0
  32. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/tests/run_tests.sh +35 -0
  33. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/tests/test_parameter_annotations.py +207 -0
  34. awslabs_terraform_mcp_server-0.0.1/awslabs/terraform_mcp_server/tests/test_tool_implementations.py +309 -0
  35. awslabs_terraform_mcp_server-0.0.1/pyproject.toml +85 -0
  36. awslabs_terraform_mcp_server-0.0.1/uv.lock +2634 -0
@@ -0,0 +1,59 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # Virtual environments
26
+ .venv
27
+ env/
28
+ venv/
29
+ ENV/
30
+
31
+ # IDE
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+
37
+ # Testing
38
+ .tox/
39
+ .coverage
40
+ .coverage.*
41
+ htmlcov/
42
+ .pytest_cache/
43
+
44
+ # Ruff
45
+ .ruff_cache/
46
+
47
+ # Build
48
+ *.manifest
49
+ *.spec
50
+ .pybuilder/
51
+ target/
52
+
53
+ # Environments
54
+ .env
55
+ .env.local
56
+ .env.*.local
57
+
58
+ # PyPI
59
+ .pypirc
@@ -0,0 +1,14 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.9.6
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/commitizen-tools/commitizen
10
+ rev: v3.13.0
11
+ hooks:
12
+ - id: commitizen
13
+ - id: commitizen-branch
14
+ stages: [push]
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## Unreleased
9
+
10
+ ### Added
11
+
12
+ - Initial project setup
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: awslabs.terraform-mcp-server
3
+ Version: 0.0.1
4
+ Summary: An AWS Labs Model Context Protocol (MCP) server for terraform
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: beautifulsoup4>=4.12.0
7
+ Requires-Dist: checkov>=3.2.402
8
+ Requires-Dist: loguru>=0.7.0
9
+ Requires-Dist: mcp[cli]>=1.6.0
10
+ Requires-Dist: playwright>=1.40.0
11
+ Requires-Dist: pydantic>=2.10.6
12
+ Requires-Dist: pypdf2>=3.0.0
13
+ Requires-Dist: requests>=2.31.0
14
+ Description-Content-Type: text/markdown
15
+
16
+ # AWS Terraform MCP Server
17
+
18
+ MCP server for Terraform on AWS best practices, infrastructure as code patterns, and security compliance with Checkov.
19
+
20
+ ## Features
21
+
22
+ - **Terraform Best Practices** - Get prescriptive Terraform advice for building applications on AWS
23
+ - AWS Well-Architected guidance for Terraform configurations
24
+ - Security and compliance recommendations
25
+ - AWSCC provider prioritization for consistent API behavior
26
+
27
+ - **Security-First Development Workflow** - Follow a structured process for creating secure code
28
+ - Step-by-step guidance for validation and security scanning
29
+ - Integration of Checkov at the right stages of development
30
+ - Clear handoff points between AI assistance and developer deployment
31
+
32
+ - **Checkov Integration** - Work with Checkov for security and compliance scanning
33
+ - Run security scans on Terraform code to identify vulnerabilities
34
+ - Automatically fix identified security issues when possible
35
+ - Get detailed remediation guidance for compliance issues
36
+
37
+ - **AWS Provider Documentation** - Search for AWS and AWSCC provider resources
38
+ - Find documentation for specific resources and attributes
39
+ - Get example snippets and implementation guidance
40
+ - Compare AWS and AWSCC provider capabilities
41
+
42
+ - **AWS-IA GenAI Modules** - Access specialized modules for AI/ML workloads
43
+ - Amazon Bedrock module for generative AI applications
44
+ - OpenSearch Serverless for vector search capabilities
45
+ - SageMaker endpoint deployment for ML model hosting
46
+ - Serverless Streamlit application deployment for AI interfaces
47
+
48
+ - **Terraform Workflow Execution** - Run Terraform commands directly
49
+ - Initialize, plan, validate, apply, and destroy operations
50
+ - Pass variables and specify AWS regions
51
+ - Get formatted command output for analysis
52
+
53
+ ## Tools and Resources
54
+
55
+ - **Terraform Development Workflow**: Follow security-focused development process via `terraform://workflow_guide`
56
+ - **AWS Best Practices**: Access AWS-specific guidance via `terraform://aws_best_practices`
57
+ - **AWS Provider Resources**: Access resource listings via `terraform://aws_provider_resources_listing`
58
+ - **AWSCC Provider Resources**: Access resource listings via `terraform://awscc_provider_resources_listing`
59
+
60
+ ## Prerequisites
61
+
62
+ 1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
63
+ 2. Install Python using `uv python install 3.10`
64
+ 3. Install Terraform CLI for workflow execution
65
+ 4. Install Checkov for security scanning
66
+
67
+ ## Installation
68
+
69
+ Here are some ways you can work with MCP across AWS, and we'll be adding support to more products including Amazon Q Developer CLI soon: (e.g. for Amazon Q Developer CLI MCP, `~/.aws/amazonq/mcp.json`):
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "awslabs.terraform-mcp-server": {
75
+ "command": "uvx",
76
+ "args": ["awslabs.terraform-mcp-server@latest"],
77
+ "env": {
78
+ "FASTMCP_LOG_LEVEL": "ERROR"
79
+ },
80
+ "disabled": false,
81
+ "autoApprove": []
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Security Considerations
88
+
89
+ When using this MCP server, you should consider:
90
+ - **Following the structured development workflow** that integrates validation and security scanning
91
+ - Reviewing all Checkov warnings and errors manually
92
+ - Fixing security issues rather than ignoring them whenever possible
93
+ - Documenting clear justifications for any necessary exceptions
94
+ - Using the RunCheckovScan tool regularly to verify security compliance
95
+ - Preferring the AWSCC provider for its consistent API behavior and better security defaults
96
+
97
+ Before applying Terraform changes to production environments, you should conduct your own independent assessment to ensure that your infrastructure would comply with your own specific security and quality control practices and standards, as well as the local laws, rules, and regulations that govern you and your content.
@@ -0,0 +1,82 @@
1
+ # AWS Terraform MCP Server
2
+
3
+ MCP server for Terraform on AWS best practices, infrastructure as code patterns, and security compliance with Checkov.
4
+
5
+ ## Features
6
+
7
+ - **Terraform Best Practices** - Get prescriptive Terraform advice for building applications on AWS
8
+ - AWS Well-Architected guidance for Terraform configurations
9
+ - Security and compliance recommendations
10
+ - AWSCC provider prioritization for consistent API behavior
11
+
12
+ - **Security-First Development Workflow** - Follow a structured process for creating secure code
13
+ - Step-by-step guidance for validation and security scanning
14
+ - Integration of Checkov at the right stages of development
15
+ - Clear handoff points between AI assistance and developer deployment
16
+
17
+ - **Checkov Integration** - Work with Checkov for security and compliance scanning
18
+ - Run security scans on Terraform code to identify vulnerabilities
19
+ - Automatically fix identified security issues when possible
20
+ - Get detailed remediation guidance for compliance issues
21
+
22
+ - **AWS Provider Documentation** - Search for AWS and AWSCC provider resources
23
+ - Find documentation for specific resources and attributes
24
+ - Get example snippets and implementation guidance
25
+ - Compare AWS and AWSCC provider capabilities
26
+
27
+ - **AWS-IA GenAI Modules** - Access specialized modules for AI/ML workloads
28
+ - Amazon Bedrock module for generative AI applications
29
+ - OpenSearch Serverless for vector search capabilities
30
+ - SageMaker endpoint deployment for ML model hosting
31
+ - Serverless Streamlit application deployment for AI interfaces
32
+
33
+ - **Terraform Workflow Execution** - Run Terraform commands directly
34
+ - Initialize, plan, validate, apply, and destroy operations
35
+ - Pass variables and specify AWS regions
36
+ - Get formatted command output for analysis
37
+
38
+ ## Tools and Resources
39
+
40
+ - **Terraform Development Workflow**: Follow security-focused development process via `terraform://workflow_guide`
41
+ - **AWS Best Practices**: Access AWS-specific guidance via `terraform://aws_best_practices`
42
+ - **AWS Provider Resources**: Access resource listings via `terraform://aws_provider_resources_listing`
43
+ - **AWSCC Provider Resources**: Access resource listings via `terraform://awscc_provider_resources_listing`
44
+
45
+ ## Prerequisites
46
+
47
+ 1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
48
+ 2. Install Python using `uv python install 3.10`
49
+ 3. Install Terraform CLI for workflow execution
50
+ 4. Install Checkov for security scanning
51
+
52
+ ## Installation
53
+
54
+ Here are some ways you can work with MCP across AWS, and we'll be adding support to more products including Amazon Q Developer CLI soon: (e.g. for Amazon Q Developer CLI MCP, `~/.aws/amazonq/mcp.json`):
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "awslabs.terraform-mcp-server": {
60
+ "command": "uvx",
61
+ "args": ["awslabs.terraform-mcp-server@latest"],
62
+ "env": {
63
+ "FASTMCP_LOG_LEVEL": "ERROR"
64
+ },
65
+ "disabled": false,
66
+ "autoApprove": []
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## Security Considerations
73
+
74
+ When using this MCP server, you should consider:
75
+ - **Following the structured development workflow** that integrates validation and security scanning
76
+ - Reviewing all Checkov warnings and errors manually
77
+ - Fixing security issues rather than ignoring them whenever possible
78
+ - Documenting clear justifications for any necessary exceptions
79
+ - Using the RunCheckovScan tool regularly to verify security compliance
80
+ - Preferring the AWSCC provider for its consistent API behavior and better security defaults
81
+
82
+ Before applying Terraform changes to production environments, you should conduct your own independent assessment to ensure that your infrastructure would comply with your own specific security and quality control practices and standards, as well as the local laws, rules, and regulations that govern you and your content.
@@ -0,0 +1,2 @@
1
+ # This file is part of the awslabs namespace.
2
+ # It is intentionally minimal to support PEP 420 namespace packages.
@@ -0,0 +1,3 @@
1
+ """awslabs.terraform-mcp-server"""
2
+
3
+ __version__ = '0.0.0'
@@ -0,0 +1,11 @@
1
+ """Resource implementations for the Terraform expert."""
2
+
3
+ from .terraform_aws_provider_resources_listing import terraform_aws_provider_assets_listing_impl
4
+ from .terraform_awscc_provider_resources_listing import (
5
+ terraform_awscc_provider_resources_listing_impl,
6
+ )
7
+
8
+ __all__ = [
9
+ 'terraform_aws_provider_assets_listing_impl',
10
+ 'terraform_awscc_provider_resources_listing_impl',
11
+ ]
@@ -0,0 +1,52 @@
1
+ """Implementation for terraform_aws_provider_resources_listing resource."""
2
+
3
+ import sys
4
+ from loguru import logger
5
+ from pathlib import Path
6
+
7
+
8
+ # Configure logger for enhanced diagnostics with stacktraces
9
+ logger.configure(
10
+ handlers=[
11
+ {
12
+ 'sink': sys.stderr,
13
+ 'backtrace': True,
14
+ 'diagnose': True,
15
+ 'format': '<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>',
16
+ }
17
+ ]
18
+ )
19
+
20
+ # Path to the static markdown file
21
+ STATIC_RESOURCES_PATH = (
22
+ Path(__file__).parent.parent.parent / 'static' / 'AWS_PROVIDER_RESOURCES.md'
23
+ )
24
+
25
+
26
+ async def terraform_aws_provider_assets_listing_impl() -> str:
27
+ """Generate a comprehensive listing of AWS provider resources and data sources.
28
+
29
+ This implementation reads from a pre-generated static markdown file instead of
30
+ scraping the web in real-time. The static file should be generated using the
31
+ generate_aws_provider_resources.py script.
32
+
33
+ Returns:
34
+ A markdown formatted string with categorized resources and data sources
35
+ """
36
+ logger.info('Loading AWS provider resources listing from static file')
37
+
38
+ try:
39
+ # Check if the static file exists
40
+ if STATIC_RESOURCES_PATH.exists():
41
+ # Read the static file content
42
+ with open(STATIC_RESOURCES_PATH, 'r') as f:
43
+ content = f.read()
44
+ logger.info('Successfully loaded AWS Provider asset list')
45
+ return content
46
+ else:
47
+ # Send error if static file does not exist
48
+ logger.debug(f"Static assets list file not found at '{STATIC_RESOURCES_PATH}'")
49
+ raise Exception('Static assets list file not found')
50
+ except Exception as e:
51
+ logger.error(f'Error generating AWS provider assets listing: {e}')
52
+ return f'# AWS Provider Assets Listing\n\nError generating listing: {str(e)}'
@@ -0,0 +1,55 @@
1
+ """Implementation for terraform_awscc_provider_resources_listing resource."""
2
+
3
+ import sys
4
+ from loguru import logger
5
+ from pathlib import Path
6
+
7
+
8
+ # Configure logger for enhanced diagnostics with stacktraces
9
+ logger.configure(
10
+ handlers=[
11
+ {
12
+ 'sink': sys.stderr,
13
+ 'backtrace': True,
14
+ 'diagnose': True,
15
+ 'format': '<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>',
16
+ }
17
+ ]
18
+ )
19
+
20
+ # Path to the static markdown file
21
+ STATIC_RESOURCES_PATH = (
22
+ Path(__file__).parent.parent.parent / 'static' / 'AWSCC_PROVIDER_RESOURCES.md'
23
+ )
24
+
25
+
26
+ async def terraform_awscc_provider_resources_listing_impl() -> str:
27
+ """Generate a comprehensive listing of AWSCC provider resources and data sources.
28
+
29
+ This implementation reads from a pre-generated static markdown file instead of
30
+ scraping the web in real-time. The static file should be generated using the
31
+ generate_awscc_provider_resources.py script.
32
+
33
+ Returns:
34
+ A markdown formatted string with categorized resources and data sources
35
+ """
36
+ logger.info('Loading AWSCC provider resources listing from static file')
37
+
38
+ try:
39
+ # Check if the static file exists
40
+ if STATIC_RESOURCES_PATH.exists():
41
+ # Read the static file content
42
+ with open(STATIC_RESOURCES_PATH, 'r') as f:
43
+ content = f.read()
44
+
45
+ logger.info(
46
+ f'Successfully loaded AWSCC provider resources from {STATIC_RESOURCES_PATH}'
47
+ )
48
+ return content
49
+ else:
50
+ # Send error if static file does not exist
51
+ logger.debug(f"Static assets list file not found at '{STATIC_RESOURCES_PATH}'")
52
+ raise Exception('Static assets list file not found')
53
+ except Exception as e:
54
+ logger.error(f'Error generating AWSCC provider resources listing: {e}')
55
+ return f'# AWSCC Provider Resources Listing\n\nError generating listing: {str(e)}'
@@ -0,0 +1,15 @@
1
+ """Tool implementations for the terraform MCP server."""
2
+
3
+ from .execute_terraform_command import execute_terraform_command_impl
4
+ from .search_aws_provider_docs import search_aws_provider_docs_impl
5
+ from .search_awscc_provider_docs import search_awscc_provider_docs_impl
6
+ from .search_specific_aws_ia_modules import search_specific_aws_ia_modules_impl
7
+ from .run_checkov_scan import run_checkov_scan_impl
8
+
9
+ __all__ = [
10
+ 'execute_terraform_command_impl',
11
+ 'search_aws_provider_docs_impl',
12
+ 'search_awscc_provider_docs_impl',
13
+ 'search_specific_aws_ia_modules_impl',
14
+ 'run_checkov_scan_impl',
15
+ ]
@@ -0,0 +1,206 @@
1
+ """Implementation of Terraform command execution tool."""
2
+
3
+ import json
4
+ import os
5
+ import re
6
+ import subprocess
7
+ from awslabs.terraform_mcp_server.impl.tools.utils import get_dangerous_patterns
8
+ from awslabs.terraform_mcp_server.models import TerraformExecutionRequest, TerraformExecutionResult
9
+ from loguru import logger
10
+
11
+
12
+ async def execute_terraform_command_impl(
13
+ request: TerraformExecutionRequest,
14
+ ) -> TerraformExecutionResult:
15
+ """Execute Terraform workflow commands against an AWS account.
16
+
17
+ This tool runs Terraform commands (init, plan, validate, apply, destroy) in the
18
+ specified working directory, with optional variables and region settings.
19
+
20
+ Parameters:
21
+ request: Details about the Terraform command to execute
22
+
23
+ Returns:
24
+ A TerraformExecutionResult object containing command output and status
25
+ """
26
+ logger.info(f"Executing 'terraform {request.command}' in {request.working_directory}")
27
+
28
+ # Helper function to clean output text
29
+ def clean_output_text(text: str) -> str:
30
+ """Clean output text by removing or replacing problematic Unicode characters.
31
+
32
+ Args:
33
+ text: The text to clean
34
+
35
+ Returns:
36
+ Cleaned text with ASCII-friendly replacements
37
+ """
38
+ if not text:
39
+ return text
40
+
41
+ # First remove ANSI escape sequences (color codes, cursor movement)
42
+ ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
43
+ text = ansi_escape.sub('', text)
44
+
45
+ # Remove C0 and C1 control characters (except common whitespace)
46
+ control_chars = re.compile(r'[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F]')
47
+ text = control_chars.sub('', text)
48
+
49
+ # Replace HTML entities
50
+ html_entities = {
51
+ '-&gt;': '->', # Replace HTML arrow
52
+ '&lt;': '<', # Less than
53
+ '&gt;': '>', # Greater than
54
+ '&amp;': '&', # Ampersand
55
+ }
56
+ for entity, replacement in html_entities.items():
57
+ text = text.replace(entity, replacement)
58
+
59
+ # Replace box-drawing and other special Unicode characters with ASCII equivalents
60
+ unicode_chars = {
61
+ '\u2500': '-', # Horizontal line
62
+ '\u2502': '|', # Vertical line
63
+ '\u2514': '+', # Up and right
64
+ '\u2518': '+', # Up and left
65
+ '\u2551': '|', # Double vertical
66
+ '\u2550': '-', # Double horizontal
67
+ '\u2554': '+', # Double down and right
68
+ '\u2557': '+', # Double down and left
69
+ '\u255a': '+', # Double up and right
70
+ '\u255d': '+', # Double up and left
71
+ '\u256c': '+', # Double cross
72
+ '\u2588': '#', # Full block
73
+ '\u25cf': '*', # Black circle
74
+ '\u2574': '-', # Left box drawing
75
+ '\u2576': '-', # Right box drawing
76
+ '\u2577': '|', # Down box drawing
77
+ '\u2575': '|', # Up box drawing
78
+ }
79
+ for char, replacement in unicode_chars.items():
80
+ text = text.replace(char, replacement)
81
+
82
+ return text
83
+
84
+ # Set environment variables for AWS region if provided
85
+ env = os.environ.copy()
86
+ if request.aws_region:
87
+ env['AWS_REGION'] = request.aws_region
88
+
89
+ # Security check for command injection
90
+ allowed_commands = ['init', 'plan', 'validate', 'apply', 'destroy']
91
+ if request.command not in allowed_commands:
92
+ logger.error(f'Invalid Terraform command: {request.command}')
93
+ return TerraformExecutionResult(
94
+ command=f'terraform {request.command}',
95
+ status='error',
96
+ error_message=f'Invalid Terraform command: {request.command}. Allowed commands are: {", ".join(allowed_commands)}',
97
+ working_directory=request.working_directory,
98
+ outputs=None,
99
+ )
100
+
101
+ # Check for potentially dangerous characters or command injection attempts
102
+ dangerous_patterns = get_dangerous_patterns()
103
+ logger.debug(f'Checking for {len(dangerous_patterns)} dangerous patterns')
104
+
105
+ for pattern in dangerous_patterns:
106
+ if request.variables:
107
+ # Check if the pattern is in any of the variable values
108
+ for var_name, var_value in request.variables.items():
109
+ if pattern in str(var_value) or pattern in str(var_name):
110
+ logger.error(
111
+ f'Potentially dangerous pattern detected in variable {var_name}: {pattern}'
112
+ )
113
+ return TerraformExecutionResult(
114
+ command=f'terraform {request.command}',
115
+ status='error',
116
+ error_message=f"Security violation: Potentially dangerous pattern '{pattern}' detected in variable '{var_name}'",
117
+ working_directory=request.working_directory,
118
+ outputs=None,
119
+ )
120
+
121
+ # Build the command
122
+ cmd = ['terraform', request.command]
123
+
124
+ # Add auto-approve flag for apply and destroy commands to make them non-interactive
125
+ if request.command in ['apply', 'destroy']:
126
+ logger.info(f'Adding -auto-approve flag to {request.command} command')
127
+ cmd.append('-auto-approve')
128
+
129
+ # Add variables only for commands that accept them (plan, apply, destroy)
130
+ if request.command in ['plan', 'apply', 'destroy'] and request.variables:
131
+ logger.info(f'Adding {len(request.variables)} variables to {request.command} command')
132
+ for key, value in request.variables.items():
133
+ cmd.append(f'-var={key}={value}')
134
+
135
+ # Execute command
136
+ try:
137
+ process = subprocess.run(
138
+ cmd, cwd=request.working_directory, capture_output=True, text=True, env=env
139
+ )
140
+
141
+ # Prepare the result
142
+ stdout = process.stdout
143
+ stderr = process.stderr if process.stderr else ''
144
+
145
+ # Clean output text if requested
146
+ if request.strip_ansi:
147
+ logger.debug('Cleaning command output text (ANSI codes and control characters)')
148
+ stdout = clean_output_text(stdout)
149
+ stderr = clean_output_text(stderr)
150
+
151
+ result = {
152
+ 'command': f'terraform {request.command}',
153
+ 'status': 'success' if process.returncode == 0 else 'error',
154
+ 'return_code': process.returncode,
155
+ 'stdout': stdout,
156
+ 'stderr': stderr,
157
+ 'working_directory': request.working_directory,
158
+ 'outputs': None,
159
+ }
160
+
161
+ # Get outputs if this was a successful apply command
162
+ if request.command == 'apply' and process.returncode == 0:
163
+ try:
164
+ logger.info('Getting Terraform outputs')
165
+ output_process = subprocess.run(
166
+ ['terraform', 'output', '-json'],
167
+ cwd=request.working_directory,
168
+ capture_output=True,
169
+ text=True,
170
+ env=env,
171
+ )
172
+
173
+ if output_process.returncode == 0 and output_process.stdout:
174
+ # Get output and clean it if needed
175
+ output_stdout = output_process.stdout
176
+ if request.strip_ansi:
177
+ output_stdout = clean_output_text(output_stdout)
178
+
179
+ # Parse the JSON output
180
+ raw_outputs = json.loads(output_stdout)
181
+
182
+ # Process outputs to extract values from complex structure
183
+ processed_outputs = {}
184
+ for key, value in raw_outputs.items():
185
+ # Terraform outputs in JSON format have a nested structure
186
+ # with 'value', 'type', and sometimes 'sensitive'
187
+ if isinstance(value, dict) and 'value' in value:
188
+ processed_outputs[key] = value['value']
189
+ else:
190
+ processed_outputs[key] = value
191
+
192
+ result['outputs'] = processed_outputs
193
+ logger.info(f'Extracted {len(processed_outputs)} Terraform outputs')
194
+ except Exception as e:
195
+ logger.warning(f'Failed to get Terraform outputs: {e}')
196
+
197
+ # Return the output
198
+ return TerraformExecutionResult(**result)
199
+ except Exception as e:
200
+ return TerraformExecutionResult(
201
+ command=f'terraform {request.command}',
202
+ status='error',
203
+ error_message=str(e),
204
+ working_directory=request.working_directory,
205
+ outputs=None,
206
+ )