feat(ssh): add bootstrap-ssh-ca role for OpenBao SSH user CA trust
Deploy TrustedUserCAKeys, auth_principals from ssh_principals.yaml, and Makefile targets bootstrap-ssh-ca / bootstrap-ssh-ca-host (NET-WP-0020 T5).
This commit is contained in:
11
Makefile
11
Makefile
@@ -143,6 +143,17 @@ provision-custodian-agent-host: ## Deploy custodian agent key to one host: make
|
||||
cd ansible && ansible-playbook playbooks/custodian-agent.yaml -u $(SSH_USER) \
|
||||
--limit "$(HOST)"
|
||||
|
||||
bootstrap-ssh-ca: ## Deploy OpenBao SSH CA trust + auth_principals: make bootstrap-ssh-ca SSH_CA_PUBKEY=/path/to/ca_user.pub
|
||||
@test -n "$(SSH_CA_PUBKEY)" || (echo "Usage: make bootstrap-ssh-ca SSH_CA_PUBKEY=/path/to/ca_user.pub [HOST=Railiance01]"; exit 1)
|
||||
cd ansible && ansible-playbook playbooks/bootstrap-ssh-ca.yaml -u $(SSH_USER) \
|
||||
-e ssh_ca_pubkey_path="$(SSH_CA_PUBKEY)" \
|
||||
$(if $(HOST),--limit "$(HOST)",)
|
||||
|
||||
bootstrap-ssh-ca-host: ## Deploy SSH CA trust to one host: make bootstrap-ssh-ca-host HOST=Railiance01 SSH_CA_PUBKEY=...
|
||||
@test -n "$(HOST)" && test -n "$(SSH_CA_PUBKEY)" || \
|
||||
(echo "Usage: make bootstrap-ssh-ca-host HOST=Railiance01 SSH_CA_PUBKEY=/path/to/ca_user.pub"; exit 1)
|
||||
$(MAKE) bootstrap-ssh-ca SSH_CA_PUBKEY="$(SSH_CA_PUBKEY)" HOST="$(HOST)"
|
||||
|
||||
# ---- Orchestration ----
|
||||
apply: tf-fmt tf-apply ansible-bootstrap ## Provision via Terraform then converge via Ansible
|
||||
|
||||
|
||||
19
ansible/inventory/ssh_principals.yaml
Normal file
19
ansible/inventory/ssh_principals.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
# Central SSH certificate principals inventory — synced with ops-warden actor
|
||||
# principals (wiki/ActorInventoryPatterns.md). Public data only.
|
||||
|
||||
ssh_principals:
|
||||
CoulombCore:
|
||||
users:
|
||||
tegwick:
|
||||
- agt-task-bridge
|
||||
- agt-interhub-bootstrap
|
||||
- adm-full
|
||||
- atm-backup-daily
|
||||
|
||||
Railiance01:
|
||||
users:
|
||||
tegwick:
|
||||
- agt-task-bridge
|
||||
- agt-interhub-bootstrap
|
||||
- adm-full
|
||||
- atm-backup-daily
|
||||
19
ansible/playbooks/bootstrap-ssh-ca.yaml
Normal file
19
ansible/playbooks/bootstrap-ssh-ca.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
# Deploy OpenBao SSH user CA trust and per-user auth_principals.
|
||||
#
|
||||
# Prerequisite: railiance-platform openbao-configure-ssh (exports CA pubkey).
|
||||
#
|
||||
# cd ~/railiance-platform
|
||||
# OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token \
|
||||
# OPENBAO_SSH_CA_PUBKEY_OUT=/tmp/openbao-ssh-ca.pub \
|
||||
# make openbao-configure-ssh
|
||||
#
|
||||
# cd ~/railiance-infra
|
||||
# make bootstrap-ssh-ca SSH_CA_PUBKEY=/tmp/openbao-ssh-ca.pub
|
||||
|
||||
- hosts: all
|
||||
become: true
|
||||
vars_files:
|
||||
- ../inventory/ssh_principals.yaml
|
||||
roles:
|
||||
- role: ssh_ca_host
|
||||
5
ansible/roles/ssh_ca_host/handlers/main.yml
Normal file
5
ansible/roles/ssh_ca_host/handlers/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Restart sshd
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
85
ansible/roles/ssh_ca_host/tasks/main.yml
Normal file
85
ansible/roles/ssh_ca_host/tasks/main.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
- name: Require SSH CA public key path
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ssh_ca_pubkey_path is defined
|
||||
- ssh_ca_pubkey_path | length > 0
|
||||
fail_msg: >-
|
||||
Set ssh_ca_pubkey_path to the OpenBao SSH CA public key file
|
||||
(from railiance-platform openbao-configure-ssh).
|
||||
|
||||
- name: Stat SSH CA public key source
|
||||
ansible.builtin.stat:
|
||||
path: "{{ ssh_ca_pubkey_path }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
register: ssh_ca_pubkey_stat
|
||||
|
||||
- name: Fail when SSH CA public key is missing
|
||||
ansible.builtin.fail:
|
||||
msg: "SSH CA public key not found on controller: {{ ssh_ca_pubkey_path }}"
|
||||
when: not ssh_ca_pubkey_stat.stat.exists
|
||||
|
||||
- name: Ensure SSH CA directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/ssh/ca
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Install SSH user CA public key
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ssh_ca_pubkey_path }}"
|
||||
dest: /etc/ssh/ca/ca_user.pub
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart sshd
|
||||
|
||||
- name: Configure SSH certificate trust
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ssh/sshd_config.d/20-ssh-ca.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
TrustedUserCAKeys /etc/ssh/ca/ca_user.pub
|
||||
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
|
||||
notify: Restart sshd
|
||||
|
||||
- name: Ensure auth_principals directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/ssh/auth_principals
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Resolve principals for this host
|
||||
ansible.builtin.set_fact:
|
||||
ssh_ca_host_principals: >-
|
||||
{{
|
||||
(ssh_principals[inventory_hostname].users
|
||||
if ssh_principals is defined
|
||||
and inventory_hostname in ssh_principals
|
||||
else {})
|
||||
}}
|
||||
|
||||
- name: Deploy auth_principals files per user
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/ssh/auth_principals/{{ item.key }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: "{{ item.value | join('\n') }}\n"
|
||||
loop: "{{ ssh_ca_host_principals | dict2items }}"
|
||||
when: ssh_ca_host_principals | length > 0
|
||||
notify: Restart sshd
|
||||
|
||||
- name: Warn when no principals configured for host
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
No principals in ssh_principals.yaml for {{ inventory_hostname }} —
|
||||
CA trust installed; add users under hosts.<name>.users to enable cert login.
|
||||
when: ssh_ca_host_principals | length == 0
|
||||
Reference in New Issue
Block a user