diff --git a/.ansible-lint b/.ansible-lint index 50c7005..3e834ba 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -21,6 +21,6 @@ exclude_paths: - .markdownlint.yaml - examples/roles/ mock_roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client supported_ansible_also: - "2.14.0" diff --git a/.github/workflows/tft.yml b/.github/workflows/tft.yml index 8d1ff5e..7e0e7d4 100644 --- a/.github/workflows/tft.yml +++ b/.github/workflows/tft.yml @@ -181,7 +181,7 @@ jobs: tf_scope: private api_key: ${{ secrets.TF_API_KEY_RH }} update_pull_request_status: false - tmt_plan_filter: "tag:playbooks_parallel,trustee_attestation_client" + tmt_plan_filter: "tag:playbooks_parallel,trustee_client" - name: Set final commit status uses: myrotvorets/set-commit-status-action@master diff --git a/.gitignore b/.gitignore index 10cccca..d2cdca3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ vault.yml *.pyc *.retry /tests/.coverage +/tests/kbs_test_cert.crt /tests/htmlcov* /.tox /venv*/ diff --git a/README.md b/README.md index 7c50785..f01c086 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# trustee_attestation_client +# trustee_client -[![ansible-lint.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/ansible-lint.yml) [![ansible-test.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/ansible-test.yml) [![codespell.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/codespell.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/codespell.yml) [![markdownlint.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/markdownlint.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/markdownlint.yml) [![qemu-kvm-integration-tests.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/qemu-kvm-integration-tests.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/qemu-kvm-integration-tests.yml) [![shellcheck.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/shellcheck.yml) [![tft.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/tft.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/tft.yml) [![tft_citest_bad.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/tft_citest_bad.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/tft_citest_bad.yml) [![woke.yml](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/woke.yml/badge.svg)](https://github.com/linux-system-roles/trustee_attestation_client/actions/workflows/woke.yml) +[![ansible-lint.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/ansible-lint.yml) [![ansible-test.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/ansible-test.yml) [![codespell.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/codespell.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/codespell.yml) [![markdownlint.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/markdownlint.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/markdownlint.yml) [![qemu-kvm-integration-tests.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/qemu-kvm-integration-tests.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/qemu-kvm-integration-tests.yml) [![shellcheck.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/shellcheck.yml) [![tft.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/tft.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/tft.yml) [![tft_citest_bad.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/tft_citest_bad.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/tft_citest_bad.yml) [![woke.yml](https://github.com/linux-system-roles/trustee_client/actions/workflows/woke.yml/badge.svg)](https://github.com/linux-system-roles/trustee_client/actions/workflows/woke.yml) -![trustee_attestation_client](https://github.com/linux-system-roles/trustee_attestation_client/workflows/tox/badge.svg) +![trustee_client](https://github.com/linux-system-roles/trustee_client/workflows/tox/badge.svg) Ansible role for deploying Trustee Guest Components using Podman Quadlets for confidential virtual machine deployments. The role downloads quadlet files and @@ -20,13 +20,10 @@ storage devices. Example of setting the variables: ```yaml -trustee_attestation_client_quadlet_repo_url: "https://github.com/litian1992/trustee-gc-quadlet-rhel" -trustee_attestation_client_quadlet_repo_path: "quadlet" -trustee_attestation_client_quadlet_repo_branch: "main" -trustee_attestation_client_kbs_url: "https://kbs.example.com" -trustee_attestation_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" -trustee_attestation_client_secret_registration_enabled: true -trustee_attestation_client_encrypt_disk: true +trustee_client_kbs_url: "https://kbs.example.com" +trustee_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" # or trustee_client_kbs_cert_src: "/path/to/server.crt" +trustee_client_secret_registration_enabled: true +trustee_client_encrypt_disk: true ``` ## Example Playbook @@ -38,15 +35,12 @@ passed in as parameters) is always nice for users too: - name: Deploy Trustee Guest Components using Podman Quadlets hosts: all vars: - trustee_attestation_client_quadlet_repo_url: "https://github.com/litian1992/trustee-gc-quadlet-rhel" - trustee_attestation_client_quadlet_repo_path: "quadlet" - trustee_attestation_client_quadlet_repo_branch: "main" - trustee_attestation_client_kbs_url: "https://kbs.example.com" - trustee_attestation_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" - trustee_attestation_client_secret_registration_enabled: true - trustee_attestation_client_encrypt_disk: true + trustee_client_kbs_url: "https://kbs.example.com" + trustee_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" + trustee_client_secret_registration_enabled: true + trustee_client_encrypt_disk: true roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client ``` ## Trustee Client @@ -66,11 +60,14 @@ When enabled, this task: ## Encrypt Disk -When enabled, this task: +An unpartitioned empty disk must be attached to the target. When enabled, this task: 1. Finds the first unpartitioned and unmounted disk -2. Requests disk encryption key from Secret Registration Client -3. Encrypts the disk using above encryption key and mounts it at the designated path +2. Encrypts the disk using a key from either: + a. secret key fetched using Secret Registration Client (when enabled), or + b. `systemd-cryptenroll` which binds to PCR 7 +3. Mounts it at the designated path +4. Sets up automatic unlock and mount either with Secret Registration Client service or /etc/crypttab with `systemd-cryptenroll` ## License diff --git a/contributing.md b/contributing.md index 7071d9b..2bf49c9 100644 --- a/contributing.md +++ b/contributing.md @@ -1,4 +1,4 @@ -# Contributing to the trustee_attestation_client Linux System Role +# Contributing to the trustee_client Linux System Role ## Where to start @@ -12,12 +12,12 @@ This has all of the common information that all role developers need: * How to create git commits and submit pull requests **Bugs and needed implementations** are listed on -[Github Issues](https://github.com/linux-system-roles/trustee_attestation_client/issues). +[Github Issues](https://github.com/linux-system-roles/trustee_client/issues). Issues labeled with -[**help wanted**](https://github.com/linux-system-roles/trustee_attestation_client/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) +[**help wanted**](https://github.com/linux-system-roles/trustee_client/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) are likely to be suitable for new contributors! -**Code** is managed on [Github](https://github.com/linux-system-roles/trustee_attestation_client), using +**Code** is managed on [Github](https://github.com/linux-system-roles/trustee_client), using [Pull Requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests). ## Running CI Tests Locally diff --git a/defaults/main.yml b/defaults/main.yml index 194ab71..caa2b06 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -3,20 +3,17 @@ # Here is the right place to put the role's input variables. # This file also serves as a documentation for such a variables. -# Trustee Guest Components Quadlet repository configuration -trustee_attestation_client_trustee_gc: true -trustee_attestation_client_quadlet_repo_url: "https://github.com/litian1992/trustee-gc-quadlet-rhel" -trustee_attestation_client_quadlet_repo_path: "quadlet" -trustee_attestation_client_quadlet_repo_branch: "main" -trustee_attestation_client_quadlet_install_dir: "/etc/containers/systemd" +# Trustee Guest Components Quadlet (see vars/main.yml for quadlet repo defaults) +trustee_client_trustee_gc: true # Trustee KBS configuration -trustee_attestation_client_kbs_url: "" -trustee_attestation_client_kbs_cert_content: "" +trustee_client_kbs_url: "" +trustee_client_kbs_cert_content: "" +trustee_client_kbs_cert_src: "" # Path to cert file (alternative to trustee_client_kbs_cert_content) # Secret registration client configuration -trustee_attestation_client_secret_registration_enabled: false +trustee_client_secret_registration_enabled: false # Encrypt disk configuration -trustee_attestation_client_encrypt_disk: false -trustee_attestation_client_encrypt_disk_mount_point: "/mnt/encrypted-disk" +trustee_client_encrypt_disk: false +trustee_client_encrypt_disk_mount_point: "/mnt/encrypted-disk" diff --git a/examples/simple.yml b/examples/simple.yml index e86cb76..f562585 100644 --- a/examples/simple.yml +++ b/examples/simple.yml @@ -3,13 +3,11 @@ - name: Deploy Trustee Guest Components using Podman Quadlets from GitHub repository hosts: all vars: - trustee_attestation_client_quadlet_repo_url: "https://github.com/litian1992/trustee-gc-quadlet-rhel" - trustee_attestation_client_quadlet_repo_path: "quadlet" - trustee_attestation_client_quadlet_repo_branch: "main" - trustee_attestation_client_quadlet_install_dir: "/etc/containers/systemd" - trustee_attestation_client_encrypt_disk: false - trustee_attestation_client_kbs_url: "https://kbs.example.com" - trustee_attestation_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" - trustee_attestation_client_secret_registration_enabled: false + trustee_client_encrypt_disk: false + trustee_client_kbs_url: "https://kbs.example.com" + # Use either cert content or path to cert file: + trustee_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" + # trustee_client_kbs_cert_src: "/path/to/server.crt" + trustee_client_secret_registration_enabled: false roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client diff --git a/handlers/main.yml b/handlers/main.yml index 17b37ac..f7ef67f 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -10,5 +10,5 @@ name: "{{ item }}" enabled: true state: restarted - loop: "{{ __trustee_attestation_client_services | default([]) }}" + loop: "{{ __trustee_client_services | default([]) }}" listen: "restart trustee services" diff --git a/plans/README-plans.md b/plans/README-plans.md index acd9488..d51226c 100644 --- a/plans/README-plans.md +++ b/plans/README-plans.md @@ -1,6 +1,6 @@ # Introduction CI Testing Plans -Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/trustee_attestation_client/blob/main/.github/workflows/tft.yml) GitHub workflow. +Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/trustee_client/blob/main/.github/workflows/tft.yml) GitHub workflow. The `plans/test_playbooks_parallel.fmf` plan is a test plan that runs test playbooks in parallel on multiple managed nodes. `plans/test_playbooks_parallel.fmf` is generated centrally from `https://github.com/linux-system-roles/.github/`. @@ -16,7 +16,7 @@ The `plans/test_playbooks_parallel.fmf` plan does the following steps: 2. Does the required preparation on systems. 3. For the given role and the given PR, runs the general test from [test.sh](https://github.com/linux-system-roles/tft-tests/blob/main/tests/general/test.sh). -The [tft.yml](https://github.com/linux-system-roles/trustee_attestation_client/blob/main/.github/workflows/tft.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access. +The [tft.yml](https://github.com/linux-system-roles/trustee_client/blob/main/.github/workflows/tft.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access. This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm). ## Running Tests @@ -47,7 +47,7 @@ You can run tests locally with the `tmt try` cli or remotely in Testing Farm. $ TESTING_FARM_API_TOKEN= \ testing-farm request --pipeline-type="tmt-multihost" \ --plan-filter="tag:playbooks_parallel" \ - --git-url "https://github.com//trustee_attestation_client" \ + --git-url "https://github.com//trustee_client" \ --git-ref "" \ --compose CentOS-Stream-9 \ -e "SYSTEM_ROLES_ONLY_TESTS=tests_default.yml" \ diff --git a/plans/test_playbooks_parallel.fmf b/plans/test_playbooks_parallel.fmf index 7d886c1..8fe1317 100644 --- a/plans/test_playbooks_parallel.fmf +++ b/plans/test_playbooks_parallel.fmf @@ -12,7 +12,7 @@ provision: environment: # ensure versions are strings! SR_ANSIBLE_VER: "2.17" - SR_REPO_NAME: trustee_attestation_client + SR_REPO_NAME: trustee_client SR_PYTHON_VERSION: "3.12" SR_ONLY_TESTS: "" # tests_default.yml SR_TEST_LOCAL_CHANGES: true diff --git a/tasks/encrypt_disk.yml b/tasks/encrypt_disk.yml index 9430e56..db193c9 100644 --- a/tasks/encrypt_disk.yml +++ b/tasks/encrypt_disk.yml @@ -15,50 +15,108 @@ } } ' - register: __trustee_attestation_client_unpartitioned_disk + register: __trustee_client_unpartitioned_disk changed_when: false failed_when: false - name: Encrypt disk - when: __trustee_attestation_client_unpartitioned_disk.stdout != "" + when: __trustee_client_unpartitioned_disk.stdout != "" vars: - __trustee_attestation_client_disk_device: "/dev/{{ __trustee_attestation_client_unpartitioned_disk.stdout }}" - __trustee_attestation_client_disk_partition: >- - /dev/{{ __trustee_attestation_client_unpartitioned_disk.stdout }}{{ 'p' if 'nvme' in __trustee_attestation_client_unpartitioned_disk.stdout else '' }}1 + __trustee_client_disk_device: "/dev/{{ __trustee_client_unpartitioned_disk.stdout }}" + __trustee_client_disk_partition: >- + /dev/{{ __trustee_client_unpartitioned_disk.stdout }}{{ 'p' if 'nvme' in __trustee_client_unpartitioned_disk.stdout else '' }}1 block: - name: Ensure packages for disk encryption are installed ansible.builtin.package: - name: "{{ __trustee_attestation_client_encrypt_disk_packages }}" + name: "{{ __trustee_client_encrypt_disk_packages }}" state: present - use: "{{ (__trustee_attestation_client_is_ostree | d(false)) | + use: "{{ (__trustee_client_is_ostree | d(false)) | ternary('ansible.posix.rhel_rpm_ostree', omit) }}" - name: Create temporary file for disk encryption key ansible.builtin.tempfile: state: file suffix: .bin - register: __trustee_attestation_client_secret_key_tempfile + register: __trustee_client_secret_key_tempfile - name: Acquire disk encryption key from Secret Registration Client service ansible.builtin.shell: | - /usr/local/bin/secret_registration_client.sh --fetch-key-to {{ __trustee_attestation_client_secret_key_tempfile.path }} + /usr/local/bin/secret_registration_client.sh --fetch-key-to {{ __trustee_client_secret_key_tempfile.path }} changed_when: true + when: trustee_client_secret_registration_enabled | bool + no_log: true + + - name: Check systemd-cryptenroll command exists + ansible.builtin.command: command -v systemd-cryptenroll + register: __trustee_client_cryptenroll_check + changed_when: false + when: not trustee_client_secret_registration_enabled | bool + + - name: Create a random disk encryption key + ansible.builtin.shell: | + set -o pipefail + head -c 32 /dev/urandom | base64 > {{ __trustee_client_secret_key_tempfile.path }} + changed_when: true + when: + - __trustee_client_cryptenroll_check is success + - not trustee_client_secret_registration_enabled | bool no_log: true - name: Encrypt the partition ansible.builtin.shell: | set -o pipefail - parted -s {{ __trustee_attestation_client_disk_device }} mklabel gpt - parted -s {{ __trustee_attestation_client_disk_device }} mkpart primary ext4 0% 100% - cryptsetup luksFormat --key-file {{ __trustee_attestation_client_secret_key_tempfile.path }} --batch-mode {{ __trustee_attestation_client_disk_partition }} - cryptsetup open --key-file {{ __trustee_attestation_client_secret_key_tempfile.path }} {{ __trustee_attestation_client_disk_partition }} encrypted-disk - mkfs.ext4 /dev/mapper/encrypted-disk - [ -d {{ trustee_attestation_client_encrypt_disk_mount_point }} ] || mkdir -p {{ trustee_attestation_client_encrypt_disk_mount_point }} - mount /dev/mapper/encrypted-disk {{ trustee_attestation_client_encrypt_disk_mount_point }} + parted -s {{ __trustee_client_disk_device }} mklabel gpt + parted -s {{ __trustee_client_disk_device }} mkpart primary ext4 0% 100% + cryptsetup luksFormat --key-file {{ __trustee_client_secret_key_tempfile.path }} --batch-mode {{ __trustee_client_disk_partition }} + cryptsetup open --key-file {{ __trustee_client_secret_key_tempfile.path }} {{ __trustee_client_disk_partition }} trustee_client_encrypted_disk_0 + mkfs.ext4 /dev/mapper/trustee_client_encrypted_disk_0 + [ -d {{ trustee_client_encrypt_disk_mount_point }} ] || mkdir -p {{ trustee_client_encrypt_disk_mount_point }} + mount /dev/mapper/trustee_client_encrypted_disk_0 {{ trustee_client_encrypt_disk_mount_point }} changed_when: true no_log: true + - name: TPM2 cryptenroll and configure crypttab/fstab + when: + - __trustee_client_cryptenroll_check is success + - not trustee_client_secret_registration_enabled | bool + block: + - name: Bind TPM2 slot to LUKS volume + ansible.builtin.shell: | + systemd-cryptenroll {{ __trustee_client_disk_partition }} --tpm2-device=auto --tpm2-pcrs=7 --unlock-key-file={{ __trustee_client_secret_key_tempfile.path }} + systemd-cryptenroll {{ __trustee_client_disk_partition }} --wipe-slot=password + changed_when: true + no_log: true + + - name: Get UUID of the LUKS partition + ansible.builtin.command: "lsblk -dno UUID {{ __trustee_client_disk_partition }}" + register: __luks_uuid + changed_when: false + + - name: Retrieve facts for the /etc/crypttab file + stat: + path: /etc/crypttab + register: __trustee_client_crypttab + changed_when: false + + - name: Configure /etc/crypttab for TPM auto-unlock + ansible.builtin.lineinfile: + path: /etc/crypttab + line: "trustee_client_encrypted_disk_0 UUID={{ __luks_uuid.stdout }} none tpm2-device=auto" + regexp: '^trustee_client_encrypted_disk_0\s+' + create: true + mode: "{{ __trustee_client_crypttab.stat.mode | d('0600') }}" + owner: "{{ __trustee_client_crypttab.stat.pw_name | d('root') }}" + group: "{{ __trustee_client_crypttab.stat.gr_name | d('root') }}" + + - name: Configure /etc/fstab and mount volume + ansible.posix.mount: + path: "{{ trustee_client_encrypt_disk_mount_point }}" + src: /dev/mapper/trustee_client_encrypted_disk_0 + fstype: ext4 + opts: defaults,x-systemd.requires=systemd-cryptsetup@trustee_client_encrypted_disk_0.service + state: mounted + - name: Clean up disk encryption key file ansible.builtin.file: - path: "{{ __trustee_attestation_client_secret_key_tempfile.path }}" + path: "{{ __trustee_client_secret_key_tempfile.path }}" state: absent diff --git a/tasks/main.yml b/tasks/main.yml index bf7a28f..258f784 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -5,19 +5,18 @@ - name: Deploy Trustee Guest Components using Podman Quadlets include_tasks: trustee_quadlet.yml - when: trustee_attestation_client_trustee_gc | bool + when: trustee_client_trustee_gc | bool - name: Deploy Secret Registration Client Service include_tasks: secret_registration_client.yml when: - - trustee_attestation_client_secret_registration_enabled | bool - - trustee_attestation_client_trustee_gc | bool + - trustee_client_secret_registration_enabled | bool + - trustee_client_trustee_gc | bool - name: Create encrypted disk partition include_tasks: encrypt_disk.yml when: - - trustee_attestation_client_encrypt_disk | bool - - trustee_attestation_client_secret_registration_enabled | bool + - trustee_client_encrypt_disk | bool - name: Flush handlers to ensure services are started ansible.builtin.meta: flush_handlers diff --git a/tasks/secret_registration_client.yml b/tasks/secret_registration_client.yml index b2cd880..3ed4cc9 100644 --- a/tasks/secret_registration_client.yml +++ b/tasks/secret_registration_client.yml @@ -2,13 +2,13 @@ --- # Secret registration client: registers with server using attestation, # fetches disk encryption key from Trustee KBS. -# Requires Trustee GC (trustee_attestation_client_trustee_gc). +# Requires Trustee GC (trustee_client_trustee_gc). - name: Ensure secret registration client dependencies are installed ansible.builtin.package: - name: "{{ __trustee_attestation_client_secret_registration_client_packages }}" + name: "{{ __trustee_client_secret_registration_client_packages }}" state: present - use: "{{ (__trustee_attestation_client_is_ostree | d(false)) | + use: "{{ (__trustee_client_is_ostree | d(false)) | ternary('ansible.posix.rhel_rpm_ostree', omit) }}" - name: Deploy secret registration client script @@ -16,17 +16,17 @@ src: secret_registration_client.sh.j2 dest: "/usr/local/bin/secret_registration_client.sh" mode: "0755" - register: __trustee_attestation_client_reg_script + register: __trustee_client_reg_script - name: Deploy secret registration client systemd unit ansible.builtin.template: src: secret_registration_client.service.j2 dest: /etc/systemd/system/secret_registration_client.service mode: "0644" - register: __trustee_attestation_client_service + register: __trustee_client_service - name: Append secret_registration_client to services list ansible.builtin.set_fact: - __trustee_attestation_client_services: >- - {{ __trustee_attestation_client_services | default([]) + ['secret_registration_client'] }} + __trustee_client_services: >- + {{ __trustee_client_services | default([]) + ['secret_registration_client'] }} notify: "restart trustee services" diff --git a/tasks/set_vars.yml b/tasks/set_vars.yml index 93528f4..10f12e3 100644 --- a/tasks/set_vars.yml +++ b/tasks/set_vars.yml @@ -1,12 +1,12 @@ --- - name: Ensure ansible_facts used by role setup: - gather_subset: "{{ __trustee_attestation_client_required_facts_subsets }}" - when: __trustee_attestation_client_required_facts | + gather_subset: "{{ __trustee_client_required_facts_subsets }}" + when: __trustee_client_required_facts | difference(ansible_facts.keys() | list) | length > 0 - name: Determine if system is ostree and set flag - when: not __trustee_attestation_client_is_ostree is defined + when: not __trustee_client_is_ostree is defined block: - name: Check if system is ostree stat: @@ -15,7 +15,7 @@ - name: Set flag to indicate system is ostree set_fact: - __trustee_attestation_client_is_ostree: "{{ __ostree_booted_stat.stat.exists }}" + __trustee_client_is_ostree: "{{ __ostree_booted_stat.stat.exists }}" - name: Set platform/version specific variables include_vars: "{{ __vars_file }}" diff --git a/tasks/trustee_quadlet.yml b/tasks/trustee_quadlet.yml index 4672850..cd192ef 100644 --- a/tasks/trustee_quadlet.yml +++ b/tasks/trustee_quadlet.yml @@ -1,34 +1,34 @@ --- - name: Ensure required packages are installed ansible.builtin.package: - name: "{{ __trustee_attestation_client_trustee_gc_packages }}" + name: "{{ __trustee_client_trustee_gc_packages }}" state: present - use: "{{ (__trustee_attestation_client_is_ostree | d(false)) | + use: "{{ (__trustee_client_is_ostree | d(false)) | ternary('ansible.posix.rhel_rpm_ostree', omit) }}" - name: Ensure quadlet install directory exists ansible.builtin.file: - path: "{{ trustee_attestation_client_quadlet_install_dir }}" + path: "{{ __trustee_client_quadlet_install_dir }}" state: directory mode: "0755" - name: Create a temporary directory for the quadlet repository ansible.builtin.tempfile: state: directory - register: __trustee_attestation_client_quadlet_repo_dir + register: __trustee_client_quadlet_repo_dir - name: Download Trustee Guest Components quadlet files from GitHub repository ansible.builtin.git: - repo: "{{ trustee_attestation_client_quadlet_repo_url }}" - dest: "{{ __trustee_attestation_client_quadlet_repo_dir.path }}" - version: "{{ trustee_attestation_client_quadlet_repo_branch }}" + repo: "{{ __trustee_client_quadlet_repo_url }}" + dest: "{{ __trustee_client_quadlet_repo_dir.path }}" + version: "{{ __trustee_client_quadlet_repo_branch }}" depth: 1 force: true register: quadlet_repo_download - name: Find Trustee Guest Components quadlet files in repository ansible.builtin.find: - paths: "{{ __trustee_attestation_client_quadlet_repo_dir.path }}/{{ trustee_attestation_client_quadlet_repo_path }}" + paths: "{{ __trustee_client_quadlet_repo_dir.path }}/{{ __trustee_client_quadlet_repo_path }}" patterns: - "*.container" - "*.volume" @@ -40,13 +40,13 @@ - name: Fail if no Trustee Guest Components quadlet files found ansible.builtin.fail: - msg: "No quadlet files found in {{ trustee_attestation_client_quadlet_repo_url }}/{{ trustee_attestation_client_quadlet_repo_path }}" + msg: "No quadlet files found in {{ __trustee_client_quadlet_repo_url }}/{{ __trustee_client_quadlet_repo_path }}" when: quadlet_files_found.files | length == 0 - name: Copy Trustee Guest Components quadlet files to install directory ansible.builtin.copy: src: "{{ item.path }}" - dest: "{{ trustee_attestation_client_quadlet_install_dir }}/{{ item.path | basename }}" + dest: "{{ __trustee_client_quadlet_install_dir }}/{{ item.path | basename }}" mode: "0644" remote_src: true force: true @@ -55,39 +55,49 @@ - name: Stat repository configs directory ansible.builtin.stat: - path: "{{ __trustee_attestation_client_quadlet_repo_dir.path }}/configs" + path: "{{ __trustee_client_quadlet_repo_dir.path }}/configs" register: __repo_configs_dir - name: Copy Trustee Guest Components config files to /etc/trustee-gc/ ansible.builtin.copy: - src: "{{ __trustee_attestation_client_quadlet_repo_dir.path }}/configs/" + src: "{{ __trustee_client_quadlet_repo_dir.path }}/configs/" dest: /etc/trustee-gc/ mode: "0644" remote_src: true force: true when: __repo_configs_dir.stat.exists -- name: Replace KBS_URL and KBS_CERT in config.toml files +- name: Set KBS cert content from path or explicit content + ansible.builtin.set_fact: + __trustee_client_kbs_cert_content: "{{ trustee_client_kbs_cert_content + if (trustee_client_kbs_cert_content | length > 0) + else lookup('file', trustee_client_kbs_cert_src) + if (trustee_client_kbs_cert_src | length > 0) else '' }}" + when: __repo_configs_dir.stat.exists + +- name: Replace KBS_URL in config.toml files + ansible.builtin.replace: + path: "{{ item }}" + regexp: KBS_URL + replace: "{{ trustee_client_kbs_url }}" + loop: + - /etc/trustee-gc/cdh/config.toml + - /etc/trustee-gc/aa/config.toml + when: + - __repo_configs_dir.stat.exists + - trustee_client_kbs_url | length > 0 + +- name: Replace KBS_CERT in config.toml files ansible.builtin.replace: - path: "{{ item.path }}" - regexp: "{{ item.regexp }}" - replace: "{{ item.replace }}" + path: "{{ item }}" + regexp: KBS_CERT + replace: "{{ __trustee_client_kbs_cert_content }}" loop: - - path: /etc/trustee-gc/cdh/config.toml - regexp: KBS_URL - replace: "{{ trustee_attestation_client_kbs_url }}" - - path: /etc/trustee-gc/cdh/config.toml - regexp: KBS_CERT - replace: "{{ trustee_attestation_client_kbs_cert_content }}" - - path: /etc/trustee-gc/aa/config.toml - regexp: KBS_URL - replace: "{{ trustee_attestation_client_kbs_url }}" - - path: /etc/trustee-gc/aa/config.toml - regexp: KBS_CERT - replace: "{{ trustee_attestation_client_kbs_cert_content }}" + - /etc/trustee-gc/cdh/config.toml + - /etc/trustee-gc/aa/config.toml when: - __repo_configs_dir.stat.exists - - trustee_attestation_client_kbs_url != "" or trustee_attestation_client_kbs_cert_content != "" + - __trustee_client_kbs_cert_content | length > 0 - name: Stat /dev/sev-guest device ansible.builtin.stat: @@ -96,14 +106,14 @@ - name: Add /dev/sev-guest to trustee-gc-aa.container when device exists ansible.builtin.replace: - path: "{{ trustee_attestation_client_quadlet_install_dir }}/trustee-gc-aa.container" + path: "{{ __trustee_client_quadlet_install_dir }}/trustee-gc-aa.container" regexp: '^#AddDevice=/dev/sev-guest' replace: 'AddDevice=/dev/sev-guest' when: __sev_guest_device.stat.exists - name: Get the installed Trustee Guest Components pod name ansible.builtin.find: - paths: "{{ trustee_attestation_client_quadlet_install_dir }}" + paths: "{{ __trustee_client_quadlet_install_dir }}" patterns: "*.pod" register: trustee_gc_pod_name @@ -118,12 +128,12 @@ - name: Write KBS certificate to /etc/trustee-gc/server.crt ansible.builtin.copy: - content: "{{ trustee_attestation_client_kbs_cert_content }}" + content: "{{ __trustee_client_kbs_cert_content }}" dest: /etc/trustee-gc/server.crt mode: "0644" - when: trustee_attestation_client_kbs_cert_content | length > 0 + when: __trustee_client_kbs_cert_content | length > 0 - name: Clean up temporary repository directory ansible.builtin.file: - path: "{{ __trustee_attestation_client_quadlet_repo_dir.path }}" + path: "{{ __trustee_client_quadlet_repo_dir.path }}" state: absent diff --git a/templates/secret_registration_client.service.j2 b/templates/secret_registration_client.service.j2 index d16ba0d..0d06d83 100644 --- a/templates/secret_registration_client.service.j2 +++ b/templates/secret_registration_client.service.j2 @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT {{ ansible_managed | comment }} -{{ "system_role:trustee_attestation_client" | comment(prefix="", postfix="") }} +{{ "system_role:trustee_client" | comment(prefix="", postfix="") }} [Unit] Description=Secret Registration Client - register with server and fetch disk encryption key diff --git a/templates/secret_registration_client.sh.j2 b/templates/secret_registration_client.sh.j2 index 1ff3618..17e84b0 100644 --- a/templates/secret_registration_client.sh.j2 +++ b/templates/secret_registration_client.sh.j2 @@ -2,7 +2,7 @@ #!/bin/bash -eu # SPDX-License-Identifier: MIT {{ ansible_managed | comment }} -{{ "system_role:trustee_attestation_client" | comment(prefix="", postfix="") }} +{{ "system_role:trustee_client" | comment(prefix="", postfix="") }} # # Secret Registration Client - registers with the server using attestation, # then fetches the disk encryption key from Trustee KBS. @@ -13,12 +13,12 @@ # set -o pipefail -REGISTRATION_SERVER_URL="{{ trustee_attestation_client_kbs_url }}" +REGISTRATION_SERVER_URL="{{ trustee_client_kbs_url }}" REGISTRATION_SERVER_PORT="8081" CDH_URL="http://127.0.0.1:8006" RESOURCE_REPOSITORY="disk-encryption" KEY_TAG="luks-key-0" -MOUNT_POINT="{{ trustee_attestation_client_encrypt_disk_mount_point }}" +MOUNT_POINT="{{ trustee_client_encrypt_disk_mount_point }}" log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*"; } die() { log "ERROR: $*"; exit 1; } @@ -61,8 +61,8 @@ mount_disk() { trap 'rm -f "$key_path"' EXIT fetch_key "$key_path" mkdir -p "$MOUNT_POINT" || die "Failed to create mount point directory" - cryptsetup open --key-file "$key_path" "$disk_partition" encrypted-disk || die "Failed to open encrypted disk" - mount /dev/mapper/encrypted-disk "$MOUNT_POINT" || die "Failed to mount encrypted disk" + cryptsetup open --key-file "$key_path" "$disk_partition" trustee_client_encrypted_disk_0 || die "Failed to open encrypted disk" + mount /dev/mapper/trustee_client_encrypted_disk_0 "$MOUNT_POINT" || die "Failed to mount encrypted disk" log "Mounted encrypted disk at $MOUNT_POINT" } diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/defaults b/tests/roles/linux-system-roles.trustee_client/defaults similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/defaults rename to tests/roles/linux-system-roles.trustee_client/defaults diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/handlers b/tests/roles/linux-system-roles.trustee_client/handlers similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/handlers rename to tests/roles/linux-system-roles.trustee_client/handlers diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/meta b/tests/roles/linux-system-roles.trustee_client/meta similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/meta rename to tests/roles/linux-system-roles.trustee_client/meta diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/tasks b/tests/roles/linux-system-roles.trustee_client/tasks similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/tasks rename to tests/roles/linux-system-roles.trustee_client/tasks diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/templates b/tests/roles/linux-system-roles.trustee_client/templates similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/templates rename to tests/roles/linux-system-roles.trustee_client/templates diff --git a/tests/roles/linux-system-roles.trustee_attestation_client/vars b/tests/roles/linux-system-roles.trustee_client/vars similarity index 100% rename from tests/roles/linux-system-roles.trustee_attestation_client/vars rename to tests/roles/linux-system-roles.trustee_client/vars diff --git a/tests/setup-snapshot.yml b/tests/setup-snapshot.yml index 0a9ce08..bf96e7a 100644 --- a/tests/setup-snapshot.yml +++ b/tests/setup-snapshot.yml @@ -4,11 +4,11 @@ tasks: - name: Set platform/version specific variables include_role: - name: linux-system-roles.trustee_attestation_client + name: linux-system-roles.trustee_client tasks_from: set_vars.yml public: true - name: Install test packages package: - name: "{{ (__trustee_attestation_client_trustee_gc_packages | default([])) + (__trustee_attestation_client_encrypt_disk_packages | default([])) | unique }}" + name: "{{ (__trustee_client_trustee_gc_packages | default([])) + (__trustee_client_encrypt_disk_packages | default([])) | unique }}" state: present diff --git a/tests/tests_default.yml b/tests/tests_default.yml index 9afba2e..56287d8 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -4,10 +4,10 @@ hosts: all gather_facts: false # test that role works without pre-gathered facts vars: - trustee_attestation_client_trustee_gc: true - trustee_attestation_client_encrypt_disk: false + trustee_client_trustee_gc: true + trustee_client_encrypt_disk: false roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client tasks: - name: Collect package facts package_facts: @@ -19,11 +19,11 @@ that: - item in ansible_facts.packages fail_msg: "Required package '{{ item }}' is not installed" - loop: "{{ __trustee_attestation_client_trustee_gc_packages }}" + loop: "{{ __trustee_client_trustee_gc_packages }}" - name: Stat the quadlet install directory stat: - path: "{{ trustee_attestation_client_quadlet_install_dir }}" + path: "{{ __trustee_client_quadlet_install_dir }}" register: __test_quadlet_dir - name: Assert quadlet install directory exists @@ -32,12 +32,12 @@ - __test_quadlet_dir.stat.exists - __test_quadlet_dir.stat.isdir fail_msg: >- - Quadlet install directory {{ trustee_attestation_client_quadlet_install_dir }} + Quadlet install directory {{ __trustee_client_quadlet_install_dir }} does not exist - name: Find deployed quadlet files find: - paths: "{{ trustee_attestation_client_quadlet_install_dir }}" + paths: "{{ __trustee_client_quadlet_install_dir }}" patterns: - "*.container" - "*.volume" @@ -51,7 +51,7 @@ that: - __test_quadlet_files.files | length > 0 fail_msg: >- - No quadlet files found in {{ trustee_attestation_client_quadlet_install_dir }} + No quadlet files found in {{ __trustee_client_quadlet_install_dir }} - name: Stat the trustee-gc config directory stat: @@ -67,7 +67,7 @@ - name: Find trustee pod file find: - paths: "{{ trustee_attestation_client_quadlet_install_dir }}" + paths: "{{ __trustee_client_quadlet_install_dir }}" patterns: "*.pod" recurse: false register: __test_trustee_pod_files @@ -75,7 +75,7 @@ - name: Assert trustee pod file exists assert: that: __test_trustee_pod_files.matched | int > 0 - fail_msg: "No trustee pod file found in {{ trustee_attestation_client_quadlet_install_dir }}" + fail_msg: "No trustee pod file found in {{ __trustee_client_quadlet_install_dir }}" - name: Set trustee pod service name ansible.builtin.set_fact: diff --git a/tests/tests_encrypt_disk.yml b/tests/tests_encrypt_disk.yml index b5657d9..1e20a95 100644 --- a/tests/tests_encrypt_disk.yml +++ b/tests/tests_encrypt_disk.yml @@ -3,13 +3,13 @@ # NOTE: This test requires an unpartitioned block device of type "disk" # to be present on the target host (e.g. a second virtual disk in a VM). # The test skips automatically when no such device is found. -- name: Ensure disk encryption works when trustee_attestation_client_encrypt_disk is enabled +- name: Ensure disk encryption works when trustee_client_encrypt_disk is enabled hosts: all gather_facts: false vars: - trustee_attestation_client_trustee_gc: false - trustee_attestation_client_encrypt_disk: true - trustee_attestation_client_encrypt_disk_mount_point: /mnt/encrypted-disk + trustee_client_trustee_gc: false + trustee_client_encrypt_disk: true + trustee_client_encrypt_disk_mount_point: /mnt/encrypted-disk tasks: - name: Check for an unpartitioned disk device ansible.builtin.shell: | @@ -34,14 +34,14 @@ ansible.builtin.set_fact: __test_skip_encrypt_assertions: "{{ __test_unpartitioned_disk.stdout | trim == '' }}" - - name: Run trustee_attestation_client role with disk encryption enabled + - name: Run trustee_client role with disk encryption enabled ansible.builtin.include_role: - name: linux-system-roles.trustee_attestation_client + name: linux-system-roles.trustee_client when: not __test_skip_encrypt_assertions - name: Stat the encrypted disk mount point ansible.builtin.stat: - path: "{{ trustee_attestation_client_encrypt_disk_mount_point }}" + path: "{{ trustee_client_encrypt_disk_mount_point }}" register: __test_mount_point when: not __test_skip_encrypt_assertions @@ -52,11 +52,11 @@ - __test_mount_point.stat.isdir fail_msg: >- Encrypted disk mount point - {{ trustee_attestation_client_encrypt_disk_mount_point }} does not exist + {{ trustee_client_encrypt_disk_mount_point }} does not exist when: not __test_skip_encrypt_assertions - name: Get mount information - ansible.builtin.command: findmnt --noheadings --output SOURCE {{ trustee_attestation_client_encrypt_disk_mount_point }} + ansible.builtin.command: findmnt --noheadings --output SOURCE {{ trustee_client_encrypt_disk_mount_point }} register: __test_findmnt changed_when: false failed_when: false @@ -68,24 +68,24 @@ - __test_findmnt.rc == 0 - __test_findmnt.stdout | trim != "" fail_msg: >- - Nothing is mounted at {{ trustee_attestation_client_encrypt_disk_mount_point }} + Nothing is mounted at {{ trustee_client_encrypt_disk_mount_point }} when: not __test_skip_encrypt_assertions - name: Assert the mounted device is the LUKS mapper device ansible.builtin.assert: that: - >- - '/dev/mapper/encrypted-disk' in + '/dev/mapper/trustee_client_encrypted_disk_0' in (__test_findmnt.stdout | trim) fail_msg: >- - Expected /dev/mapper/encrypted-disk to be mounted at - {{ trustee_attestation_client_encrypt_disk_mount_point }} but found: + Expected /dev/mapper/trustee_client_encrypted_disk_0 to be mounted at + {{ trustee_client_encrypt_disk_mount_point }} but found: {{ __test_findmnt.stdout }} when: not __test_skip_encrypt_assertions - name: Stat the LUKS mapper device ansible.builtin.stat: - path: /dev/mapper/encrypted-disk + path: /dev/mapper/trustee_client_encrypted_disk_0 register: __test_mapper_dev when: not __test_skip_encrypt_assertions @@ -93,7 +93,7 @@ ansible.builtin.assert: that: - __test_mapper_dev.stat.exists - fail_msg: "LUKS mapper device /dev/mapper/encrypted-disk does not exist" + fail_msg: "LUKS mapper device /dev/mapper/trustee_client_encrypted_disk_0 does not exist" when: not __test_skip_encrypt_assertions - name: Assert encrypted_disk_key fact was set @@ -106,7 +106,7 @@ - name: Stat podman storage directory on encrypted disk ansible.builtin.stat: - path: "{{ trustee_attestation_client_encrypt_disk_mount_point }}/containers-storage" + path: "{{ trustee_client_encrypt_disk_mount_point }}/containers-storage" register: __test_containers_storage when: not __test_skip_encrypt_assertions @@ -117,7 +117,7 @@ - __test_containers_storage.stat.isdir fail_msg: >- Podman storage directory - {{ trustee_attestation_client_encrypt_disk_mount_point }}/containers-storage + {{ trustee_client_encrypt_disk_mount_point }}/containers-storage was not created when: not __test_skip_encrypt_assertions @@ -131,9 +131,119 @@ ansible.builtin.assert: that: - >- - trustee_attestation_client_encrypt_disk_mount_point in + trustee_client_encrypt_disk_mount_point in (__test_storage_conf.content | b64decode) fail_msg: >- /etc/containers/storage.conf does not reference the encrypted - disk mount point {{ trustee_attestation_client_encrypt_disk_mount_point }} + disk mount point {{ trustee_client_encrypt_disk_mount_point }} when: not __test_skip_encrypt_assertions + +- name: Ensure disk encryption works with systemd-cryptenroll when secret_registration_client is disabled + hosts: all + gather_facts: false + vars: + trustee_client_trustee_gc: false + trustee_client_encrypt_disk: true + trustee_client_secret_registration_enabled: false + trustee_client_encrypt_disk_mount_point: /mnt/encrypted-disk + tasks: + - name: Check for an unpartitioned disk device + ansible.builtin.shell: | + set -o pipefail + lsblk -n -o NAME,TYPE,PKNAME | awk ' + $2=="disk" && $1 !~ /^zram|^loop|^dm/ { disk=$1; haspart[disk]=0 } + $2=="part" { parent=$3; if (parent in haspart) haspart[parent]=1 } + END { + for (d in haspart) { + if (haspart[d] == 0) { + print d + exit 0 + } + } + } + ' + register: __test_unpartitioned_disk + changed_when: false + failed_when: false + + - name: Set fact when no unpartitioned disk is available + ansible.builtin.set_fact: + __test_skip_cryptenroll_assertions: "{{ __test_unpartitioned_disk.stdout | trim == '' }}" + + - name: Check systemd-cryptenroll exists + ansible.builtin.command: command -v systemd-cryptenroll + register: __test_cryptenroll_check + changed_when: false + failed_when: false + when: not __test_skip_cryptenroll_assertions + + - name: Set fact when systemd-cryptenroll is not available + ansible.builtin.set_fact: + __test_skip_cryptenroll_assertions: "{{ __test_skip_cryptenroll_assertions or __test_cryptenroll_check.rc != 0 }}" + when: not __test_skip_cryptenroll_assertions + + - name: Run trustee_client role with disk encryption (cryptenroll path) + ansible.builtin.include_role: + name: linux-system-roles.trustee_client + when: not __test_skip_cryptenroll_assertions + + - name: Stat the encrypted disk mount point + ansible.builtin.stat: + path: "{{ trustee_client_encrypt_disk_mount_point }}" + register: __test_mount_point + when: not __test_skip_cryptenroll_assertions + + - name: Assert mount point directory exists + ansible.builtin.assert: + that: + - __test_mount_point.stat.exists + - __test_mount_point.stat.isdir + fail_msg: >- + Encrypted disk mount point + {{ trustee_client_encrypt_disk_mount_point }} does not exist + when: not __test_skip_cryptenroll_assertions + + - name: Assert the encrypted disk is mounted + ansible.builtin.command: findmnt --noheadings --output SOURCE {{ trustee_client_encrypt_disk_mount_point }} + register: __test_findmnt + changed_when: false + when: not __test_skip_cryptenroll_assertions + + - name: Assert the mounted device is the LUKS mapper device + ansible.builtin.assert: + that: + - __test_findmnt.rc == 0 + - "'/dev/mapper/trustee_client_encrypted_disk_0' in (__test_findmnt.stdout | default('') | trim)" + fail_msg: >- + Expected /dev/mapper/trustee_client_encrypted_disk_0 in the output of findmnt to be mounted at + {{ trustee_client_encrypt_disk_mount_point }} but found: + {{ __test_findmnt.stdout | default('') }} + when: not __test_skip_cryptenroll_assertions + + - name: Assert crypttab contains trustee_client_encrypted_disk_0 entry + ansible.builtin.slurp: + src: /etc/crypttab + register: __test_crypttab + when: not __test_skip_cryptenroll_assertions + + - name: Verify crypttab has trustee_client_encrypted_disk_0 with tpm2-device=auto + ansible.builtin.assert: + that: + - "'trustee_client_encrypted_disk_0' in (__test_crypttab.content | b64decode)" + - "'tpm2-device=auto' in (__test_crypttab.content | b64decode)" + fail_msg: "/etc/crypttab does not contain trustee_client_encrypted_disk_0 entry with tpm2-device=auto" + when: not __test_skip_cryptenroll_assertions + + - name: Assert fstab contains encrypted disk mount + ansible.builtin.slurp: + src: /etc/fstab + register: __test_fstab + when: not __test_skip_cryptenroll_assertions + + - name: Verify fstab has encrypted disk mount point + ansible.builtin.assert: + that: + - trustee_client_encrypt_disk_mount_point in (__test_fstab.content | b64decode) + - "'/dev/mapper/trustee_client_encrypted_disk_0' in (__test_fstab.content | b64decode)" + fail_msg: "/etc/fstab does not contain encrypted disk mount entry" + when: not __test_skip_cryptenroll_assertions diff --git a/tests/tests_include_vars_from_parent.yml b/tests/tests_include_vars_from_parent.yml index 91a9994..141e84c 100644 --- a/tests/tests_include_vars_from_parent.yml +++ b/tests/tests_include_vars_from_parent.yml @@ -44,7 +44,7 @@ import_role: name: caller vars: - roletoinclude: linux-system-roles.trustee_attestation_client + roletoinclude: linux-system-roles.trustee_client - name: Cleanup file: diff --git a/tests/tests_kbs_config.yml b/tests/tests_kbs_config.yml index 9ecfaf9..5978d02 100644 --- a/tests/tests_kbs_config.yml +++ b/tests/tests_kbs_config.yml @@ -4,12 +4,12 @@ hosts: all gather_facts: false vars: - trustee_attestation_client_trustee_gc: true - trustee_attestation_client_encrypt_disk: false - trustee_attestation_client_kbs_url: "https://kbs.example.com:8080" - trustee_attestation_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\nMIIBIjANBgkq\n-----END CERTIFICATE-----" + trustee_client_trustee_gc: true + trustee_client_encrypt_disk: false + trustee_client_kbs_url: "https://kbs.example.com:8080" + trustee_client_kbs_cert_content: "-----BEGIN CERTIFICATE-----\nMIIBIjANBgkq\n-----END CERTIFICATE-----" roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client tasks: - name: Stat CDH config file stat: @@ -28,10 +28,10 @@ assert: that: - >- - trustee_attestation_client_kbs_url in + trustee_client_kbs_url in (__test_cdh_content.content | b64decode) fail_msg: >- - KBS URL '{{ trustee_attestation_client_kbs_url }}' not found in + KBS URL '{{ trustee_client_kbs_url }}' not found in /etc/trustee-gc/cdh/config.toml - name: Assert CDH config does not contain the KBS_URL placeholder @@ -61,10 +61,10 @@ assert: that: - >- - trustee_attestation_client_kbs_url in + trustee_client_kbs_url in (__test_aa_content.content | b64decode) fail_msg: >- - KBS URL '{{ trustee_attestation_client_kbs_url }}' not found in + KBS URL '{{ trustee_client_kbs_url }}' not found in /etc/trustee-gc/aa/config.toml - name: Assert AA config does not contain the KBS_URL placeholder @@ -94,3 +94,81 @@ assert: that: __test_kbs_cert.stat.exists fail_msg: "KBS certificate /etc/trustee-gc/server.crt was not written" + +- name: Ensure KBS certificate from path is configured in trustee-gc config files + hosts: all + gather_facts: false + vars: + trustee_client_trustee_gc: true + trustee_client_encrypt_disk: false + trustee_client_kbs_url: "https://kbs.example.com:8080" + trustee_client_kbs_cert_content: "" + __test_cert_content: "-----BEGIN CERTIFICATE-----\nMIIBIjANBgkq\n-----END CERTIFICATE-----" + tasks: + - name: Create cert file on control node for path test + ansible.builtin.copy: + content: "{{ __test_cert_content }}" + dest: "{{ playbook_dir }}/kbs_test_cert.crt" + mode: "0644" + run_once: true + delegate_to: localhost + + - name: Run trustee_client role with KBS cert from path + ansible.builtin.include_role: + name: linux-system-roles.trustee_client + vars: + trustee_client_kbs_cert_src: "{{ playbook_dir }}/kbs_test_cert.crt" + + - name: Stat CDH config file + ansible.builtin.stat: + path: /etc/trustee-gc/cdh/config.toml + register: __test_cdh_config + + - name: Verify CDH config contains KBS URL and cert content + when: __test_cdh_config.stat.exists + block: + - name: Read CDH config file + ansible.builtin.slurp: + src: /etc/trustee-gc/cdh/config.toml + register: __test_cdh_content + + - name: Assert CDH config contains the KBS URL + ansible.builtin.assert: + that: + - >- + trustee_client_kbs_url in + (__test_cdh_content.content | b64decode) + fail_msg: >- + KBS URL '{{ trustee_client_kbs_url }}' not found in + /etc/trustee-gc/cdh/config.toml + + - name: Assert CDH config contains cert content from path + ansible.builtin.assert: + that: + - >- + 'MIIBIjANBgkq' in (__test_cdh_content.content | b64decode) + fail_msg: >- + KBS cert content from path not found in + /etc/trustee-gc/cdh/config.toml + + - name: Stat KBS certificate file + ansible.builtin.stat: + path: /etc/trustee-gc/server.crt + register: __test_kbs_cert + + - name: Assert KBS certificate was written from path + ansible.builtin.assert: + that: __test_kbs_cert.stat.exists + fail_msg: "KBS certificate /etc/trustee-gc/server.crt was not written from path" + + - name: Assert server.crt contains expected cert content + ansible.builtin.slurp: + src: /etc/trustee-gc/server.crt + register: __test_server_crt_content + + - name: Verify server.crt content matches cert from path + ansible.builtin.assert: + that: + - >- + __test_cert_content in (__test_server_crt_content.content | b64decode) + fail_msg: "KBS certificate /etc/trustee-gc/server.crt content does not match cert from path" diff --git a/tests/tests_secret_registration_client.yml b/tests/tests_secret_registration_client.yml index 5fed57c..98c2c47 100644 --- a/tests/tests_secret_registration_client.yml +++ b/tests/tests_secret_registration_client.yml @@ -4,10 +4,10 @@ hosts: all gather_facts: false vars: - trustee_attestation_client_trustee_gc: true - trustee_attestation_client_secret_registration_enabled: true + trustee_client_trustee_gc: true + trustee_client_secret_registration_enabled: true roles: - - linux-system-roles.trustee_attestation_client + - linux-system-roles.trustee_client tasks: - name: Collect package facts ansible.builtin.package_facts: @@ -18,7 +18,7 @@ ansible.builtin.assert: that: item in ansible_facts.packages fail_msg: "Required package {{ item }} is not installed" - loop: "{{ __trustee_attestation_client_trustee_gc_packages + __trustee_attestation_client_secret_registration_client_packages }}" + loop: "{{ __trustee_client_trustee_gc_packages + __trustee_client_secret_registration_client_packages }}" - name: Check secret registration client script exists ansible.builtin.stat: diff --git a/tests/tests_trustee_gc_disabled.yml b/tests/tests_trustee_gc_disabled.yml index 2507e74..020618b 100644 --- a/tests/tests_trustee_gc_disabled.yml +++ b/tests/tests_trustee_gc_disabled.yml @@ -4,22 +4,22 @@ # assert the role did not add any quadlet files or create /etc/trustee-gc. # This works in batch mode when a previous test (e.g. tests_default) already # left quadlet files on the host. -- name: Ensure role is a no-op when trustee_attestation_client_trustee_gc is disabled +- name: Ensure role is a no-op when trustee_client_trustee_gc is disabled hosts: all gather_facts: false vars: - trustee_attestation_client_trustee_gc: false - trustee_attestation_client_encrypt_disk: false - trustee_attestation_client_quadlet_install_dir: "/etc/containers/systemd" + trustee_client_trustee_gc: false + trustee_client_encrypt_disk: false + __trustee_client_quadlet_install_dir: "/etc/containers/systemd" tasks: - name: Stat quadlet install directory (before role) ansible.builtin.stat: - path: "{{ trustee_attestation_client_quadlet_install_dir }}" + path: "{{ __trustee_client_quadlet_install_dir }}" register: __test_quadlet_dir_before - name: Find quadlet files before role run ansible.builtin.find: - paths: "{{ trustee_attestation_client_quadlet_install_dir }}" + paths: "{{ __trustee_client_quadlet_install_dir }}" patterns: - "*.container" - "*.volume" @@ -36,19 +36,19 @@ - name: Run role with trustee_gc disabled ansible.builtin.include_role: - name: linux-system-roles.trustee_attestation_client + name: linux-system-roles.trustee_client vars: - trustee_attestation_client_trustee_gc: false - trustee_attestation_client_encrypt_disk: false + trustee_client_trustee_gc: false + trustee_client_encrypt_disk: false - name: Stat quadlet install directory (after role) ansible.builtin.stat: - path: "{{ trustee_attestation_client_quadlet_install_dir }}" + path: "{{ __trustee_client_quadlet_install_dir }}" register: __test_quadlet_dir_after - name: Find quadlet files after role run ansible.builtin.find: - paths: "{{ trustee_attestation_client_quadlet_install_dir }}" + paths: "{{ __trustee_client_quadlet_install_dir }}" patterns: - "*.container" - "*.volume" @@ -70,7 +70,7 @@ (__test_quadlet_files_after.files | default([]) | map(attribute='path') | sort | list) == (__test_quadlet_files_before.files | default([]) | map(attribute='path') | sort | list) fail_msg: >- - Role with trustee_attestation_client_trustee_gc false added or removed quadlet + Role with trustee_client_trustee_gc false added or removed quadlet files (expected no change) - name: Assert role did not create trustee-gc config directory @@ -81,4 +81,4 @@ __test_trustee_gc_dir_before.stat.exists fail_msg: >- Trustee GC config directory /etc/trustee-gc was created by the - role even though trustee_attestation_client_trustee_gc is false + role even though trustee_client_trustee_gc is false diff --git a/tests/vars/rh_distros_vars.yml b/tests/vars/rh_distros_vars.yml index 9a15a2b..d080745 100644 --- a/tests/vars/rh_distros_vars.yml +++ b/tests/vars/rh_distros_vars.yml @@ -4,17 +4,17 @@ # file is playbooks/templates/tests/vars/rh_distros_vars.yml --- # Ansible distribution identifiers that the role treats like RHEL -__trustee_attestation_client_rh_distros: +__trustee_client_rh_distros: - AlmaLinux - CentOS - RedHat - Rocky # Same as above but includes Fedora -__trustee_attestation_client_rh_distros_fedora: "{{ __trustee_attestation_client_rh_distros + ['Fedora'] }}" +__trustee_client_rh_distros_fedora: "{{ __trustee_client_rh_distros + ['Fedora'] }}" # Use this in conditionals to check if distro is Red Hat or clone -__trustee_attestation_client_is_rh_distro: "{{ ansible_facts['distribution'] in __trustee_attestation_client_rh_distros }}" +__trustee_client_is_rh_distro: "{{ ansible_facts['distribution'] in __trustee_client_rh_distros }}" # Use this in conditionals to check if distro is Red Hat or clone, or Fedora -__trustee_attestation_client_is_rh_distro_fedora: "{{ ansible_facts['distribution'] in __trustee_attestation_client_rh_distros_fedora }}" +__trustee_client_is_rh_distro_fedora: "{{ ansible_facts['distribution'] in __trustee_client_rh_distros_fedora }}" diff --git a/vars/Fedora.yml b/vars/Fedora.yml index bf52370..60c8da4 100644 --- a/vars/Fedora.yml +++ b/vars/Fedora.yml @@ -2,4 +2,4 @@ --- # Put internal variables here with Fedora specific values. -__trustee_attestation_client_services: [] +__trustee_client_services: [] diff --git a/vars/RedHat_10.yml b/vars/RedHat_10.yml index 9c71ce9..20dc173 100644 --- a/vars/RedHat_10.yml +++ b/vars/RedHat_10.yml @@ -2,4 +2,4 @@ --- # Put internal variables here with Red Hat Enterprise Linux 10 specific values. -__trustee_attestation_client_services: [] +__trustee_client_services: [] diff --git a/vars/RedHat_7.yml b/vars/RedHat_7.yml index b837b22..8975306 100644 --- a/vars/RedHat_7.yml +++ b/vars/RedHat_7.yml @@ -2,4 +2,4 @@ --- # Put internal variables here with Red Hat Enterprise Linux 7 specific values. -__trustee_attestation_client_services: [] +__trustee_client_services: [] diff --git a/vars/RedHat_8.yml b/vars/RedHat_8.yml index 6a4984f..8e07f3c 100644 --- a/vars/RedHat_8.yml +++ b/vars/RedHat_8.yml @@ -2,4 +2,4 @@ --- # Put internal variables here with Red Hat Enterprise Linux 8 specific values. -__trustee_attestation_client_services: [] +__trustee_client_services: [] diff --git a/vars/RedHat_9.yml b/vars/RedHat_9.yml index 2f14781..a925d21 100644 --- a/vars/RedHat_9.yml +++ b/vars/RedHat_9.yml @@ -2,4 +2,4 @@ --- # Put internal variables here with Red Hat Enterprise Linux 9 specific values. -__trustee_attestation_client_services: [] +__trustee_client_services: [] diff --git a/vars/main.yml b/vars/main.yml index b564391..183df56 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -5,18 +5,22 @@ # value in a platform/version specific file in vars/ # Examples of non-distribution specific (generic) internal variables: -__trustee_attestation_client_foo_config: foo.conf -__trustee_attestation_client_trustee_gc_packages: +__trustee_client_quadlet_repo_url: "https://github.com/litian1992/trustee-gc-quadlet-rhel" +__trustee_client_quadlet_repo_path: "quadlet" +__trustee_client_quadlet_repo_branch: "main" +__trustee_client_quadlet_install_dir: "/etc/containers/systemd" +__trustee_client_foo_config: foo.conf +__trustee_client_trustee_gc_packages: - podman - git -__trustee_attestation_client_encrypt_disk_packages: +__trustee_client_encrypt_disk_packages: - cryptsetup - parted -__trustee_attestation_client_secret_registration_client_packages: +__trustee_client_secret_registration_client_packages: - jq -__trustee_attestation_client_services: [] +__trustee_client_services: [] # ansible_facts required by the role -__trustee_attestation_client_required_facts: +__trustee_client_required_facts: - distribution - distribution_major_version - distribution_version @@ -24,23 +28,23 @@ __trustee_attestation_client_required_facts: # the subsets of ansible_facts that need to be gathered in case any of the # facts in required_facts is missing; see the documentation of # the 'gather_subset' parameter of the 'setup' module -__trustee_attestation_client_required_facts_subsets: "{{ ['!all', '!min'] + - __trustee_attestation_client_required_facts }}" +__trustee_client_required_facts_subsets: "{{ ['!all', '!min'] + + __trustee_client_required_facts }}" # BEGIN - DO NOT EDIT THIS BLOCK - rh distros variables # Ansible distribution identifiers that the role treats like RHEL -__trustee_attestation_client_rh_distros: +__trustee_client_rh_distros: - AlmaLinux - CentOS - RedHat - Rocky # Same as above but includes Fedora -__trustee_attestation_client_rh_distros_fedora: "{{ __trustee_attestation_client_rh_distros + ['Fedora'] }}" +__trustee_client_rh_distros_fedora: "{{ __trustee_client_rh_distros + ['Fedora'] }}" # Use this in conditionals to check if distro is Red Hat or clone -__trustee_attestation_client_is_rh_distro: "{{ ansible_facts['distribution'] in __trustee_attestation_client_rh_distros }}" +__trustee_client_is_rh_distro: "{{ ansible_facts['distribution'] in __trustee_client_rh_distros }}" # Use this in conditionals to check if distro is Red Hat or clone, or Fedora -__trustee_attestation_client_is_rh_distro_fedora: "{{ ansible_facts['distribution'] in __trustee_attestation_client_rh_distros_fedora }}" +__trustee_client_is_rh_distro_fedora: "{{ ansible_facts['distribution'] in __trustee_client_rh_distros_fedora }}" # END - DO NOT EDIT THIS BLOCK - rh distros variables