Browse Source

Add support for High Availability

This patch adds the ability to configure the Luna Network HSM
client to use more than one HSM for high availability (HA) mode.

Change-Id: If0eb393ca970206cc95c7453641f33781eb698b2
changes/06/740806/1
Douglas Mendizábal 3 weeks ago
parent
commit
b4eaaeb9cc
5 changed files with 148 additions and 87 deletions
  1. +17
    -10
      README.rst
  2. +2
    -10
      defaults/main.yaml
  3. +52
    -11
      tasks/main.yaml
  4. +77
    -0
      tasks/register_client.yaml
  5. +0
    -56
      tasks/register_hsm.yaml

+ 17
- 10
README.rst View File

@@ -1,11 +1,14 @@
lunasa-hsm
==========

A role to manage Safenet Lunasa Hardware Security Module (HSM) client software.
A role to manage Thales Luna Network Hardware Security Module (HSM) clients.

Role Variables
--------------

This ansible role automates the configuration of a new client for the
Thales Luna Network HSM.

.. list-table::
:widths: auto
:header-rows: 1
@@ -25,18 +28,22 @@ Role Variables
* - lunasa_client_installer_path
- None
- Path to the instal.sh script inside the tarball.
* - lunasa_hsm_server_hostname
- None
- Hostnme for the Lunasa HSM.
* - lunasa_hsm_server_admin_password
* - lunasa_client_pin
- None
- Password for the admin user for the Lunasa HSM.
* - lunasa_hsm_partition
- None
- HSM Partition to assign the client.
- The HSM Partition Password (PKCS#11 PIN) to be used by the client.
* - lunasa_client_ip
- None
- IP to use when registering the client.
- (Optional) When set, this role will use the given IP to register
the client instead of the client's fqdn.
* - lunasa_client_rotate_cert
- False
- When set to True, the role will generate a new client certificate
to replace the previous one.
* - lunasa_hsms
- None
- List of dictionaries, each of which describes a single HSM
`see vars.sample.yaml` for details. When more than one HSM is
listed here, the client will be configured in HA mode.

Requirements
------------


+ 2
- 10
defaults/main.yaml View File

@@ -1,12 +1,4 @@
---
# TODO: maybe use random tmpdir here
lunasa_client_working_dir: /tmp/lunasa_client_install

# non-defaults
#lunasa_client_tarball_location: http://download-node-02.eng.bos.redhat.com/qa/rhts/lookaside/IdM/rhcs/lunasa_software/610-012382-014_SW_Client_HSM_6.2_RevA.tar.zip
#lunasa_client_tarball_name: 610-012382-014_SW_Client_HSM_6.2_RevA.tar.zip
#lunasa_client_installer_path: 610-012382-014_SW_Client_HSM_6.2_RevA/linux/64/install.sh
#lunasa_hsm_server_hostname: os-luna-hsm-1.perf.lab.eng.rdu2.redhat.com
#lunasa_hsm_server_admin_password: ABC123!!!
#lunasa_hsm_partition: secdfgPartition1
#lunasa_client_ip: 10.0.79.37
lunasa_client_rotate_cert: false
lunasa_ha_label: myHAgroup

+ 52
- 11
tasks/main.yaml View File

@@ -1,9 +1,9 @@
---
- name: Create working directory
file:
path: "{{ lunasa_client_working_dir }}"
state: directory
mode: 0755
path: "{{ lunasa_client_working_dir }}"
state: directory
mode: 0755

- name: Download Lunasa client tarball
get_url:
@@ -26,22 +26,59 @@
creates: /usr/lib/libCryptoki2_64.so
become: true

- name: register the client to the HSMs
include_tasks: register_hsm.yaml
loop: "{{ lunasa_hsms }}"
- name: set client facts for fqdn
set_fact:
client_name: "{{ ansible_fqdn }}"
client_reg_opt: "-hostname"
client_host: "{{ ansible_fqdn }}"
client_cert_cn: "{{ inventory_hostname }}"
when: lunasa_client_ip is undefined

- name: set client facts for IP override
set_fact:
client_name: "{{ ansible_fqdn }}"
client_reg_opt: "-ip"
client_host: "{{ lunasa_client_ip }}"
client_cert_cn: "{{ lunasa_client_ip }}"
when: lunasa_client_ip is defined

- name: Check for existing client cert
stat:
path: "/usr/safenet/lunaclient/cert/client/{{ client_host }}.pem"
register: client_cert

- name: Generate a new client cert for NTL
command: /usr/safenet/lunaclient/bin/vtl createCert -n "{{ client_cert_cn }}"
become: true
register: created_cert
when: not client_cert.stat.exists or lunasa_client_rotate_cert

- name: Note when a new cert is created
set_fact:
client_new_cert: "{{ created_cert.changed }}"

- name: register the client on each HSM
include_tasks: register_client.yaml
vars:
hsm_name: "{{ item.name }}"
hsm_hostname: "{{ item.hostname }}"
hsm_admin_password: "{{ item.admin_password }}"
client_ip: "{{ item.client_ip }}"
hsm_partition: "{{ item.partition }}"
loop: "{{ lunasa_hsms }}"

- name: verify the NTL connection
command: /usr/safenet/lunaclient/bin/vtl verify
become: true
register: vtl_verify

- name: Fail if NTL connection doesn't verify
fail:
msg: >
ERROR: 'vtl verify' failed. This is commonly due to network NAT between
the client and the HSM. Try disabling client IP checking in the HSM
when: "'Error: Unable to find any Luna SA slots/partitions' in vtl_verify.stdout"

- name: create hsm ha partition
when: lunasa_ha_label is defined
when: lunasa_hsms | length > 1
become: true
block:
- name: create ha partition
@@ -49,7 +86,7 @@
echo 'copy' | /usr/safenet/lunaclient/bin/lunacm -c hagroup createGroup \
-label {{ lunasa_ha_label }} \
-serialNumber {{ lunasa_hsms[0].partition_serial }} \
-password {{ lunasa_partition_password }}
-password {{ lunasa_client_pin }}
register: result
failed_when:
- "'Command Result : No Error' not in result.stdout"
@@ -60,7 +97,7 @@
echo 'copy' | /usr/safenet/lunaclient/bin/lunacm -c hagroup addMember \
-group {{ lunasa_ha_label }} \
-serialNumber {{ item.partition_serial }} \
-password {{ lunasa_partition_password }}
-password {{ lunasa_client_pin }}
loop: "{{ lunasa_hsms }}"
loop_control:
extended: yes
@@ -86,3 +123,7 @@
- name: Set HA Slot fact for use by the playbook calling this role
set_fact:
lunasa_ha_slot: "{{ slot_result.stdout }}"

- name: Log the HA Slot ID used
debug:
var: lunasa_ha_slot

+ 77
- 0
tasks/register_client.yaml View File

@@ -0,0 +1,77 @@
---
- name: Log when client is being registered to HSM
debug:
msg: "Registering client: {{ client_name }} [{{ client_host }}] with HSM: {{ hsm_hostname }}"

- name: Get the hsm server cert from the hsm_server
shell: >
sshpass -p '{{ hsm_admin_password }}'
scp -o StrictHostKeyChecking=false -c aes256-cbc
admin@{{ hsm_hostname }}:server.pem
/usr/safenet/lunaclient/bin/{{ hsm_hostname }}.pem
args:
creates: /usr/safenet/lunaclient/bin/{{ hsm_hostname }}.pem
become: true

- name: Register the HSM server cert with the client
shell: >
/usr/safenet/lunaclient/bin/vtl addServer -n {{ hsm_hostname }}
-c /usr/safenet/lunaclient/bin/{{ hsm_hostname }}.pem
register: add_server
become: true
failed_when:
- add_server.rc != 0
- '"This server is already registered" not in add_server.stdout'

- name: Check for existing clients
shell: >
sshpass -p '{{ hsm_admin_password }}'
ssh -o StrictHostKeyChecking=false -c aes256-cbc admin@{{ hsm_hostname }}
-C client list
register: client_list

- name: Fail if client is already registered, but we don't have that cert
fail:
msg: "Client: {{ client_name }} is already registered, but the client cert is missing!"
when:
- client_name in client_list.stdout
- client_new_cert
- not lunasa_client_rotate_cert

- name: Delete existing client when rotating certs
shell: >
sshpass -p '{{ hsm_admin_password }}' ssh -c aes256-cbc admin@{{ hsm_hostname }}
-C "client delete -f -c {{ client_name }}"
when:
- client_name in client_list.stdout
- lunasa_client_rotate_cert

- name: Register the client certificate on the hsm_server
block:
- name: Copy the NTL client cert to the HSM
shell: >
sshpass -p '{{ hsm_admin_password }}' scp -c aes256-cbc
/usr/safenet/lunaclient/cert/client/{{ client_host }}.pem
admin@{{ hsm_hostname }}:{{ client_host }}.pem

- name: Register the client
shell: >
sshpass -p '{{ hsm_admin_password }}' ssh -c aes256-cbc admin@{{ hsm_hostname }}
-C "client register -c {{ client_name }} {{ client_reg_opt }} {{ client_host }}"
register: client_register
failed_when:
- client_register.rc != 0
- "'client with the same IP address has already been registered' not in client_register.stdout"
become: true
when: client_name not in client_list.stdout or lunasa_client_rotate_cert

- name: Assign client to an HSM partition
shell: |
sshpass -p '{{ hsm_admin_password }}' ssh -c aes256-cbc admin@{{ hsm_hostname }} \
-C "client assignPartition -c {{ client_name }} -p {{ hsm_partition }}"
register: assign_partition
failed_when:
- assign_partition.rc != 0
- "'client already has access' not in assign_partition.stdout"
become: true


+ 0
- 56
tasks/register_hsm.yaml View File

@@ -1,56 +0,0 @@
---
- debug:
msg: "Registering the following HSM: {{ hsm_name }}"

- name: Get the hsm server cert from the hsm_server
shell: |
sshpass -p '{{ hsm_admin_password }}' \
scp -o StrictHostKeyChecking=false admin@{{ hsm_hostname }}:server.pem /usr/safenet/lunaclient/bin/{{ hsm_hostname }}.pem
become: true

- name: Register the HSM server cert with the client
shell: |
/usr/safenet/lunaclient/bin/vtl addServer -n {{ hsm_hostname }} \
-c /usr/safenet/lunaclient/bin/{{ hsm_hostname }}.pem
register: add_server
become: true
failed_when:
- add_server.rc != 0
- '"This server is already registered" not in add_server.stdout'

- name: Set the cert file name
set_fact:
client_name: "{{ inventory_hostname }}"

- name: Create a client cert for NTL
command: /usr/safenet/lunaclient/bin/vtl createCert -n "{{ client_ip }}"
args:
creates: "/usr/safenet/lunaclient/cert/client/{{ client_ip }}.pem"
become: true

- name: Copy the NTL client cert to the HSM
shell: |
sshpass -p '{{ hsm_admin_password }}' scp /usr/safenet/lunaclient/cert/client/{{ client_ip }}.pem \
admin@{{ hsm_hostname }}:{{ client_ip }}.pem
become: true

# A client with the same hostname has already been registered
- name: Register the client certificate on the hsm_server
shell: |
sshpass -p '{{ hsm_admin_password }}' ssh admin@{{ hsm_hostname }} \
-C "client register -c {{ client_name }} -ip {{ client_ip }}"
register: client_register
failed_when:
- client_register.rc != 0
- "'client with the same IP address has already been registered' not in client_register.stdout"
become: true

- name: Assign client to an HSM partition
shell: |
sshpass -p '{{ hsm_admin_password }}' ssh admin@{{ hsm_hostname }} \
-C "client assignPartition -c {{ client_name }} -p {{ hsm_partition }}"
register: assign_partition
failed_when:
- assign_partition.rc != 0
- "'client already has access' not in assign_partition.stdout"
become: true

Loading…
Cancel
Save