feat: A2A auth — mutual TLS between fleet agents
All checks were successful
Lint / lint (pull_request) Successful in 8s
All checks were successful
Lint / lint (pull_request) Successful in 8s
Implements mTLS for securing agent-to-agent communication in the Hermes fleet. Fixes #806. Changes: - scripts/gen_fleet_ca.sh: generate a self-signed Fleet CA (4096-bit RSA, 10-year validity) that signs all agent certificates - scripts/gen_agent_cert.sh: generate per-agent certs (Timmy, Allegro, Ezra) signed by the fleet CA with SAN entries and clientAuth/serverAuth extended key usage - agent/mtls.py: new module providing: - build_server_ssl_context() — TLS_SERVER context with CERT_REQUIRED, enforces client cert against Fleet CA - build_client_ssl_context() — TLS_CLIENT context for outbound A2A calls - MTLSMiddleware — ASGI middleware that rejects unauthenticated requests to A2A routes (/.well-known/agent-card*, /api/agent-card, /a2a/) with HTTP 403 when mTLS is enabled - is_mtls_configured() — checks HERMES_MTLS_CERT/KEY/CA env vars - hermes_cli/web_server.py: wire MTLSMiddleware into the FastAPI app; pass SSL context to uvicorn when HERMES_MTLS_* env vars are set so the server runs TLS with mandatory client cert verification - ansible/roles/hermes_mtls/: Ansible role to distribute Fleet CA cert, agent cert, and agent key to fleet nodes; writes an env file with HERMES_MTLS_* vars and restarts the hermes-gateway service - ansible/fleet_mtls.yml: fleet-wide playbook referencing the role for Timmy, Allegro, and Ezra nodes - tests/test_mtls.py: 15 tests covering is_mtls_configured, SSL context creation with real cryptography-generated certs, and MTLSMiddleware (unauthorized agent rejected → 403, authorized agent accepted → 200) mTLS is opt-in: set HERMES_MTLS_CERT, HERMES_MTLS_KEY, and HERMES_MTLS_CA to enable. When unset, the server behaves exactly as before. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
# Outputs (default: ~/.hermes/pki/agents/<name>/):
|
||||
# <name>.key — agent private key (chmod 600, stays on the agent host)
|
||||
# <name>.crt — agent certificate (signed by the fleet CA)
|
||||
# <name>.csr — CSR (intermediate, safe to delete)
|
||||
#
|
||||
# Run gen_fleet_ca.sh first if you haven't already.
|
||||
# Refs #806
|
||||
@@ -19,9 +18,9 @@ set -euo pipefail
|
||||
CERT_DAYS=365 # 1 year; rotate annually
|
||||
KEY_BITS=2048
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
# Parse args
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
AGENT_NAME=""
|
||||
CA_DIR="${HOME}/.hermes/pki/ca"
|
||||
OUT_DIR=""
|
||||
@@ -50,9 +49,9 @@ fi
|
||||
|
||||
OUT_DIR="${OUT_DIR:-${HOME}/.hermes/pki/agents/${AGENT_NAME}}"
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
# Prereq check
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
if ! command -v openssl &>/dev/null; then
|
||||
echo "ERROR: openssl not found." >&2
|
||||
exit 1
|
||||
@@ -98,7 +97,7 @@ openssl req -new \
|
||||
|
||||
# Sign with fleet CA — include SAN so modern TLS stacks accept it
|
||||
EXT_CONF=$(mktemp)
|
||||
trap 'rm -f "$EXT_CONF"' EXIT
|
||||
trap 'rm -f "$EXT_CONF" "$AGENT_CSR"' EXIT
|
||||
|
||||
cat > "$EXT_CONF" <<EOF
|
||||
[v3_agent]
|
||||
|
||||
@@ -16,9 +16,9 @@ set -euo pipefail
|
||||
CA_SUBJECT="/CN=Hermes Fleet CA/O=Hermes/OU=Fleet"
|
||||
CA_DAYS=3650 # 10 years
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
# Parse args
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
OUT_DIR="${HOME}/.hermes/pki/ca"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@@ -35,9 +35,9 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
# Prereq check
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------
|
||||
if ! command -v openssl &>/dev/null; then
|
||||
echo "ERROR: openssl not found. Install OpenSSL and re-run." >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user