diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 58586726..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: 'Type: Bug' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. ... - - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Environment** -Please run the following an paste your output here: -``` bash -# Developement -ansible --version -python --version - -# Deployment -rpm -qa | grep gpfs -``` -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index a6caefe0..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: 'Type: Enhancement' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/roles/.DS_Store b/roles/.DS_Store new file mode 100644 index 00000000..123ac137 Binary files /dev/null and b/roles/.DS_Store differ diff --git a/roles/fal_install/tasks/install_repository.yml b/roles/fal_install/tasks/install_repository.yml index f98af3fd..5d691864 100644 --- a/roles/fal_install/tasks/install_repository.yml +++ b/roles/fal_install/tasks/install_repository.yml @@ -86,6 +86,7 @@ repo: "{{ scale_install_repository_url }}{{ scale_fal_url }}" disable_gpg_check: no state: present + overwrite_multiple: yes when: - ansible_pkg_mgr == 'zypper' - scale_install_repository_url is defined diff --git a/roles/gui_install/tasks/install_repository.yml b/roles/gui_install/tasks/install_repository.yml index 70396d60..446e1cd5 100644 --- a/roles/gui_install/tasks/install_repository.yml +++ b/roles/gui_install/tasks/install_repository.yml @@ -37,7 +37,7 @@ zypper_repository: name: spectrum-scale-gui description: IBM Spectrum Scale (GUI) - repo: "{{ scale_install_repository_url }}/gpfs_rpms/" + repo: "{{ scale_install_repository_url }}gpfs_rpms/" disable_gpg_check: no state: present overwrite_multiple: yes diff --git a/roles/gui_upgrade/tasks/install_repository.yml b/roles/gui_upgrade/tasks/install_repository.yml index d548e2d3..3ae49a57 100644 --- a/roles/gui_upgrade/tasks/install_repository.yml +++ b/roles/gui_upgrade/tasks/install_repository.yml @@ -44,7 +44,7 @@ zypper_repository: name: spectrum-scale-gui description: IBM Spectrum Scale (GUI) - repo: "{{ scale_install_repository_url }}/gpfs_rpms/" + repo: "{{ scale_install_repository_url }}gpfs_rpms/" disable_gpg_check: no state: present overwrite_multiple: yes diff --git a/roles/sed_configure/README.md b/roles/sed_configure/README.md new file mode 100644 index 00000000..5260478c --- /dev/null +++ b/roles/sed_configure/README.md @@ -0,0 +1,35 @@ +Role Definition +------------------------------- +- Role name: sed +- Definition: + - The self-encrypting drives (SED) support protects data at rest on IBM Storage Scale System drives. + - TPM is a specialized hardware security chip that provides secure cryptographic functions. + - mmvdisk tpm , esstpm and esstpmkey provides options to setup the tpm ,generate keys, enroll drives with the generated keys in the IBM Storage Scale cluster. + - These operations are performed on the I/O nodes and the keys generated are also backed up on the utility node. + + +Prerequisite +---------------------------- +- Red Hat Enterprise Linux 9.x is supported. +- OpenSSL version 3+ is supported. +- TPM version 2.0 is required to use this support +- A password file with appropriate permissions (600) must exist for taking TPM ownership. + +Design +--------------------------- +- Directory Structure: + - Path: /ibm-spectrum-scale-install-infra/roles/sed_configure + - Inside the sed role, there are sub-tasks to setup the TPM stepwise + - `check_prereq`: This task checks that all the prerequisites are satisfied before proceeding with the TPM setup. It checks the following things: + - RHEL 9.x is present. + - OpenSSL 3+ version present. + - Check whether TPM is enabled from BIOS. + - Check tpm2-tools rpms. If not installed already, install it. + - `tpm_ownership`: This task sets up the TPM to be used. + - check if tpm ownership already taken, if yes skip the entire process after validating the ownership + - if not taken, we proceed to take the ownership + - if 'change_pasword' flag is set, we skip the setup and jump to the password change + - `create_nv_slots`: This task create NV slots which will be used for key generation. + - `generate_tpm_key`: This task generated a tpm key in the mentioned nv slot. + - `enroll_sed`: This task enrolls an sed using the tpm key + - `manage_key`: This task handles the backup and restore of the tpm key. diff --git a/roles/sed_configure/defaults/main.yml b/roles/sed_configure/defaults/main.yml new file mode 100644 index 00000000..84144605 --- /dev/null +++ b/roles/sed_configure/defaults/main.yml @@ -0,0 +1,20 @@ +tpm_password_file: "/path/to/password.txt" +new_tpm_password_file: "/path/to/newpassword.txt" +disable_clear: true +change_password: false +nv_slot_id: "0x01500000" +nv_slot_count: 4 +recovery_group: "RecoveryGroupName" +enroll_drive: true +rekey_drive: false +generate: true +migrate: true +backup_key: true +restore_key: false +io_nodes: + - ionode1 + - ionode2 +utility_nodes: + - utilitynode +emsvm: + - emsvmnode \ No newline at end of file diff --git a/roles/sed_configure/meta/main.yml b/roles/sed_configure/meta/main.yml new file mode 100644 index 00000000..e48de9b9 --- /dev/null +++ b/roles/sed_configure/meta/main.yml @@ -0,0 +1,18 @@ +--- +galaxy_info: + author: IBM Corporation + description: Highly-customizable Ansible role for installing and configuring IBM Spectrum Scale (GPFS) + company: IBM + + license: Apache-2.0 + + min_ansible_version: 2.9 + + platforms: + - name: EL + versions: + - 9 + + galaxy_tags: [] + +dependencies: [] \ No newline at end of file diff --git a/roles/sed_configure/tasks/check_prereq.yml b/roles/sed_configure/tasks/check_prereq.yml new file mode 100644 index 00000000..89ed00d8 --- /dev/null +++ b/roles/sed_configure/tasks/check_prereq.yml @@ -0,0 +1,50 @@ +--- +- block: + # Check the OpenSSL version and fail if the version is < 3 + - name: Check OpenSSL version + command: openssl version + register: openssl_version_output + changed_when: false + failed_when: openssl_version_output.stdout | regex_search('OpenSSL\s([0-2]\\.[0-9]+)') + + - debug: + msg: "{{(openssl_version_output.rc == 0) | ternary(openssl_version_output.stdout.split('\n'), openssl_version_output.stderr.split('\n')) }}" + + # Check the OS version and fail if the version is < RHEL 9 + - name: Check OS version + command: cat /etc/redhat-release + register: os_version_output + changed_when: false + failed_when: os_version_output.stdout | regex_search('release\s([0-8])') + + - debug: + msg: "{{(os_version_output.rc == 0) | ternary(os_version_output.stdout.split('\n'), os_version_output.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + +- block: + - name: Check TPM presence + stat: + path: /dev/tpm0 + register: tpm_device + + - debug: + msg: "TPM device present" + when: tpm_device.stat.exists + + - fail: + msg: "TPM is not enabled in BIOS. Please enable it manually before proceeding." + when: not tpm_device.stat.exists + + - name: Check if tpm2-tools is installed + command: rpm -q tpm2-tools + register: tpm2_tools_check + ignore_errors: true + changed_when: false + + - name: Install tpm2-tools if not present + yum: + name: tpm2-tools + state: present + when: tpm2_tools_check.rc != 0 + delegate_to: "{{ item }}" + when: item in io_nodes \ No newline at end of file diff --git a/roles/sed_configure/tasks/create_nv_slot.yml b/roles/sed_configure/tasks/create_nv_slot.yml new file mode 100644 index 00000000..2c3b4f51 --- /dev/null +++ b/roles/sed_configure/tasks/create_nv_slot.yml @@ -0,0 +1,24 @@ +--- +- block: + # Creation of NV slots on IO nodes + - name: Create NV slots + command: mmvdisk tpm createSlots --number-of-slots {{ nv_slot_count }} --nv-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file }} + register: nv_slot_creation_io + failed_when: nv_slot_creation_io.rc != 0 + + - debug: + msg: "{{(nv_slot_creation_io.rc == 0) | ternary(nv_slot_creation_io.stdout.split('\n'), nv_slot_creation_io.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + when: item in io_nodes + +- block: + # Creation of NV slots on utility nodes + - name: Create NV slots on utility node + command: /opt/ibm/ess/tools/bin/.TPM/./esstpm createslot --nv-slot-id {{nv_slot_id}} --password-file {{ tpm_password_file }} + register: nv_slot_creation_utility + failed_when: nv_slot_creation_utility.rc != 0 + + - debug: + msg: "{{(nv_slot_creation_utility.rc == 0) | ternary(nv_slot_creation_utility.stdout.split('\n'), nv_slot_creation_utility.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + when: item in utility_nodes \ No newline at end of file diff --git a/roles/sed_configure/tasks/enroll_sed_drive.yml b/roles/sed_configure/tasks/enroll_sed_drive.yml new file mode 100644 index 00000000..3da3208e --- /dev/null +++ b/roles/sed_configure/tasks/enroll_sed_drive.yml @@ -0,0 +1,26 @@ +--- +- block: + # Enrolling the SED with the generated TPM key + - name: Enroll drives with TPM key + command: mmvdisk sed enroll --recovery-group {{ recovery_group }} --tpm-slot-id {{ nv_slot_id }} --confirm + register: drive_enrollment + + - debug: + msg: "{{(drive_enrollment.rc == 0) | ternary(drive_enrollment.stdout.split('\n'), drive_enrollment.stderr.split('\n')) }}" + failed_when: drive_enrollment.rc != 0 + delegate_to: "{{ item }}" + run_once: true + when: enroll_drive + +- block: + # Rekeying the SED with the a new TPM key + - name: Rekey drives with new TPM key + command: mmvdisk sed rekey --recovery-group {{ recovery_group }} --tpm-slot-id {{ nv_slot_id }} --confirm + register: drive_rekey + + - debug: + msg: "{{(drive_rekey.rc == 0) | ternary(drive_rekey.stdout.split('\n'), drive_rekey.stderr.split('\n')) }}" + failed_when: drive_rekey.rc != 0 + delegate_to: "{{ item }}" + run_once: true + when: rekey_drive \ No newline at end of file diff --git a/roles/sed_configure/tasks/generate_tpm_key.yml b/roles/sed_configure/tasks/generate_tpm_key.yml new file mode 100644 index 00000000..cfb30c8f --- /dev/null +++ b/roles/sed_configure/tasks/generate_tpm_key.yml @@ -0,0 +1,28 @@ +--- +- block: + # Generate a TPM key + - name: Generate TPM key + command: mmvdisk tpm genkey --nv-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file }} + register: tpm_key_generate + + - debug: + msg: "{{(tpm_key_generate.rc == 0) | ternary(tpm_key_generate.stdout.split('\n'), tpm_key_generate.stderr.split('\n')) }}" + failed_when: tpm_key_generate.rc != 0 + delegate_to: "{{ item }}" + when: generate + run_once: true + +- block: + # Migrate the generated TPM key to other io nodes + - name: Migrate TPM key to other nodes + command: mmvdisk tpm migratekey --nv-slot-id {{ nv_slot_id }} -s {{ io_nodes.0 }} -N {{ target_nodes | join(',') }} + vars: + target_nodes: "{{ io_nodes[1:] }}" + register: tpm_key_migrate + + - debug: + msg: "{{ (tpm_key_migrate.rc == 0) | ternary(tpm_key_migrate.stdout.split('\n'),tpm_key_migrate.stderr.split('\n')) }}" + failed_when: tpm_key_migrate.rc != 0 + delegate_to: "{{ io_nodes.0 }}" + when: migrate + run_once: true \ No newline at end of file diff --git a/roles/sed_configure/tasks/main.yml b/roles/sed_configure/tasks/main.yml new file mode 100644 index 00000000..682cb55e --- /dev/null +++ b/roles/sed_configure/tasks/main.yml @@ -0,0 +1,22 @@ +--- +- include_tasks: check_prereq.yml + tags: check prerequisites + loop: "{{ io_nodes + utility_nodes }}" + +- include_tasks: tpm_ownership.yml + tags: tpm ownership + loop: "{{ io_nodes + utility_nodes }}" + +- include_tasks: create_nv_slot.yml + tags: create nv slot + loop: "{{ io_nodes + utility_nodes }}" + +- include_tasks: generate_tpm_key.yml + tags: generate tpm key + +- include_tasks: enroll_sed_drive.yml + tags: enroll sed drive + +- include_tasks: manage_key.yml + tags: restore and backup key + loop: "{{ emsvm }}" \ No newline at end of file diff --git a/roles/sed_configure/tasks/manage_key.yml b/roles/sed_configure/tasks/manage_key.yml new file mode 100644 index 00000000..af2e1478 --- /dev/null +++ b/roles/sed_configure/tasks/manage_key.yml @@ -0,0 +1,25 @@ +--- +- block: + - name: Backup TPM key + command: /opt/ibm/ess/tools/bin/.TPM/./esstpmkey backup --source-node {{ source_node }} --destination-node {{ dest_node }} --tpm-slot-id {{ nv_slot_id }} --destination-node-password-file {{ tpm_password_file}} + vars: + source_node: "{{ io_nodes[0]}}" + dest_node: "{{ utility_nodes[0] }}" + register: backup_key + when: backup + + - debug: + msg: "{{(backup_key.rc == 0) | ternary(backup_key.stdout.split('\n'), backup_key.stderr.split('\n')) }}" + + - name: Restore TPM key from backup + command: /opt/ibm/ess/tools/bin/.TPM/./esstpmkey restore --source-node {{ source_node }} --destination-node {{ dest_node }} --tpm-slot-id {{ nv_slot_id }} --source-node-password-file {{ tpm_password_file}} + vars: + source_node: "{{ utility_nodes[0] }}" + dest_node: "{{ io_nodes[0] }}" + register: restore_key + when: restore + + - debug: + msg: "{{(restore_key.rc == 0) | ternary(restore_key.stdout.split('\n'), restore_key.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + run_once: true \ No newline at end of file diff --git a/roles/sed_configure/tasks/tpm_ownership.yml b/roles/sed_configure/tasks/tpm_ownership.yml new file mode 100644 index 00000000..8a6edc01 --- /dev/null +++ b/roles/sed_configure/tasks/tpm_ownership.yml @@ -0,0 +1,99 @@ +--- +- name: Check if ownership already taken on IO nodes + shell: | + tpm2_getcap properties-variable | awk -F': *' '/ownerAuthSet:/ { v=tolower($2); print (v ~ /(^1$|set|true)/) ? 1 : 0; exit }' + register: ownership_taken_io + changed_when: false + delegate_to: "{{ item }}" + when: item in io_nodes + +- name: Check if ownership already taken on utility node + shell: | + tpm2_getcap properties-variable | awk -F': *' '/ownerAuthSet:/ { v=tolower($2); print (v ~ /(^1$|set|true)/) ? 1 : 0; exit }' + register: ownership_taken_utility + changed_when: false + delegate_to: "{{ item }}" + when: item in utility_nodes + +# skip the setup -> if ownership taken. We mention that ownership is taken, validate it. And continue to nv slot creation. +- block: + - name: Validate ownership password + debug: + msg: Ownership already taken. Skipping the tpm ownership setup. + + - name: Check the password + command: mmvdisk tpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ tpm_password_file }} + register: pwd_validation_io + + - debug: + msg: "Validated the Ownership successfully" + when: pwd_validation_io.rc == 0 + + - fail: + msg: "Ownership password did not match. Please verify" + when: pwd_validation_io.rc != 0 + delegate_to: "{{ item }}" + when: item in io_nodes and ownership_taken_io.stdout == '1' and not change_password + +- block: + - name: Validate ownership password + debug: + msg: Ownership already taken. Skipping the tpm ownership setup. + + - name: Check the password + command: /opt/ibm/ess/tools/bin/.TPM/./esstpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ tpm_password_file }} + register: pwd_validation_utility + + - debug: + msg: "Validated the Ownership successfully" + when: pwd_validation_utility.rc == 0 + + - fail: + msg: "Ownership password did not match. Please verify" + when: pwd_validation_utility.rc != 0 + delegate_to: "{{ item }}" + when: item in utility_nodes and ownership_taken_utility.stdout == '1' and not change_password + +# if tpm ownership not taken already, proceed to take it on io nodes +- block: + - name: Disable TPM clear + command: tpm2_clearcontrol -C l s + register: disable_operation + when: disable_clear + + - name: Take TPM ownership # ensure file permission is 600 + command: mmvdisk tpm setup --password-file {{ tpm_password_file }} + register: take_ownership_io + + - debug: + msg: "{{(take_ownership_io.rc == 0) | ternary(take_ownership_io.stdout.split('\n'),take_ownership_io.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + when: item in io_nodes and ownership_taken_io.stdout == '0' and not change_password + +# if tpm ownership not taken already, proceed to take it on utility node +- block: + - name: Disable TPM clear + command: tpm2_clearcontrol -C l s + register: disable_operation + when: disable_clear + + - name: Take TPM ownership on utility node + command: /opt/ibm/ess/tools/bin/.TPM/./esstpm setup --password-file {{ tpm_password_file }} + register: take_ownership_utility + + - debug: + msg: "{{(take_ownership_utility.rc == 0) | ternary(take_ownership_utility.stdout.split('\n'), take_ownership_utility.stderr.split('\n')) }}" + delegate_to: "{{ item }}" + when: item in utility_nodes and ownership_taken_utility.stdout == '0' and not change_password + +# execute only when change password is set to true. +- block: + - name: Change TPM Ownership password + command: mmvdisk tpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ new_tpm_password_file }} + when: inventory_hostname in io_nodes + + - name: Change TPM Ownership password on utility node + command: /opt/ibm/ess/tools/bin/.TPM/./esstpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ new_tpm_password_file }} + when: inventory_hostname in utility_nodes + delegate_to: "{{ item }}" + when: change_password \ No newline at end of file diff --git a/samples/playbook_sed_tpm.yml b/samples/playbook_sed_tpm.yml new file mode 100644 index 00000000..0c43013c --- /dev/null +++ b/samples/playbook_sed_tpm.yml @@ -0,0 +1,7 @@ +--- +- hosts: all + become: no + pre_tasks: + - include_vars: sed_tpm_vars.yml + roles: + - sed_configure \ No newline at end of file diff --git a/samples/vars/sed_tpm_vars.yml b/samples/vars/sed_tpm_vars.yml new file mode 100644 index 00000000..b6733293 --- /dev/null +++ b/samples/vars/sed_tpm_vars.yml @@ -0,0 +1,19 @@ +tpm_password_file: "/root/tpm_pwd" +new_tpm_password_file: "/path/to/newpassword.txt" +disable_clear: true +nv_slot_count: 4 +nv_slot_id: "0x1500000" +generate: true +migrate: true +enroll_drive: true +rekey_drive: false +backup_key: true +restore_key: false +recovery_group: "recoverygroup" +io_nodes: + - ionode1 + - ionode2 +utility_nodes: + - utilitynode +emsvm: + - emsvmnode \ No newline at end of file