Commit graph

2 commits

Author SHA1 Message Date
Jack Ivanov
4289db043a
Refactor StrongSwan PKI tasks to use Ansible crypto modules and remove legacy OpenSSL scripts (#14809)
* Refactor StrongSwan PKI automation with Ansible crypto modules

- Replace shell-based OpenSSL commands with community.crypto modules
- Remove custom OpenSSL config template and manual file management
- Upgrade Ansible to 11.8.0 in requirements.txt
- Improve idempotency, maintainability, and security of certificate and CRL handling

* Enhance nameConstraints with comprehensive exclusions

- Add email domain exclusions (.com, .org, .net, .gov, .edu, .mil, .int)
- Include private IPv4 network exclusions
- Add IPv6 null route exclusion
- Preserve all security constraints from original openssl.cnf.j2
- Note: Complex IPv6 conditional logic simplified for Ansible compatibility

Security: Maintains defense-in-depth certificate scope restrictions

* Refactor StrongSwan PKI with comprehensive security enhancements and hybrid testing

## StrongSwan PKI Modernization
- Migrated from shell-based OpenSSL commands to Ansible community.crypto modules
- Simplified complex Jinja2 templates while preserving all security properties
- Added clear, concise comments explaining security rationale and Apple compatibility

## Enhanced Security Implementation (Issues #75, #153)
- **Name constraints**: CA certificates restricted to specific IP/email domains
- **EKU role separation**: Server certs (serverAuth only) vs client certs (clientAuth only)
- **Domain exclusions**: Blocks public domains (.com, .org, etc.) and private IP ranges
- **Apple compatibility**: SAN extensions and PKCS#12 compatibility2022 encryption
- **Certificate revocation**: Automated CRL generation for removed users

## Comprehensive Test Suite
- **Hybrid testing**: Validates real certificates when available, config validation for CI
- **Security validation**: Verifies name constraints, EKU restrictions, role separation
- **Apple compatibility**: Tests SAN extensions and PKCS#12 format compliance
- **Certificate chain**: Validates CA signing and certificate validity periods
- **CI-compatible**: No deployment required, tests Ansible configuration directly

## Configuration Updates
- Updated CLAUDE.md: Ansible version rationale (stay current for security/performance)
- Streamlined comments: Removed duplicative explanations while preserving technical context
- Maintained all Issue #75/#153 security enhancements with modern Ansible approach

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix linting issues across the codebase

## Python Code Quality (ruff)
- Fixed import organization and removed unused imports in test files
- Replaced `== True` comparisons with direct boolean checks
- Added noqa comments for intentional imports in test modules

## YAML Formatting (yamllint)
- Removed trailing spaces in openssl.yml comments
- All YAML files now pass yamllint validation (except one pre-existing long regex line)

## Code Consistency
- Maintained proper import ordering in test files
- Ensured all code follows project linting standards
- Ready for CI pipeline validation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Replace magic number with configurable certificate validity period

## Maintainability Improvement
- Replaced hardcoded `+3650d` (10 years) with configurable variable
- Added `certificate_validity_days: 3650` in vars section with clear documentation
- Applied consistently to both server and client certificate signing

## Benefits
- Single location to modify certificate validity period
- Supports compliance requirements for shorter certificate lifespans
- Improves code readability and maintainability
- Eliminates magic number duplication

## Backwards Compatibility
- Default remains 10 years (3650 days) - no behavior change
- Organizations can now easily customize certificate validity as needed

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update test to validate configurable certificate validity period

## Test Update
- Fixed test failure after replacing magic number with configurable variable
- Now validates both variable definition and usage patterns:
  - `certificate_validity_days: 3650` (configurable parameter)
  - `ownca_not_after: "+{{ certificate_validity_days }}d"` (variable usage)

## Improved Test Coverage
- Better validation: checks that validity is configurable, not hardcoded
- Maintains backwards compatibility verification (10-year default)
- Ensures proper Ansible variable templating is used

## Verified
- Config validation mode: All 6 tests pass ✓
- Validates the maintainability improvement from previous commit

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update to Python 3.11 minimum and fix IPv6 constraint format

- Update Python requirement from 3.10 to 3.11 to align with Ansible 11
- Pin Ansible collections in requirements.yml for stability
- Fix invalid IPv6 constraint format causing deployment failure
- Update ruff target-version to py311 for consistency

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix x509_crl mode parameter and auto-fix Python linting

- Remove deprecated 'mode' parameter from x509_crl task
- Add separate file task to set CRL permissions (0644)
- Auto-fix Python datetime import (use datetime.UTC alias)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix final IPv6 constraint format in defaults template

- Update nameConstraints template in defaults/main.yml
- Change malformed IP:0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0 to correct IP:::/0
- This ensures both Ansible crypto modules and OpenSSL template use consistent IPv6 format

* Fix critical certificate generation issues for macOS/iOS VPN compatibility

This commit addresses multiple certificate generation bugs in the Ansible crypto
module implementation that were causing VPN authentication failures on Apple devices.

Fixes implemented:

1. **Basic Constraints Extension**: Added missing `CA:FALSE` constraints to both
   server and client certificate CSRs. This was causing certificate chain validation
   errors on macOS/iOS devices.

2. **Subject Key Identifier**: Added `create_subject_key_identifier: true` to CA
   certificate generation to enable proper Authority Key Identifier creation in
   signed certificates.

3. **Complete Name Constraints**: Fixed missing DNS and IPv6 constraints in CA
   certificate that were causing size differences compared to legacy shell-based
   generation. Now includes:
   - DNS constraints for the deployment-specific domain
   - IPv6 permitted addresses when IPv6 support is enabled
   - Complete IPv6 exclusion ranges (fc00::/7, fe80::/10, 2001:db8::/32)

These changes bring the certificate format much closer to the working shell-based
implementation and should resolve most macOS/iOS VPN connectivity issues.

**Outstanding Issue**: Authority Key Identifier still incomplete - missing DirName
and serial components. The community.crypto module limitation may require
additional investigation or alternative approaches.

Certificate size improvements: Server certificates increased from ~750 to ~775 bytes,
CA certificates from ~1070 to ~1250 bytes, bringing them closer to the expected
~3000 byte target size.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix certificate generation and improve version parsing

This commit addresses multiple issues found during macOS certificate validation:

Certificate Generation Fixes:
- Add Basic Constraints (CA:FALSE) to server and client certificates
- Generate Subject Key Identifier for proper AKI creation
- Improve Name Constraints implementation for security
- Update community.crypto to version 3.0.3 for latest fixes

Code Quality Improvements:
- Clean up certificate comments and remove obsolete references
- Fix server certificate identification in tests
- Update datetime comparisons for cryptography library compatibility
- Fix Ansible version parsing in main.yml with proper regex handling

Testing:
- All certificate validation tests pass
- Ansible syntax checks pass
- Python linting (ruff) clean
- YAML linting (yamllint) clean

These changes restore macOS/iOS certificate compatibility while maintaining
security best practices and improving code maintainability.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Enhance security documentation with comprehensive inline comments

Add detailed technical explanations for critical PKI security features:

- Name Constraints: Defense-in-depth rationale and attack prevention
- Public domain/network exclusions: Impersonation attack prevention
- RFC 1918 private IP blocking: Lateral movement prevention
- IPv6 constraint strategy: ULA/link-local/documentation range handling
- Role separation enforcement: Server vs client EKU restrictions
- CA delegation prevention: pathlen:0 security implications
- Cross-deployment isolation: UUID-based certificate scope limiting

These comments provide essential context for maintainers to understand
the security importance of each configuration without referencing
external issue numbers, ensuring long-term maintainability.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix CI test failures in PKI certificate validation

Resolve Smart Test Selection workflow failures by fixing test validation logic:

**Certificate Configuration Fixes:**
- Remove unnecessary serverAuth/clientAuth EKUs from CA certificate
- CA now only has IPsec End Entity EKU for VPN-specific certificate issuance
- Maintains proper role separation between server and client certificates

**Test Validation Improvements:**
- Fix domain exclusion detection to handle both single and double quotes in YAML
- Improve EKU validation to check actual configuration lines, not comments
- Server/client certificate tests now correctly parse YAML structure
- Tests pass in both CI mode (config validation) and local mode (real certificates)

**Root Cause:**
The CI failures were caused by overly broad test assertions that:
1. Expected double-quoted strings but found single-quoted YAML
2. Detected EKU keywords in comments rather than actual configuration
3. Failed to properly parse YAML list structures

All security constraints remain intact - no actual security issues were present.
The certificate generation produces properly constrained certificates for VPN use.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix trailing space in openssl.yml for yamllint compliance

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-05 05:40:28 -07:00
Jack Ivanov
5214c5f819
Refactor WireGuard key management (#14803)
* Refactor WireGuard key management: generate all keys locally with Ansible modules

- Move all WireGuard key generation from remote hosts to local execution via Ansible modules
- Enhance x25519_pubkey module for robust, idempotent, and secure key handling
- Update WireGuard role tasks to use local key generation and management
- Improve error handling and support for check mode

* Improve x25519_pubkey module code quality and add integration tests

Code Quality Improvements:
- Fix import organization and Ruff linting errors
- Replace bare except clauses with practical error handling
- Simplify documentation while maintaining useful debugging info
- Use dictionary literals instead of dict() calls for better performance

New Integration Test:
- Add comprehensive WireGuard key generation test (test_wireguard_key_generation.py)
- Tests actual deployment scenarios matching roles/wireguard/tasks/keys.yml
- Validates mathematical correctness of X25519 key derivation
- Tests both file and string input methods used by Algo
- Includes consistency validation and WireGuard tool integration
- Addresses documented test gap in tests/README.md line 63-67

Test Coverage:
- Module import validation
- Raw private key file processing
- Base64 private key string processing
- Key derivation consistency checks
- Optional WireGuard tool validation (when available)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Trigger CI build for PR #14803

Testing x25519_pubkey module improvements and WireGuard key generation changes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix yamllint error: add missing newline at end of keys.yml

Resolves: no new line character at the end of file (new-line-at-end-of-file)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix critical binary data corruption bug in x25519_pubkey module

Issue: Private keys with whitespace-like bytes (0x09, 0x0A, etc.) at edges
were corrupted by .strip() call on binary data, causing 32-byte keys to
become 31 bytes and deployment failures.

Root Cause:
- Called .strip() on raw binary data unconditionally
- X25519 keys containing whitespace bytes were truncated
- Error: "got 31 bytes" instead of expected 32 bytes

Fix:
- Only strip whitespace when processing base64 text data
- Preserve raw binary data integrity for 32-byte keys
- Maintain backward compatibility with both formats

Addresses deployment failure: "Private key file must be either base64
or exactly 32 raw bytes, got 31 bytes"

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add inline comments to prevent binary data corruption bug

Explain the base64/raw file detection logic with clear warnings about
the critical issue where .strip() on raw binary data corrupts X25519
keys containing whitespace-like bytes (0x09, 0x0A, etc.).

This prevents future developers from accidentally reintroducing the
'got 31 bytes' deployment error by misunderstanding the dual-format
key handling logic.

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-03 18:24:12 -07:00