Skip to content

Commit 81639e5

Browse files
committed
Added sed tpm support
Signed-off-by: Dhananjay Sonawane <[email protected]>
1 parent e70e2a7 commit 81639e5

File tree

11 files changed

+410
-0
lines changed

11 files changed

+410
-0
lines changed

roles/sed_configure/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Role Definition
2+
-------------------------------
3+
- Role name: sed
4+
- Definition:
5+
- The self-encrypting drives (SED) support protects data at rest on IBM Storage Scale System drives.
6+
- TPM is a specialized hardware security chip that provides secure cryptographic functions.
7+
- mmvdisk tpm , esstpm and esstpm key provides options to setup the tpm ,generate keys, enroll drives with the generated keys in the IBM Storage Scale cluster.
8+
- These operations are performed on the I/O nodes and the keys generated are also backed up on the utility node.
9+
10+
11+
Prerequisite
12+
----------------------------
13+
- Red Hat Enterprise Linux 9.x is supported.
14+
- OpenSSL version 3+ is supported.
15+
- TPM version 2.0 is required to use this support
16+
- A password file with appropriate permissions (600) must exist for taking TPM ownership.
17+
18+
Design
19+
---------------------------
20+
- Directory Structure:
21+
- Path: /ibm-spectrum-scale-install-infra/roles/sed_configure
22+
- Inside the sed role, there are sub-tasks to setup the TPM stepwise
23+
- `check_prereq`: This task checks that all the prerequisites are satisfied before proceeding with the TPM setup. It checks the following things:
24+
- RHEL 9.x is present.
25+
- OpenSSL 3+ version present.
26+
- Check whether TPM is enabled from BIOS.
27+
- Check tpm2-tools rpms. If not installed already, install it.
28+
- `tpm_ownership`: This task sets up the TPM to be used.
29+
- check if tpm ownership already taken, if yes skip the entire process after validating the ownership
30+
- if not taken, we proceed to take the ownership
31+
- if 'change_pasword' flag is set, we skip the setup and jump to the password change
32+
- `create_nv_slots`: This task create NV slots which will be used for key generation.
33+
- `generate_tpm_key`: This task generated a tpm key in the mentioned nv slot.
34+
- `enroll_sed`: This task enrolls an sed using the tpm key
35+
- `manage_key`: This task handles the backup and restore of the tpm key.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tpm_password_file: "/path/to/password.txt"
2+
new_tpm_password_file: "/path/to/newpassword.txt"
3+
disable_clear: true
4+
change_password: false
5+
nv_slot_id: "0x01500000"
6+
nv_slot_count: 2
7+
recovery_group: "RecoveryGroupName"
8+
enroll_drive: true
9+
rekey_drive: false
10+
generate: true
11+
migrate: true
12+
backup_key: true
13+
restore_key: true
14+
15+

roles/sed_configure/meta/main.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
galaxy_info:
3+
author: IBM Corporation
4+
description: Highly-customizable Ansible role for installing and configuring IBM Spectrum Scale (GPFS)
5+
company: IBM
6+
7+
license: Apache-2.0
8+
9+
min_ansible_version: 2.9
10+
11+
platforms:
12+
- name: EL
13+
versions:
14+
- 7
15+
- 8
16+
17+
galaxy_tags: []
18+
19+
dependencies:
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
- block:
3+
# Check the OpenSSL version and fail if the version is < 3
4+
- name: Check OpenSSL version
5+
command: openssl version
6+
register: openssl_version_output
7+
changed_when: false
8+
failed_when: openssl_version_output.stdout | regex_search('OpenSSL\s([0-2]\\.[0-9]+)')
9+
10+
- debug:
11+
msg: "{{(openssl_version_output.rc == 0) | ternary(openssl_version_output.stdout.split('\n'), openssl_version_output.stderr.split('\n')) }}"
12+
13+
# Check the OS version and fail if the version is < RHEL 9
14+
- name: Check OS version
15+
command: cat /etc/redhat-release
16+
register: os_version_output
17+
changed_when: false
18+
failed_when: os_version_output.stdout | regex_search('release\s([0-8])')
19+
20+
- debug:
21+
msg: "{{(os_version_output.rc == 0) | ternary(os_version_output.stdout.split('\n'), os_version_output.stderr.split('\n')) }}"
22+
when: inventory_hostname == 'localhost' or inventory_hostname in scale_io_nodes_list
23+
24+
- block:
25+
- name: Check TPM presence
26+
stat:
27+
path: /dev/tpm0
28+
register: tpm_device
29+
30+
- debug:
31+
msg: "TPM device present"
32+
when: tpm_device.stat.exists
33+
34+
- fail:
35+
msg: "TPM is not enabled in BIOS. Please enable it manually before proceeding."
36+
when: not tpm_device.stat.exists
37+
38+
- name: Check if tpm2-tools is installed
39+
command: rpm -q tpm2-tools
40+
register: tpm2_tools_check
41+
ignore_errors: true
42+
changed_when: false
43+
44+
- name: Install tpm2-tools if not present
45+
yum:
46+
name: tpm2-tools
47+
state: present
48+
when: tpm2_tools_check.rc != 0
49+
when: inventory_hostname in scale_io_nodes_list
50+
51+
52+
53+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
- block:
3+
# Creation of NV slots on IO nodes
4+
- name: Create NV slots
5+
command: mmvdisk tpm createSlots --number-of-slots {{ nv_slot_count }} --nv-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file }}
6+
register: nv_slot_creation_io
7+
failed_when: nv_slot_creation_io.rc != 0
8+
9+
- debug:
10+
msg: "{{(nv_slot_creation_io.rc == 0) | ternary(nv_slot_creation_io.stdout.split('\n'), nv_slot_creation_io.stderr.split('\n')) }}"
11+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
12+
13+
- block:
14+
# Creation of NV slots on utility nodes
15+
- name: Create NV slots on utility node
16+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpm createslot --nv-slot-id {{nv_slot_id}} --password-file {{ tpm_password_file }}
17+
register: nv_slot_creation_utility
18+
failed_when: nv_slot_creation_utility.rc != 0
19+
20+
- debug:
21+
msg: "{{(nv_slot_creation_utility.rc == 0) | ternary(nv_slot_creation_utility.stdout.split('\n'), nv_slot_creation_utility.stderr.split('\n')) }}"
22+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_utility_nodes_list']
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
- block:
3+
# Enrolling the SED with the generated TPM key
4+
- name: Enroll drives with TPM key
5+
command: mmvdisk sed enroll --recovery-group {{ recovery_group }} --tpm-slot-id {{ nv_slot_id }}
6+
register: drive_enrollment
7+
8+
- debug:
9+
msg: "{{(drive_enrollment.rc == 0) | ternary(drive_enrollment.stdout.split('\n'), drive_enrollment.stderr.split('\n')) }}"
10+
failed_when: drive_enrollment.rc != 0
11+
when: enroll_drive and inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
12+
run_once: true
13+
14+
- block:
15+
# Rekeying the SED with the a new TPM key
16+
- name: Rekey drives with new TPM key
17+
command: mmvdisk sed rekey --recovery-group {{ recovery_group }} --tpm-slot-id {{ nv_slot_id }}
18+
register: drive_rekey
19+
20+
- debug:
21+
msg: "{{(drive_rekey.rc == 0) | ternary(drive_rekey.stdout.split('\n'), drive_rekey.stderr.split('\n')) }}"
22+
failed_when: drive_rekey.rc != 0
23+
when: rekey_drives and inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
24+
run_once: true
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
# Generate only on one node. migrate to others.
3+
# Run both commands only on one single io node.
4+
5+
- block:
6+
# Generate a TPM key
7+
- name: Generate TPM key
8+
command: mmvdisk tpm genkey --nv-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file }}
9+
register: tpm_key_generate
10+
11+
- debug:
12+
msg: "{{(tpm_key_generate.rc == 0) | ternary(tpm_key_generate.stdout.split('\n'), tpm_key_generate.stderr.split('\n')) }}"
13+
failed_when: tpm_key_generate.rc != 0
14+
when: generate and inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
15+
run_once: true
16+
17+
- block:
18+
# Migrate the generated TPM key to other io nodes
19+
- name: Migrate TPM key to other nodes
20+
command: mmvdisk tpm migratekey --nv-slot-id {{ nv_slot_id }} -s {{ inventory_hostname }} -N {{ target_nodes | join(',') }}
21+
vars:
22+
target_nodes: "{{ (hostvars[groups['emsvm'][0]]['scale_io_nodes_list'])[1:]}}"
23+
register: tpm_key_migrate
24+
25+
- debug:
26+
msg: "{{ (tpm_key_migrate.rc == 0) | ternary(tpm_key_migrate.stdout.split('\n'),tpm_key_migrate.stderr.split('\n')) }}"
27+
failed_when: tpm_key_migrate.rc != 0
28+
when: migrate and inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
29+
run_once: true

roles/sed_configure/tasks/main.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
- import_tasks: check_prereq.yml
3+
tags: check prerequisites
4+
5+
- import_tasks: tpm_ownership.yml
6+
tags: tpm ownership
7+
8+
- import_tasks: create_nv_slot.yml
9+
tags: create nv slot
10+
11+
- import_tasks: generate_tpm_key.yml
12+
tags: generate tpm key
13+
14+
- import_tasks: enroll_sed_drive.yml
15+
tags: enroll sed drive
16+
17+
- import_tasks: manage_key.yml
18+
tags: restore and backup key
19+
20+
21+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
- block:
3+
- name: Backup TPM key
4+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpmkey backup --source-node {{ source_node }} --destination-node {{ dest_node }} --tpm-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file}}
5+
vars:
6+
source_node: "{{ hostvars[groups['emsvm'][0]]['scale_io_nodes_list'][0] }}"
7+
dest_node: "{{ hostvars[groups['emsvm'][0]]['scale_utility_nodes_list'][0] }}"
8+
register: backup_key
9+
when: backup
10+
11+
- debug:
12+
msg: "{{(backup_key.rc == 0) | ternary(backup_key.stdout.split('\n'), backup_key.stderr.split('\n')) }}"
13+
14+
- name: Restore TPM key from backup
15+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpmkey restore --source-node {{ source_node }} --destination-node {{ dest_node }} --tpm-slot-id {{ nv_slot_id }} --password-file {{ tpm_password_file}}
16+
vars:
17+
source_node: "{{hostvars[groups['emsvm'][0]]['scale_utility_nodes_list'][0] }}"
18+
dest_node: "{{ hostvars[groups['emsvm'][0]]['scale_io_nodes_list'][0] }}"
19+
register: restore_key
20+
when: restore
21+
22+
- debug:
23+
msg: "{{(restore_key.rc == 0) | ternary(restore_key.stdout.split('\n'), restore_key.stderr.split('\n')) }}"
24+
when: inventory_hostname in scale_ems_vm_nodes_list
25+
26+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
- name: Check if ownership already taken on IO nodes
3+
shell: |
4+
tpm2_getcap properties-variable | awk -F': *' '/ownerAuthSet:/ { v=tolower($2); print (v ~ /(^1$|set|true)/) ? 1 : 0; exit }'
5+
register: ownership_taken_io
6+
changed_when: false
7+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
8+
9+
- name: Check if ownership already taken on utility node
10+
shell: |
11+
tpm2_getcap properties-variable | awk -F': *' '/ownerAuthSet:/ { v=tolower($2); print (v ~ /(^1$|set|true)/) ? 1 : 0; exit }'
12+
register: ownership_taken_utility
13+
changed_when: false
14+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_utility_nodes_list']
15+
16+
# skip the setup -> if ownership taken. We mention that ownership is taken, validate it. And continue to nv slot creation.
17+
- block:
18+
- name: Validate ownership password
19+
debug:
20+
msg: Ownership already taken. Skipping the tpm ownership setup.
21+
22+
- name: Check the password
23+
command: mmvdisk tpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ tpm_password_file }}
24+
register: pwd_validation_io
25+
26+
- debug:
27+
msg: "Validated the Ownership successfully"
28+
when: pwd_validation_io.rc == 0
29+
30+
- fail:
31+
msg: "Ownership password did not match. Please verify"
32+
when: pw_validation_io.rc != 0
33+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list'] and ownership_taken_io.stdout == '1' and not change_password
34+
35+
- block:
36+
- name: Validate ownership password
37+
debug:
38+
msg: Ownership already taken. Skipping the tpm ownership setup.
39+
40+
- name: Check the password
41+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ tpm_password_file }}
42+
register: pwd_validation_utility
43+
44+
- debug:
45+
msg: "Validated the Ownership successfully"
46+
when: pwd_validation_utility.rc == 0
47+
48+
- fail:
49+
msg: "Ownership password did not match. Please verify"
50+
when: pw_validation_utility.rc != 0
51+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_utility_nodes_list'] and ownership_taken_utility.stdout == '1' and not change_password
52+
53+
# if tpm ownership not taken already, proceed to take it on io nodes
54+
- block:
55+
- name: Disable TPM clear
56+
command: tpm2_clearcontrol -C l s
57+
register: disable_operation
58+
when: disable_clear
59+
60+
- name: Take TPM ownership # ensure file permission is 600
61+
command: mmvdisk tpm setup --password-file {{ tpm_password_file }}
62+
register: take_ownership_io
63+
64+
- debug:
65+
msg: "{{(take_ownership.rc == 0) | ternary(take_ownership_io.stdout.split('\n'),take_ownership_io.stderr.split('\n')) }}"
66+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list'] and ownership_taken_io.stdout == '0' and not change_password
67+
68+
# if tpm ownership not taken already, proceed to take it on utility node
69+
- block:
70+
- name: Disable TPM clear
71+
command: tpm2_clearcontrol -C l s
72+
register: disable_operation
73+
when: disable_clear
74+
75+
- name: Take TPM ownership on utility node
76+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpm setup --password-file {{ tpm_password_file }}
77+
register: take_ownership_utility
78+
79+
- debug:
80+
msg: "{{(take_ownership_utility.rc == 0) | ternary(take_ownership_utility.stdout.split('\n'), take_ownership_utility.stderr.split('\n')) }}"
81+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_utility_nodes_list'] and ownership_taken_utility.stdout == '0' and not change_password
82+
83+
# execute only when change password is set to true.
84+
- block:
85+
- name: Change TPM Ownership password
86+
command: mmvdisk tpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ new_tpm_password_file }}
87+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_io_nodes_list']
88+
89+
- name: Change TPM Ownership password on utility node
90+
command: /opt/ibm/ess/tools/bin/.TPM/./esstpm chpasswd --old-password-file {{ tpm_password_file }} --new-password-file {{ new_tpm_password_file }}
91+
when: inventory_hostname in hostvars[groups['emsvm'][0]]['scale_utility_nodes_list']
92+
when: change_password
93+
94+
95+

0 commit comments

Comments
 (0)