diff --git a/inventories/production/group_vars/control/vars.yml b/inventories/production/group_vars/control/vars.yml index b4e64ee..6f06074 100644 --- a/inventories/production/group_vars/control/vars.yml +++ b/inventories/production/group_vars/control/vars.yml @@ -12,6 +12,9 @@ dev_env__users: # group only. ansible_user: sjat +# ubongo's AI-worker; passwordless sudo for the claude user (ADR-015 amended). +base__ai_worker_user: claude + # ubongo is a NetBird mesh peer (ADR-016, M5) — enrol the agent via base's `mesh` concern. # Enrollment only; the host firewall default-deny stays deferred (the mesh-hardening # follow-on), so this brings up wt0 without changing SSH exposure. diff --git a/roles/base/defaults/main.yml b/roles/base/defaults/main.yml index 6073a1a..301dee7 100644 --- a/roles/base/defaults/main.yml +++ b/roles/base/defaults/main.yml @@ -29,6 +29,11 @@ base__ssh_authorised_keys: [] base__ssh_listen_mesh_only: false base__ssh_listen_addr: "" +# The automation/AI-worker user granted passwordless sudo (ADR-015 amended / ADR-021). +# Empty = no AI-worker sudo. Set per-group (e.g. group_vars/control: claude). The user's +# password should be locked so NOPASSWD is its only sudo path; actions are auditd-attributed. +base__ai_worker_user: "" + # NetBird mesh agent enrollment (ADR-016). Opt-in: default off so applying `base` to a # host not on the mesh is a no-op for this concern. The live actions (apt install over # the network, `netbird up` against the coordinator) are additionally gated by diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index b022586..b40e305 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -23,6 +23,13 @@ tags: [hardening] tags: [hardening] +- name: AI-worker operational access (sudoers drop-in) + ansible.builtin.include_tasks: + file: operational_access.yml + apply: + tags: [users] + tags: [users] + - name: NetBird mesh enrollment ansible.builtin.include_tasks: file: mesh.yml diff --git a/roles/base/tasks/operational_access.yml b/roles/base/tasks/operational_access.yml new file mode 100644 index 0000000..3a27a18 --- /dev/null +++ b/roles/base/tasks/operational_access.yml @@ -0,0 +1,11 @@ +--- +- name: Grant the AI-worker user passwordless sudo (ADR-015 amended / ADR-021) + ansible.builtin.copy: + content: "{{ base__ai_worker_user }} ALL=(ALL) NOPASSWD:ALL\n" + dest: "/etc/sudoers.d/{{ base__ai_worker_user }}-ai-worker" + owner: root + group: root + mode: "0440" + validate: "visudo -cf %s" + when: base__ai_worker_user | length > 0 + tags: [users]