All checks were successful
Lint / lint (pull_request) Successful in 10s
Implements mutual TLS for secure agent-to-agent communication (#806). - scripts/gen_fleet_ca.sh: generate fleet CA (4096-bit RSA, 10-year) - scripts/gen_agent_cert.sh: per-agent cert signed by fleet CA (timmy, allegro, ezra) - agent/a2a_mtls.py: A2AServer requiring client cert verification (CERT_REQUIRED), build_server_ssl_context / build_client_ssl_context helpers, server_from_env() - ansible/roles/fleet_mtls_certs/: distribute CA + per-agent certs to fleet nodes, write /etc/hermes/a2a.env, notify hermes-a2a service on change - ansible/fleet_mtls.yml + ansible/inventory/fleet.ini.example: playbook + example inventory - tests/agent/test_a2a_mtls.py: 11 tests — authorized agent accepted (200/202), self-signed cert rejected, no-cert rejected, lifecycle, env-var wiring Fixes #806 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
3.3 KiB
YAML
100 lines
3.3 KiB
YAML
---
|
|
# fleet_mtls_certs/tasks/main.yml
|
|
#
|
|
# Distribute the fleet CA certificate and the per-agent TLS cert+key to
|
|
# each fleet node. Triggers a hermes-a2a service restart when any cert
|
|
# changes.
|
|
#
|
|
# Refs #806 — A2A mutual TLS between fleet agents.
|
|
|
|
- name: Verify agent cert source files exist on control node
|
|
ansible.builtin.stat:
|
|
path: "{{ item }}"
|
|
register: _src_stat
|
|
delegate_to: localhost
|
|
loop:
|
|
- "{{ fleet_mtls_ca_cert_src }}"
|
|
- "{{ fleet_mtls_agent_certs_dir }}/{{ fleet_mtls_agent_name }}/{{ fleet_mtls_agent_name }}.crt"
|
|
- "{{ fleet_mtls_agent_certs_dir }}/{{ fleet_mtls_agent_name }}/{{ fleet_mtls_agent_name }}.key"
|
|
loop_control:
|
|
label: "{{ item | basename }}"
|
|
|
|
- name: Fail if any source cert is missing
|
|
ansible.builtin.fail:
|
|
msg: >
|
|
Required cert file not found: {{ item.item }}
|
|
Run scripts/gen_fleet_ca.sh and scripts/gen_agent_cert.sh --agent {{ fleet_mtls_agent_name }} first.
|
|
when: not item.stat.exists
|
|
loop: "{{ _src_stat.results }}"
|
|
loop_control:
|
|
label: "{{ item.item | basename }}"
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Remote directory structure
|
|
# -----------------------------------------------------------------------
|
|
|
|
- name: Create remote PKI directories
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0750"
|
|
loop:
|
|
- "{{ fleet_mtls_remote_pki_dir }}"
|
|
- "{{ fleet_mtls_remote_ca_dir }}"
|
|
- "{{ fleet_mtls_remote_agent_dir }}"
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Fleet CA certificate (public — read-only for all)
|
|
# -----------------------------------------------------------------------
|
|
|
|
- name: Deploy fleet CA certificate
|
|
ansible.builtin.copy:
|
|
src: "{{ fleet_mtls_ca_cert_src }}"
|
|
dest: "{{ fleet_mtls_remote_ca_dir }}/fleet-ca.crt"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
notify: Restart hermes-a2a
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Per-agent certificate (public portion)
|
|
# -----------------------------------------------------------------------
|
|
|
|
- name: Deploy agent certificate
|
|
ansible.builtin.copy:
|
|
src: "{{ fleet_mtls_agent_certs_dir }}/{{ fleet_mtls_agent_name }}/{{ fleet_mtls_agent_name }}.crt"
|
|
dest: "{{ fleet_mtls_remote_agent_dir }}/agent.crt"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
notify: Restart hermes-a2a
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Per-agent private key (secret — root-only read)
|
|
# -----------------------------------------------------------------------
|
|
|
|
- name: Deploy agent private key
|
|
ansible.builtin.copy:
|
|
src: "{{ fleet_mtls_agent_certs_dir }}/{{ fleet_mtls_agent_name }}/{{ fleet_mtls_agent_name }}.key"
|
|
dest: "{{ fleet_mtls_remote_agent_dir }}/agent.key"
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
no_log: true # suppress file content from Ansible output
|
|
notify: Restart hermes-a2a
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Environment file for hermes-a2a systemd unit
|
|
# -----------------------------------------------------------------------
|
|
|
|
- name: Write hermes-a2a environment file
|
|
ansible.builtin.template:
|
|
src: hermes_a2a_env.j2
|
|
dest: /etc/hermes/a2a.env
|
|
owner: root
|
|
group: root
|
|
mode: "0640"
|
|
notify: Restart hermes-a2a
|