mirror of
https://github.com/trailofbits/algo.git
synced 2025-09-08 04:53:08 +02:00
* Add test to detect inline comments in Jinja2 expressions within YAML files This test would have caught the bug reported where inline comments (#) within Jinja2 expressions in YAML task files caused Ansible template errors. The test: - Extracts and validates all Jinja2 expressions from YAML files - Specifically detects inline comments within {{ }} and {% %} blocks - Includes regression test for the exact reported bug pattern - Avoids false positives (# in strings, escaped #, comments outside expressions) - Focuses on the critical inline comment issue The original bug was in roles/strongswan/tasks/openssl.yml where comments like "# Per-deployment UUID..." were placed inside a Jinja2 expression, causing "unexpected char '#'" errors during playbook execution. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Refactor test to use pytest framework and add comprehensive edge cases - Converted standalone script to proper pytest test functions - Replaced main() with individual test functions using pytest assertions - Added comprehensive edge case tests for inline comment detection: * Hash symbols in strings (should pass) * Escaped hashes (should pass) * Comments in control blocks (should fail) * Multi-line expressions with comments (should fail) * URL fragments and hex colors (should pass) - Test functions now properly integrate with pytest: * test_regression_openssl_inline_comments() - regression test * test_edge_cases_inline_comments() - comprehensive edge cases * test_yaml_files_no_inline_comments() - scan all YAML files * test_openssl_file_specifically() - test the originally buggy file This addresses the review feedback about pytest integration and adds the suggested test cases for better coverage. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix linter issues in test_yaml_jinja2_expressions.py - Fixed trailing whitespace issues (W293) - Applied ruff formatting for consistent code style - All tests still pass after formatting changes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Add mutation testing guidance to CLAUDE.md Added a section on writing effective tests that emphasizes the importance of verifying that tests actually detect failure cases. This lightweight mutation testing approach ensures: - Tests catch the specific bugs they're designed to prevent - We avoid false confidence from tests that always pass - Test purposes are clear and documented - Both success and failure cases are validated The guidance includes a concrete example from our recent inline comment detection test, showing how to verify both the problematic pattern (should fail) and the fixed pattern (should pass). 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
11 KiB
11 KiB
CLAUDE.md - LLM Guidance for Algo VPN
This document provides essential context and guidance for LLMs working on the Algo VPN codebase. It captures important learnings, patterns, and best practices discovered through extensive work with this project.
Project Overview
Algo is an Ansible-based tool that sets up a personal VPN in the cloud. It's designed to be:
- Security-focused: Creates hardened VPN servers with minimal attack surface
- Easy to use: Automated deployment with sensible defaults
- Multi-platform: Supports various cloud providers and operating systems
- Privacy-preserving: No logging, minimal data retention
Core Technologies
- VPN Protocols: WireGuard (preferred) and IPsec/IKEv2
- Configuration Management: Ansible (currently v9.x)
- Languages: Python, YAML, Shell, Jinja2 templates
- Supported Providers: AWS, Azure, DigitalOcean, GCP, Vultr, Hetzner, local deployment
Architecture and Structure
Directory Layout
algo/
├── main.yml # Primary playbook
├── users.yml # User management playbook
├── server.yml # Server-specific tasks
├── config.cfg # Main configuration file
├── pyproject.toml # Python project configuration and dependencies
├── uv.lock # Exact dependency versions lockfile
├── requirements.yml # Ansible collections
├── roles/ # Ansible roles
│ ├── common/ # Base system configuration
│ ├── wireguard/ # WireGuard VPN setup
│ ├── strongswan/ # IPsec/IKEv2 setup
│ ├── dns/ # DNS configuration (dnsmasq, dnscrypt)
│ ├── ssh_tunneling/ # SSH tunnel setup
│ └── cloud-*/ # Cloud provider specific roles
├── library/ # Custom Ansible modules
├── playbooks/ # Supporting playbooks
└── tests/ # Test suite
└── unit/ # Python unit tests
Key Roles
- common: Firewall rules, system hardening, package management
- wireguard: WireGuard server/client configuration
- strongswan: IPsec server setup with certificate generation
- dns: DNS encryption and ad blocking
- cloud-*: Provider-specific instance creation
Critical Dependencies and Version Management
Current Versions (MUST maintain compatibility)
ansible==11.8.0 # Stay current to get latest security, performance and bugfixes
jinja2~=3.1.6 # Security fix for CVE-2025-27516
netaddr==1.3.0 # Network address manipulation
Version Update Guidelines
- Be Conservative: Prefer minor version bumps over major ones
- Security First: Always prioritize security updates (CVEs)
- Test Thoroughly: Run all tests before updating
- Document Changes: Explain why each update is necessary
Ansible Collections
Currently unpinned in requirements.yml
, but key ones include:
community.general
ansible.posix
openstack.cloud
Development Practices
Code Style and Linting
Python (ruff)
# pyproject.toml configuration
[tool.ruff]
target-version = "py311"
line-length = 120
[tool.ruff.lint]
select = ["E", "W", "F", "I", "B", "C4", "UP"]
YAML (yamllint)
- Document start markers (
---
) required - No trailing spaces
- Newline at end of file
- Quote
'on':
in GitHub workflows (truthy value)
Shell Scripts (shellcheck)
- Quote all variables:
"${var}"
- Use
set -euo pipefail
for safety
PowerShell Scripts (PSScriptAnalyzer)
- Use approved verbs (Get-, Set-, New-, etc.)
- Avoid positional parameters in functions
- Use proper error handling with try/catch
- Note: Algo's PowerShell script is a WSL wrapper since Ansible doesn't run natively on Windows
Ansible (ansible-lint)
- Many warnings are suppressed in
.ansible-lint
- Focus on errors, not warnings
- Common suppressions:
name[missing]
,risky-file-permissions
Documentation Style
- Avoid excessive header nesting (prefer 2-3 levels maximum)
- Don't overuse bold formatting in lists - use sparingly for emphasis only
- Write flowing paragraphs instead of choppy bullet-heavy sections
- Keep formatting clean and readable - prefer natural text over visual noise
- Use numbered lists for procedures, simple bullets for feature lists
- Example: "Navigate to Network → Interfaces" not "Navigate to Network → Interfaces"
Git Workflow
- Create feature branches from
master
- Make atomic commits with clear messages
- Run all linters before pushing
- Update PR description with test results
- Squash commits if requested
Testing Requirements
Before pushing any changes:
# Python tests
pytest tests/unit/ -v
# Ansible syntax
ansible-playbook main.yml --syntax-check
ansible-playbook users.yml --syntax-check
# Linters
ansible-lint
yamllint .
ruff check .
shellcheck *.sh
# PowerShell (if available)
pwsh -Command "Invoke-ScriptAnalyzer -Path ./algo.ps1"
Writing Effective Tests - Mutation Testing Approach
When writing tests, always verify that your test actually detects the failure case. This is a form of lightweight mutation testing that ensures tests add real value:
- Write the test for the bug/issue you're preventing
- Temporarily introduce the bug to verify the test fails
- Fix the bug and verify the test passes
- Document what specific issue the test prevents
Example from our codebase:
def test_regression_openssl_inline_comments():
"""Tests that we detect inline comments in Jinja2 expressions."""
# This pattern SHOULD fail (has inline comments)
problematic = "{{ ['DNS:' + id, # comment ] }}"
assert not validate(problematic), "Should detect inline comments"
# This pattern SHOULD pass (no inline comments)
fixed = "{{ ['DNS:' + id] }}"
assert validate(fixed), "Should pass without comments"
This practice ensures:
- Tests aren't just checking happy paths
- Tests will actually catch regressions
- The test's purpose is clear to future maintainers
- We avoid false confidence from tests that always pass
Common Issues and Solutions
1. Ansible-lint "name[missing]" Warnings
- Added to skip_list in
.ansible-lint
- Too many tasks to fix immediately (113+)
- Focus on new code having proper names
3. Jinja2 Template Complexity
- Many templates use Ansible-specific filters
- Test templates with
tests/unit/test_template_rendering.py
- Mock Ansible filters when testing
4. OpenSSL Version Compatibility
# Check version and use appropriate flags
{{ (openssl_version is version('3', '>=')) | ternary('-legacy', '') }}
5. IPv6 Endpoint Formatting
- WireGuard configs must bracket IPv6 addresses
- Template logic:
{% if ':' in IP %}[{{ IP }}]:{{ port }}{% else %}{{ IP }}:{{ port }}{% endif %}
Security Considerations
Always Priority One
- Never expose secrets: No passwords/keys in commits
- CVE Response: Update immediately when security issues found
- Least Privilege: Minimal permissions, dropped capabilities
- Secure Defaults: Strong crypto, no logging, firewall rules
Certificate Management
- Elliptic curve cryptography (secp384r1)
- Proper CA password handling
- Certificate revocation support
- Secure storage in
/etc/ipsec.d/
Network Security
- Strict firewall rules (iptables/ip6tables)
- No IP forwarding except for VPN
- DNS leak protection
- Kill switch implementation
Platform Support
Operating Systems
- Primary: Ubuntu 20.04/22.04 LTS
- Secondary: Debian 11/12
- Clients: Windows, macOS, iOS, Android, Linux
Cloud Providers
Each has specific requirements:
- AWS: Requires boto3, specific AMI IDs
- Azure: Complex networking setup
- DigitalOcean: Simple API, good for testing
- Local: KVM/Docker for development
Architecture Considerations
- Support both x86_64 and ARM64
- Some providers have limited ARM support
- Performance varies by instance type
CI/CD Pipeline
GitHub Actions Workflows
- lint.yml: Runs ansible-lint on all pushes
- main.yml: Tests cloud provider configurations
- smart-tests.yml: Selective test running based on changes
- integration-tests.yml: Full deployment tests (currently disabled)
Test Categories
- Unit Tests: Python-based, test logic and templates
- Syntax Checks: Ansible playbook validation
- Linting: Code quality enforcement
- Integration: Full deployment testing (needs work)
Maintenance Guidelines
Dependency Updates
- Check for security vulnerabilities monthly
- Update conservatively (minor versions)
- Test on multiple platforms
- Document in PR why updates are needed
Issue Triage
- Security issues: Priority 1
- Broken functionality: Priority 2
- Feature requests: Priority 3
- Check issues for duplicates
Pull Request Standards
- Clear description of changes
- Test results included
- Linter compliance
- Conservative approach
Working with Algo
Local Development Setup
# Install dependencies
uv sync
uv run ansible-galaxy install -r requirements.yml
# Run local deployment
ansible-playbook main.yml -e "provider=local"
Common Tasks
Adding a New User
ansible-playbook users.yml -e "server=SERVER_NAME"
Updating Dependencies
- Create a new branch
- Update pyproject.toml conservatively
- Run
uv lock
to update lockfile - Run all tests
- Document security fixes
Debugging Deployment Issues
- Check
ansible-playbook -vvv
output - Verify cloud provider credentials
- Check firewall rules
- Review generated configs in
configs/
Important Context for LLMs
What Makes Algo Special
- Simplicity: One command to deploy
- Security: Hardened by default
- No Bloat: Minimal dependencies
- Privacy: No telemetry or logging
User Expectations
- It should "just work"
- Security is non-negotiable
- Backwards compatibility matters
- Clear error messages
Common User Profiles
- Privacy Advocates: Want secure communications
- Travelers: Need reliable VPN access
- Small Teams: Shared VPN for remote work
- Developers: Testing and development
Maintenance Philosophy
- Stability over features
- Security over convenience
- Clarity over cleverness
- Test everything
Final Notes
When working on Algo:
- Think Security First: Every change should maintain or improve security
- Test Thoroughly: Multiple platforms, both VPN types
- Document Clearly: Users may not be technical
- Be Conservative: This is critical infrastructure
- Respect Privacy: No tracking, minimal logging
Remember: People trust Algo with their privacy and security. Every line of code matters.