Secure Development Environment Setup

Secure Development Environment Setup

A secure development environment forms the foundation for secure software. This begins with properly configured development machines, secure access to source code repositories, and isolated development environments that mirror production security controls. Developers need the right tools and configurations to write secure code effectively.

# Python - Secure Development Environment Configuration
import os
import json
import subprocess
from pathlib import Path
from typing import Dict, List, Optional
import yaml
import toml
import configparser

class SecureDevEnvironment:
    """Configure and validate secure development environment"""
    
    def __init__(self, project_root: str):
        self.project_root = Path(project_root)
        self.config = self._load_security_config()
        self.validation_results = {}
    
    def _load_security_config(self) -> Dict:
        """Load security configuration from various sources"""
        config = {
            'pre_commit_hooks': [],
            'security_tools': {},
            'ide_plugins': [],
            'git_hooks': {},
            'environment_checks': []
        }
        
        # Load from .security.yml if exists
        security_yml = self.project_root / '.security.yml'
        if security_yml.exists():
            with open(security_yml) as f:
                config.update(yaml.safe_load(f))
        
        return config
    
    def setup_pre_commit_hooks(self):
        """Configure pre-commit hooks for security checks"""
        pre_commit_config = {
            'repos': [
                {
                    'repo': 'https://github.com/pre-commit/pre-commit-hooks',
                    'rev': 'v4.4.0',
                    'hooks': [
                        {'id': 'trailing-whitespace'},
                        {'id': 'end-of-file-fixer'},
                        {'id': 'check-yaml'},
                        {'id': 'check-added-large-files', 'args': ['--maxkb=1000']},
                        {'id': 'check-merge-conflict'},
                        {'id': 'detect-private-key'}
                    ]
                },
                {
                    'repo': 'https://github.com/psf/black',
                    'rev': '23.3.0',
                    'hooks': [{'id': 'black'}]
                },
                {
                    'repo': 'https://github.com/PyCQA/bandit',
                    'rev': '1.7.5',
                    'hooks': [
                        {
                            'id': 'bandit',
                            'args': ['-c', '.bandit'],
                            'files': '.py$'
                        }
                    ]
                },
                {
                    'repo': 'https://github.com/Yelp/detect-secrets',
                    'rev': 'v1.4.0',
                    'hooks': [
                        {
                            'id': 'detect-secrets',
                            'args': ['--baseline', '.secrets.baseline']
                        }
                    ]
                },
                {
                    'repo': 'local',
                    'hooks': [
                        {
                            'id': 'safety-check',
                            'name': 'Safety check',
                            'entry': 'safety check',
                            'language': 'system',
                            'pass_filenames': False,
                            'files': 'requirements.*\\.txt$'
                        },
                        {
                            'id': 'pytest-security',
                            'name': 'Security tests',
                            'entry': 'pytest tests/security/',
                            'language': 'system',
                            'pass_filenames': False,
                            'always_run': True
                        }
                    ]
                }
            ],
            'ci': {
                'autofix_prs': False,
                'autoupdate_schedule': 'weekly'
            }
        }
        
        # Write pre-commit config
        pre_commit_file = self.project_root / '.pre-commit-config.yaml'
        with open(pre_commit_file, 'w') as f:
            yaml.dump(pre_commit_config, f, default_flow_style=False)
        
        # Install pre-commit
        subprocess.run(['pre-commit', 'install'], cwd=self.project_root)
        
        print("✓ Pre-commit hooks configured")
    
    def create_security_baseline(self):
        """Create baseline for secret detection"""
        try:
            # Initialize detect-secrets baseline
            result = subprocess.run(
                ['detect-secrets', 'scan', '--baseline', '.secrets.baseline'],
                cwd=self.project_root,
                capture_output=True,
                text=True
            )
            
            if result.returncode == 0:
                print("✓ Secrets baseline created")
            else:
                print(f"✗ Failed to create secrets baseline: {result.stderr}")
                
        except Exception as e:
            print(f"✗ Error creating secrets baseline: {e}")
    
    def configure_ide_security(self):
        """Generate IDE security configurations"""
        # VS Code settings
        vscode_settings = {
            "python.linting.enabled": True,
            "python.linting.pylintEnabled": True,
            "python.linting.banditEnabled": True,
            "python.linting.mypyEnabled": True,
            "python.formatting.provider": "black",
            "editor.formatOnSave": True,
            "files.exclude": {
                "**/.git": True,
                "**/.env": True,
                "**/*.pyc": True,
                "**/__pycache__": True,
                "**/.pytest_cache": True
            },
            "python.linting.banditArgs": [
                "-c",
                ".bandit"
            ],
            "extensions.recommendations": [
                "ms-python.python",
                "ms-python.vscode-pylance",
                "njpwerner.autodocstring",
                "streetsidesoftware.code-spell-checker",
                "dotenv.dotenv-vscode"
            ]
        }
        
        # Create .vscode directory
        vscode_dir = self.project_root / '.vscode'
        vscode_dir.mkdir(exist_ok=True)
        
        # Write settings
        with open(vscode_dir / 'settings.json', 'w') as f:
            json.dump(vscode_settings, f, indent=2)
        
        # PyCharm/IntelliJ configuration
        self._configure_jetbrains_security()
        
        print("✓ IDE security settings configured")
    
    def setup_git_security(self):
        """Configure Git security settings"""
        git_attributes = """# Git attributes for security
*.key filter=git-crypt diff=git-crypt
*.pem filter=git-crypt diff=git-crypt
*.p12 filter=git-crypt diff=git-crypt
*.pfx filter=git-crypt diff=git-crypt
.env filter=git-crypt diff=git-crypt
.env.* filter=git-crypt diff=git-crypt

# Prevent committing of sensitive files
*.key binary
*.pem binary
*.p12 binary
*.pfx binary
"""
        
        with open(self.project_root / '.gitattributes', 'w') as f:
            f.write(git_attributes)
        
        # Configure git hooks
        hooks_dir = self.project_root / '.git' / 'hooks'
        if hooks_dir.exists():
            # Pre-push hook for security scanning
            pre_push_hook = """#!/bin/bash
# Pre-push hook for security checks

echo "Running security checks before push..."

# Run security tests
pytest tests/security/ -v
if [ $? -ne 0 ]; then
    echo "Security tests failed. Push aborted."
    exit 1
fi

# Check for secrets
detect-secrets scan --baseline .secrets.baseline
if [ $? -ne 0 ]; then
    echo "Potential secrets detected. Push aborted."
    exit 1
fi

# Run dependency check
safety check
if [ $? -ne 0 ]; then
    echo "Vulnerable dependencies detected. Push aborted."
    exit 1
fi

echo "Security checks passed!"
"""
            
            pre_push_file = hooks_dir / 'pre-push'
            with open(pre_push_file, 'w') as f:
                f.write(pre_push_hook)
            
            # Make executable
            os.chmod(pre_push_file, 0o755)
        
        print("✓ Git security configured")
    
    def create_security_policies(self):
        """Create security policy files"""
        # Security policy template
        security_md = """# Security Policy