diff --git a/roles/openssh/.ansible-lint b/roles/openssh/.ansible-lint new file mode 100644 index 0000000..c04a869 --- /dev/null +++ b/roles/openssh/.ansible-lint @@ -0,0 +1,71 @@ +--- +# Ansible-lint configuration +# Uses production profile for highest quality standards + +# Profile selection (production is strictest) +profile: production + +# Exclude paths +exclude_paths: + - .cache/ + - .github/ + - collections/ + - tests/output/ + - '*.md' + - .tox/ + - molecule/default/molecule.yml + +# Enable specific security-focused rules +enable_list: + - no-log-password # Require no_log for password fields + - risky-file-permissions # Catch overly permissive file modes + - command-instead-of-shell # Prefer command over shell module + - name[casing] # Enforce consistent task naming + - yaml[line-length] # Max line length + - fqcn # Require Fully Qualified Collection Names + - jinja[spacing] # Consistent Jinja2 formatting + +# Skip list for rules we explicitly don't need +skip_list: + - role-name[path] # We use namespace in paths (generic/lshw) + - galaxy[no-changelog] # We don't use Galaxy + +# Strict mode - warnings become errors +strict: true + +# Warn about potential issues +warn_list: + - experimental # Warn about experimental features + - no-changed-when # Tasks should have changed_when + - no-handler # Warn if notify without handler + +# Task naming requirements +task_name_prefix: "{stem} | " # Optional prefix for better organization + +# Offline mode for CI/CD +offline: false + +# Mock modules that may not be available during linting +mock_modules: + - docker_container + - docker_compose + - community.general.docker_compose + +# Mock roles for testing +mock_roles: + - community.general + - ansible-role-openssh_server + +# Kinds of files to lint +kinds: + - yaml: "**/*.yaml" + - yaml: "**/*.yml" + - playbook: "playbooks/*.yml" + - tasks: "roles/*/tasks/*.yml" + - handlers: "roles/*/handlers/*.yml" + - vars: "roles/*/vars/*.yml" + - vars: "roles/*/defaults/*.yml" + - meta: "roles/*/meta/*.yml" + +# Logging +verbosity: 1 diff --git a/roles/openssh/.gitignore b/roles/openssh/.gitignore new file mode 100644 index 0000000..74b2f50 --- /dev/null +++ b/roles/openssh/.gitignore @@ -0,0 +1,40 @@ +# Ansible +*.retry +.ansible/ +ansible.log + +# Python +__pycache__/ +*.py[cod] +*.pyc + +# Testing +.tox/ +.pytest_cache/ +.cache +htmlcov/ +.ruff_cache/ +molecule/*/cache/ + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log + +# Temporary files +*.tmp +*.temp +*.bak +*.orig + +# Build artifacts +*.tar.gz diff --git a/roles/openssh/.yamllint b/roles/openssh/.yamllint new file mode 100644 index 0000000..c0ed5b0 --- /dev/null +++ b/roles/openssh/.yamllint @@ -0,0 +1,82 @@ +--- +# yamllint configuration +extends: default + +rules: + # Line length - balance readability with long Ansible constructs + line-length: + max: 160 + level: warning + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + + # Indentation - 2 spaces, strict + indentation: + spaces: 2 + indent-sequences: true + check-multi-line-strings: false + + # Comments - require spacing (ansible-lint compatible) + comments: + min-spaces-from-content: 1 # ansible-lint requires 1 + require-starting-space: true + ignore-shebangs: true + comments-indentation: false # ansible-lint requires false + + # Truthy values - only true/false allowed (not yes/no) + truthy: + allowed-values: ['true', 'false'] + check-keys: true + + # Octal values - ansible-lint compatible + octal-values: + forbid-implicit-octal: true # ansible-lint requires true + forbid-explicit-octal: true # ansible-lint requires true + + # Brackets - consistent spacing + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: 0 + max-spaces-inside-empty: 0 + + # Braces - consistent spacing + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + min-spaces-inside-empty: 0 + max-spaces-inside-empty: 0 + + # Document start - require --- + document-start: + present: true + + # Document end - not required + document-end: + present: false + + # Empty values - disallow + empty-values: + forbid-in-block-mappings: true + forbid-in-flow-mappings: true + + # Key duplicates - error + key-duplicates: + forbid-duplicated-merge-keys: true + + # New lines + new-line-at-end-of-file: enable + new-lines: + type: unix + + # Trailing spaces + trailing-spaces: enable + +# Ignore patterns +ignore: | + .cache/ + .tox/ + tests/output/ + collections/ + .github/ + molecule/default/molecule.yml diff --git a/roles/openssh/AGENTS.md b/roles/openssh/AGENTS.md new file mode 100644 index 0000000..8a49e70 --- /dev/null +++ b/roles/openssh/AGENTS.md @@ -0,0 +1,701 @@ +# Agent Instructions: OpenSSH Server Ansible Role + +This document provides guidance for AI agents (Claude, etc.) working on this OpenSSH server hardening Ansible role. It captures the principles, methodology, and quality standards established during the development of this project. + +## Project Overview + +This is a **security-first Ansible role** for hardening OpenSSH server configurations on Debian and Ubuntu systems. It provides: + +- **Comprehensive security hardening** with modern cryptography +- **16 compliance frameworks** (PCI DSS, HIPAA, FedRAMP, FISMA, SOC 2, GDPR, ISO 27001+) +- **20+ CVE mitigations** with distribution-specific patch tracking +- **10 supported distributions** (Debian 11-14, Ubuntu 22.04+, Rocky 8-10) +- **Version-aware capability detection** (13 feature flags) +- **Post-quantum cryptography** (ML-KEM) and FIDO2/WebAuthn support + +This is a **standalone, independent open source project** that can be composed into other infrastructure management systems. + +## Quick Reference for Agents + +**Before every task:** +- [ ] Read existing files before editing (`Read` before `Edit`/`Write`) +- [ ] Update docs/docs/CHANGELOG.md for ALL changes +- [ ] Run `yamllint .` and `ansible-lint --profile=production` + +**Key commands:** +- Validate YAML: `yamllint .` +- Validate Ansible: `ansible-lint --profile=production` +- Check CVE status: `curl -s https://security-tracker.debian.org/tracker/CVE-YYYY-XXXXX` + +**Never do:** +- ❌ Make security claims without verification +- ❌ Break backwards compatibility with Debian Stretch (OpenSSH 7.4p1) +- ❌ Use `yes`/`no` in YAML files (use `true`/`false`) +- ❌ Forget to update docs/CHANGELOG.md + +## Development Workflow + +### Local Testing Environment +- **Linting**: Use `yamllint .` for YAML validation +- **Best practices**: Use `ansible-lint --profile=production` (strict mode) +- **CVE verification**: Check distribution security trackers before claims +- **Documentation**: Build locally by editing markdown files + +### Pre-commit Validation +All changes must pass: +1. `yamllint .` - YAML syntax and style +2. `ansible-lint --profile=production` - Ansible best practices +3. Documentation links verified +4. docs/CHANGELOG.md updated + +### File Editing Pattern +```bash +# 1. Read first (REQUIRED) +Read templates/sshd_config.j2 + +# 2. Make changes with Edit tool +Edit templates/sshd_config.j2 + +# 3. Validate +yamllint . && ansible-lint --profile=production + +# 4. Update docs/CHANGELOG.md +Edit docs/CHANGELOG.md +``` + +## Tool Usage Priorities + +### Research and Verification +1. **WebFetch**: For official documentation (OpenSSH, NIST, BSI, ANSSI) +2. **WebSearch**: For finding authoritative sources +3. **Bash**: For CVE verification commands (`curl -s https://security-tracker.debian.org/...`) + +### File Operations +1. **Read**: ALWAYS read before editing (required by Edit tool) +2. **Edit**: For targeted changes to existing files +3. **Write**: Only for new files (not for modifying existing ones) +4. **Glob**: For finding files matching patterns + +### Code Quality +1. **Bash**: Run `yamllint .` and `ansible-lint --profile=production` +2. **Read**: Review validation output +3. **Edit**: Fix issues found by linters + +### Documentation Updates +Every code change requires updating: +1. docs/CHANGELOG.md (MANDATORY) +2. Relevant docs/ file (e.g., DISTRIBUTIONS.md, CVE-TRACKING.md) +3. README.md (if features/capabilities change) +4. examples/ (if usage patterns change) + +## Core Principles + +### 1. Security Through Research, Not Assumptions + +**CRITICAL**: Never make claims about security without verification. + +- **Always verify CVE patch status** using official security trackers: + - Debian: `https://security-tracker.debian.org/tracker/CVE-XXXX-XXXXX` + - Ubuntu: `https://ubuntu.com/security/CVE-XXXX-XXXXX` + +- **Understand vendor backports**: A distribution running OpenSSH 8.4p1 may be protected against vulnerabilities fixed in upstream 9.8p1 due to vendor security patches. NEVER assume vulnerability status based solely on version numbers. + +- **Research compliance frameworks thoroughly**: When asked about compliance (PCI DSS, HIPAA, FedRAMP, etc.), fetch official documentation and understand actual requirements, not generic security advice. + +- **Cite sources**: Every security claim should reference: + - Official OpenSSH security advisories + - CVE database entries + - Government/industry standards (NSA/CISA, BSI, ANSSI, etc.) + - Distribution security trackers + +**Example of correct approach**: +``` +❌ WRONG: "Debian Bookworm is vulnerable to CVE-2024-6387" +✅ RIGHT: "Debian Bookworm PATCHED CVE-2024-6387 via 1:9.2p1-2+deb12u3 + (verified at https://security-tracker.debian.org/tracker/CVE-2024-6387)" +``` + +### 2. Version-Aware Capability Detection + +This role supports 10 key distributions spanning OpenSSH versions 8.0p1 through 10.2p1+. **Never break older distributions** (even if not officially listed). + +**13 Capability Flags** (set in [tasks/main.yml](tasks/main.yml)): +- `openssh_has_disable_forwarding` (7.4+) +- `openssh_has_ca_signature_algorithms` (7.9+) +- `openssh_has_fido2` (8.2+) +- `openssh_has_include` (8.2+) +- `openssh_has_log_verbose` (8.5+) +- `openssh_has_required_rsa_size` (9.3+) +- `openssh_has_persourcepenalties` (9.8+) +- `openssh_has_mlkem` (9.9+) +- `openssh_has_rsa_sha2` (7.2+) +- `openssh_has_modern_kex` (7.4+) +- `openssh_blocks_dsa_ca` (7.9+) +- `openssh_removes_dsa` (9.6+) +- `openssh_dh_disabled_default` (10.0+) + +**Implementation pattern** in [templates/sshd_config.j2](templates/sshd_config.j2): +```jinja2 +{% if openssh_has_persourcepenalties | default(false) and openssh_enable_persourcepenalties %} +PerSourcePenalties yes +{% endif %} +``` + +**When adding new features**: +1. Check OpenSSH version requirement in release notes +2. Add capability flag to tasks/main.yml +3. Use conditional logic in templates/sshd_config.j2 +4. Test on both old (Debian Stretch 7.4p1) and new (Debian Forky 10.0p1) versions + +### 3. Compliance Framework Accuracy + +**16 frameworks supported**: PCI DSS 4.0, SOX, SAMA CSF, HIPAA, HITRUST CSF, GDPR, ISO 27017/27018/27037/27040/27701, FedRAMP, FISMA, NERC CIP, NCA ECC, UAE IA, SOC 2 + +**When working with compliance**: + +1. **Research the actual framework requirements**: + - PCI DSS 4.0: Multi-factor auth, 12+ char passwords, session timeout, audit logging + - FedRAMP: FIPS 140-2 compatible crypto, NIST 800-53 controls (AC-17, SC-8, SC-13) + - HIPAA: Encryption in transit (NIST SP 800-52), audit trails, addressable encryption + +2. **Document which role features satisfy requirements**: + - Map specific role variables to compliance controls + - Show configuration examples (see [examples/](examples/) directory) + - Note limitations (e.g., "FIPS 140-2 compatible algorithms, but full compliance requires OS-level FIPS mode") + +3. **Link to authoritative sources** in [docs/COMPLIANCE.md](docs/COMPLIANCE.md) + +### 4. Documentation Quality Standards + +**Documentation is split into focused topics**: +- `README.md` (~150 lines): Quick start, features, navigation +- `docs/DISTRIBUTIONS.md`: Distribution matrix and capability flags +- `docs/COMPLIANCE.md`: All 16 frameworks with requirements mapping +- `docs/CVE-TRACKING.md`: Vulnerability status by distribution +- `docs/CONFIGURATION.md`: Complete variable reference +- `docs/EXAMPLES.md`: Configuration examples +- `docs/TROUBLESHOOTING.md`: Common issues + +**Quality standards**: + +1. **Use tables for structured data**: Distribution matrices, CVE status, compliance mappings +2. **Provide specific package versions**: "Debian Bookworm 1:9.2p1-2+deb12u3" not "Debian Bookworm is patched" +3. **Include verification commands**: Show users how to check their status +4. **Link between documents**: Cross-reference related topics +5. **Keep README concise**: Link to detailed docs rather than embedding everything + +**Bad example**: +```markdown +## Supported Distributions +Debian and Ubuntu are supported. +``` + +**Good example**: +```markdown +## Supported Distributions + +| Distribution | OpenSSH Version | Feature Level | Security Status | +|--------------|-----------------|---------------|-----------------| +| Debian Bookworm | 9.2p1 | ✅ Modern | PATCHED for CVE-2024-6387 via 1:9.2p1-2+deb12u3 | +``` + +### 5. Testing and Validation + +**ALWAYS run validation** before claiming work is complete: + +```bash +# YAML syntax +yamllint . + +# Ansible best practices (production profile is strict) +ansible-lint --profile=production + +# All must pass with 0 failures, 0 warnings +``` + +**Common validation failures**: + +1. **Truthy values**: Use `true`/`false` not `yes`/`no` in YAML, convert in templates + ```yaml + # defaults/main.yml + openssh_verify_host_key_dns: false # boolean + + # templates/sshd_config.j2 + VerifyHostKeyDNS {{ 'yes' if openssh_verify_host_key_dns else 'no' }} + ``` + +2. **Galaxy role naming**: Must include `namespace` in meta/main.yml + ```yaml + galaxy_info: + role_name: openssh_server + namespace: agh # REQUIRED + ``` + +3. **Line length**: Keep YAML lines under 160 characters (yamllint rule) + +### 6. Cryptographic Preferences + +**Algorithm priority order** (Mozilla Modern + OpenSSH 10.0): + +1. **Ciphers** (AEAD preferred): + - `chacha20-poly1305@openssh.com` (highest priority) + - `aes256-gcm@openssh.com`, `aes128-gcm@openssh.com` (AEAD) + - `aes256-ctr`, `aes192-ctr`, `aes128-ctr` (fallback for ANSSI/BSI) + +2. **Key Exchange**: + - `mlkem768x25519-sha256` (post-quantum, 9.9+ only) + - `curve25519-sha256` (preferred) + - `ecdh-sha2-nistp521/384/256` (NIST curves) + - `diffie-hellman-group16-sha512`, `diffie-hellman-group18-sha512` (4096-bit DH) + +3. **MACs**: + - `hmac-sha2-512-etm@openssh.com` (ETM preferred) + - `hmac-sha2-256-etm@openssh.com` + - `umac-128-etm@openssh.com` + +**When researching crypto updates**: +- Check OpenSSH release notes (https://www.openssh.com/releasenotes.html) +- Review Mozilla OpenSSH guidelines (https://infosec.mozilla.org/guidelines/openssh) +- Check international guidance (BSI TR-02102-4, ANSSI NT_OpenSSH) +- Understand algorithm lifecycle (deprecated → removed → blocked) + +### 7. CVE Tracking Methodology + +**When a new CVE is discovered**: + +1. **Research official sources**: + - OpenSSH security page: https://www.openssh.com/security.html + - NVD/CVE database entry + - Vendor security advisories (Qualys, etc.) + +2. **Check distribution patch status**: + ```bash + # Debian + curl -s https://security-tracker.debian.org/tracker/CVE-YYYY-XXXXX + + # Ubuntu + curl -s https://ubuntu.com/security/CVE-YYYY-XXXXX + ``` + +3. **Update docs/CVE-TRACKING.md** with: + - CVE number, CVSS score, description + - Upstream affected versions + - Upstream fixed version + - Distribution-specific patch status with package versions + - Mitigation status (Fully Mitigated / Conditionally Mitigated / Open) + - Configuration-based mitigations if any + +4. **Update role if needed**: + - Add/update role variables for mitigation + - Add capability flags if version-specific + - Update defaults for secure-by-default + +### 8. International Research Standards + +**When asked about international security guidance**: + +1. **Five Eyes alliance** (English-speaking): + - 🇺🇸 NSA/CISA (https://www.nsa.gov/, https://www.cisa.gov/) + - 🇨🇦 CCCS (https://www.cyber.gc.ca/) + - 🇦🇺 ACSC (https://www.cyber.gov.au/) + - 🇬🇧 NCSC (https://www.ncsc.gov.uk/) + - 🇳🇿 GCSB/NZISM (https://www.gcsb.govt.nz/) + +2. **European standards**: + - 🇩🇪 BSI (https://www.bsi.bund.de/) - TR-02102-4 is most comprehensive + - 🇫🇷 ANSSI (https://cyber.gouv.fr/) - NT_OpenSSH + - 🇪🇺 ENISA (defers to member states) + +3. **Middle East**: + - 🇸🇦 NCA ECC (Saudi Arabia National Cybersecurity Authority) + - 🇦🇪 UAE IA (UAE Information Assurance) + +**Research approach**: +- Use WebFetch to get actual framework documents +- Look for version-dated guidance (e.g., "BSI TR-02102-4 Version 2025-1") +- Check for post-quantum cryptography roadmaps +- Identify algorithm preferences and minimum key sizes + +### 9. Error Correction and Fact-Checking + +**CRITICAL LESSON**: During this project, we initially made incorrect claims about CVE-2024-6387 vulnerability status. + +**Original incorrect claims**: +- ❌ Debian Bookworm vulnerable (WRONG - patched via backport) +- ❌ Ubuntu 22.04 Jammy vulnerable (WRONG - patched via backport) +- ❌ Ubuntu 20.04 Focal vulnerable (WRONG - not affected, version 8.2p1 predates vulnerable code) + +**What we learned**: +1. **Always verify against official trackers** before making vulnerability claims +2. **Understand vendor backports** - don't trust version numbers alone +3. **When user questions accuracy, investigate thoroughly** - they may be right +4. **Update documentation when errors discovered** - accuracy > ego + +**If you discover an error**: +1. Acknowledge it immediately +2. Research the correct information using official sources +3. Update ALL affected documentation +4. Explain what was wrong and why to help user understand + +### 10. Change Management + +**CRITICAL: docs/CHANGELOG.md is the source of truth for all changes to this project.** + +**Before making ANY changes**: + +1. **Read existing files first**: Use Read tool before Edit/Write +2. **Understand the context**: Check related files (defaults, tasks, templates, meta) +3. **Maintain backwards compatibility**: Test that changes work on Debian Stretch 7.4p1 +4. **Update docs/CHANGELOG.md**: Document what changed and why (see below) +5. **Run validation**: yamllint + ansible-lint must pass + +### 11. Commit Message Standards + +**Format**: Follow [Conventional Commits](https://www.conventionalcommits.org/) style: + +``` +(): + + + +