From 99711abf23b9a7bf76d50ec45309c25911899c5e Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Wed, 7 Dec 2022 18:08:58 +0100
Subject: [PATCH] Add ubuntu to enable-fips role

The enable-fips role has been refactored to support both centos/rhel and
Ubuntu.

In addition, for the Ubuntu tasks, a small role is added to enable a
Ubuntu Advantage subscription.  This is required because Ubuntu requires
a subscription to enable FIPS.  This role takes a subscription key as a
parameter (ubuntu_ua_token.token).

In Openstack, this is provided by the openstack-fips job in
openstack/project-config, which will be the base job for OpenStack jobs.
This job will provide the ubuntu_ua_token.token.

Change-Id: I47a31f680172b47584510adb672b68498a85bd32
---
 doc/source/general-roles.rst                 |  1 +
 playbooks/enable-fips/README.rst             | 18 +++++
 roles/enable-fips/README.rst                 |  7 +-
 roles/enable-fips/tasks/main.yaml            | 69 ++++----------------
 roles/enable-fips/tasks/rhel.yaml            | 56 ++++++++++++++++
 roles/enable-fips/tasks/ubuntu.yaml          | 31 +++++++++
 roles/enable-ua-subscription/README.rst      | 13 ++++
 roles/enable-ua-subscription/tasks/main.yaml | 12 ++++
 roles/post-reboot-tasks/README.rst           | 14 +++-
 9 files changed, 161 insertions(+), 60 deletions(-)
 create mode 100644 playbooks/enable-fips/README.rst
 create mode 100644 roles/enable-fips/tasks/rhel.yaml
 create mode 100644 roles/enable-fips/tasks/ubuntu.yaml
 create mode 100644 roles/enable-ua-subscription/README.rst
 create mode 100644 roles/enable-ua-subscription/tasks/main.yaml

diff --git a/doc/source/general-roles.rst b/doc/source/general-roles.rst
index 0e1b8f729..cbc9d9255 100644
--- a/doc/source/general-roles.rst
+++ b/doc/source/general-roles.rst
@@ -16,6 +16,7 @@ General Purpose Roles
 .. zuul:autorole:: emit-job-header
 .. zuul:autorole:: enable-fips
 .. zuul:autorole:: enable-netconsole
+.. zuul:autorole:: enable-ua-subscription
 .. zuul:autorole:: encrypt-file
 .. zuul:autorole:: ensure-bazelisk
 .. zuul:autorole:: ensure-dhall
diff --git a/playbooks/enable-fips/README.rst b/playbooks/enable-fips/README.rst
new file mode 100644
index 000000000..f6f28d151
--- /dev/null
+++ b/playbooks/enable-fips/README.rst
@@ -0,0 +1,18 @@
+The enable-fips playbook can be invoked to enable FIPS mode on jobs.
+
+This playbook will call the enable-fips role, which will turn FIPS mode on
+and then reboot the node.  To get consistent results, this role should
+be run very early in the node setup process, so that resources set up
+later are not affected by the reboot.
+
+A playbook variable enable_fips - which defaults to True - is provided.
+This variable can be used to skip this playbook.
+
+**Job Variables**
+
+.. zuul:jobvar:: enable_fips
+   :default: True
+
+   Whether to run the playbook and enable fips.  Defaults to True.
+
+
diff --git a/roles/enable-fips/README.rst b/roles/enable-fips/README.rst
index 055248612..be1ea532a 100644
--- a/roles/enable-fips/README.rst
+++ b/roles/enable-fips/README.rst
@@ -1,7 +1,12 @@
 Enable FIPS on a node.
 
 Set a node into FIPS mode, to test functionality when crypto
-policies are set to FIPS in RHEL 8/Centos 8.
+policies are set to FIPS in RHEL/Centos >=8 or Ubuntu.
+
+For Ubuntu nodes, the node is assumed to already have an Ubuntu
+Advantage subscription activated, as this is required to enable
+FIPS mode.  The enable-ua-subscription role in this repo can be
+used to activate the subscription.
 
 The role will set the node into FIPS mode, reboot the node, and
 then call the post-reboot-tasks role.  This role requires a role
diff --git a/roles/enable-fips/tasks/main.yaml b/roles/enable-fips/tasks/main.yaml
index 05525283b..e339ca4be 100644
--- a/roles/enable-fips/tasks/main.yaml
+++ b/roles/enable-fips/tasks/main.yaml
@@ -1,64 +1,21 @@
 ---
-- name: Make sure this role is run on RHEL/CentOS 8 systems
+- name: Make sure this role is run on RHEL/CentOS/Ubuntu systems
   fail:
-    msg: This role supports RHEL/CentOS 8 systems and Fedora only
+    msg: This role supports RHEL/CentOS/Fedora/Ubuntu systems only
   when:
     - not (ansible_distribution == 'CentOS' and ansible_distribution_major_version|int >= 8)
     - not (ansible_distribution == 'Red Hat Enterprise Linux' and ansible_distribution_major_version|int >= 8)
     - not ansible_distribution == 'Fedora'
+    - not ansible_distribution == 'Ubuntu'
 
-- name: Install fips-mode-setup
-  become: true
-  package:
-    name: crypto-policies-scripts
-    state: present
+- name: Do tasks for RHEL/Centos systems
+  include_tasks: rhel.yaml
+  when: >
+    (ansible_distribution == 'CentOS' and ansible_distribution_major_version|int >= 8) or
+    (ansible_distribution == 'Red Hat Enterprise Linux' and ansible_distribution_major_version|int >= 8) or
+    ansible_distribution == 'Fedora'
 
-- name: Enable FIPS mode
-  become: true
-  command: fips-mode-setup --enable
-
-- name: Check if GRUB_CMDLINE_LINUX_DEFAULT exists in /etc/default/grub
-  become: true
-  shell: |
-    set -o pipefail
-    grep "GRUB_CMDLINE_LINUX_DEFAULT=" /etc/default/grub
-  register: test_grep
-  failed_when: false
-
-- name: Add GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub
-  become: true
-  lineinfile:
-    path: /etc/default/grub
-    line: 'GRUB_CMDLINE_LINUX_DEFAULT="fips=1"'
-  when: test_grep.rc != 0
-
-- name: Replace GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub
-  become: true
-  lineinfile:
-    path: /etc/default/grub
-    regexp: 'GRUB_CMDLINE_LINUX_DEFAULT="(.*)"'
-    line: 'GRUB_CMDLINE_LINUX_DEFAULT="\1 fips=1"'
-    backrefs: true
-  when: test_grep.rc == 0
-
-- name: Rebuild grub.cfg file
-  become: true
-  command: grub2-mkconfig -o /boot/grub2/grub.cfg
-
-- name: Reboot server for FIPS mode
-  become: true
-  reboot:
-    reboot_timeout: 1800
-
-- name: Run post-boot tasks
-  include_role:
-    name: post-reboot-tasks
-
-- name: Ensure FIPS mode is enabled
-  become: true
-  command: fips-mode-setup --check
-  register: _result
-
-- name: Assert FIPS is enabled
-  assert:
-    that: _result.stdout == "FIPS mode is enabled."
+- name: Do tasks for Ubuntu
+  include_tasks: ubuntu.yaml
+  when: >
+    (ansible_distribution == "Ubuntu")
diff --git a/roles/enable-fips/tasks/rhel.yaml b/roles/enable-fips/tasks/rhel.yaml
new file mode 100644
index 000000000..ac454ed8e
--- /dev/null
+++ b/roles/enable-fips/tasks/rhel.yaml
@@ -0,0 +1,56 @@
+---
+- name: Install fips-mode-setup
+  become: true
+  package:
+    name: crypto-policies-scripts
+    state: present
+
+- name: Enable FIPS mode
+  become: true
+  command: fips-mode-setup --enable
+
+- name: Check if GRUB_CMDLINE_LINUX_DEFAULT exists in /etc/default/grub
+  become: true
+  shell: |
+    set -o pipefail
+    grep "GRUB_CMDLINE_LINUX_DEFAULT=" /etc/default/grub
+  register: test_grep
+  failed_when: false
+
+- name: Add GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub
+  become: true
+  lineinfile:
+    path: /etc/default/grub
+    line: 'GRUB_CMDLINE_LINUX_DEFAULT="fips=1"'
+  when: test_grep.rc != 0
+
+- name: Replace GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub
+  become: true
+  lineinfile:
+    path: /etc/default/grub
+    regexp: 'GRUB_CMDLINE_LINUX_DEFAULT="(.*)"'
+    line: 'GRUB_CMDLINE_LINUX_DEFAULT="\1 fips=1"'
+    backrefs: true
+  when: test_grep.rc == 0
+
+- name: Rebuild grub.cfg file
+  become: true
+  command: grub2-mkconfig -o /boot/grub2/grub.cfg
+
+- name: Reboot server for FIPS mode
+  become: true
+  reboot:
+    reboot_timeout: 1800
+
+- name: Run post-boot tasks
+  include_role:
+    name: post-reboot-tasks
+
+- name: Ensure FIPS mode is enabled
+  become: true
+  command: fips-mode-setup --check
+  register: _result
+
+- name: Assert FIPS is enabled
+  assert:
+    that: _result.stdout == "FIPS mode is enabled."
diff --git a/roles/enable-fips/tasks/ubuntu.yaml b/roles/enable-fips/tasks/ubuntu.yaml
new file mode 100644
index 000000000..d2137852f
--- /dev/null
+++ b/roles/enable-fips/tasks/ubuntu.yaml
@@ -0,0 +1,31 @@
+- name: Install ua-tools
+  become: true
+  package:
+    name: ubuntu-advantage-tools
+    state: present
+
+- name: Enable fips
+  become: true
+  command: ua enable fips
+
+- name: Verify fips is enabled
+  become: true
+  command: ua status
+
+- name: Reboot server for FIPS mode
+  become: true
+  reboot:
+    reboot_timeout: 1800
+
+- name: Run post-boot tasks
+  include_role:
+    name: post-reboot-tasks
+
+- name: Ensure FIPS mode is enabled
+  become: true
+  command: cat /proc/sys/crypto/fips_enabled
+  register: _result
+
+- name: Assert FIPS is enabled
+  assert:
+    that: _result.stdout == "1"
diff --git a/roles/enable-ua-subscription/README.rst b/roles/enable-ua-subscription/README.rst
new file mode 100644
index 000000000..ee5a24538
--- /dev/null
+++ b/roles/enable-ua-subscription/README.rst
@@ -0,0 +1,13 @@
+Enable UA Subscription on a node.
+
+For Ubuntu nodes, this role activates an Ubuntu advantage
+subscription using a passed in token (ubuntu_ua_token.token).
+
+**Role Variables**
+
+.. zuul:rolevar:: ubuntu_ua_token
+   :type: dict
+   :default: None
+
+   Dict used to specify Ubuntu advantage subscription information.
+   ubuntu_ua_token.token is a subscription key.
diff --git a/roles/enable-ua-subscription/tasks/main.yaml b/roles/enable-ua-subscription/tasks/main.yaml
new file mode 100644
index 000000000..8730258ac
--- /dev/null
+++ b/roles/enable-ua-subscription/tasks/main.yaml
@@ -0,0 +1,12 @@
+- name: Install ua-tools
+  become: true
+  package:
+    name: ubuntu-advantage-tools
+    state: present
+
+- name: Attach subscription
+  command: pro attach --no-auto-enable "{{ ubuntu_ua_token.token }}"
+  become: true
+  no_log: true
+  when: >
+    (ansible_distribution == "Ubuntu")
diff --git a/roles/post-reboot-tasks/README.rst b/roles/post-reboot-tasks/README.rst
index 82e4b694f..53de62df9 100644
--- a/roles/post-reboot-tasks/README.rst
+++ b/roles/post-reboot-tasks/README.rst
@@ -9,6 +9,14 @@ connectivity (ssh), restarting the zuul-console and making sure
 DNS is up.
 
 A role parameter nslookup_target is required to specify the DNS name
-to ensure DNS is working. If working in a mirrored environment, it
-is a good idea to use $zuul_site_mirror_fqdn, because this is what
-will be needed for package installs in any case.
+to ensure DNS is working.
+
+**Role Variables**
+
+.. zuul:rolevar:: nslookup_target
+   :type: str
+   :default: None
+
+   DNS name to query to confirm that DNS is working.  If working in a
+   mirrored environment, it is a good idea to use $zuul_site_mirror_fqdn,
+   because this is what will be needed for package installs in any case.