This plugin adds a second factor to the Horizon Authentication facility using the TOTP protocol.
This plugin was written for our Openstack Cloud back in 2015 (on Openstack Juno) and then more or less abandoned.
The codebase was cleaned up and reworked in 2017 as we updated our Openstack installation to the Mitaka Release and Newton afterwards.
The master branch is developed on top of RDO latest release (currently this is "Ussuri"). The latest environment makes use of:
- RHEL/CentOS 8.x Branch
- Python 3.6+
This version does not depend on external totp libraries and is implemented in pure python: it was developed on RedHat's own Openstack distribution but it shoud work on any openstack horizon dashboard flavor.
The plugin is composed of these modules:
- The Authentication Backend (2fa_auth_plugin folder)
- The Horizon Dashboard (2fa_dashboard_plugin folder)
A management script and library RPM spec is also provided.
These are the basic installation steps for Openstack Horizon:
First you have to build an RPM package from the totp-lib submodule in the git project.
On CentOS 8, set the default interpreter to the local python3 version:
# alternatives --set python /usr/bin/python3
And then build the otp-lib package:
# dnf install -y rpm-build git python-setuptools-wheel python3-setuptools-wheel
# mkdir -p ~/rpmbuild/{SRPMS,RPMS,SOURCES,SPECS} && cd ~/rpmbuild
# git clone https://github.com/mcaimi/python-otp-lib.git python-otp-lib-ussuri
# tar cjvf SOURCES/python-otp-lib-ussuri-1.tar.gz python-otp-lib-ussuri
Now, copy the SPEC file from this repo in ~/rpmbuild/SPECS and build the RPM package:
# rpmbuild -bb SPECS/python-otp-lib-ussuri.spec
If you are on a RedHat/CentOS distro, first install the python-qrcode RPM package, then install the RPM package just built before:
# dnf install -y python3-qrcode python3-qrcode-core
# rpm -ivH python-otp-lib-ussuri-1.x86_64.rpm
On every Horizon node you happen to have deployed in your environment, install the new django dashboard. It will show up under the 'Identity' tab:
# cp -rv 2fa_dashboard_plugin/totp /usr/share/openstack-dashboard/openstack_dashboard/dashboards/identity/
Next the actual auth backend must be put in place:
# mkdir -p /usr/share/openstack-dashboard/openstack_dashboard/auth
# cp -v 2fa_auth_plugin/* /usr/share/openstack-dashboard/openstack_dashboard/auth/
On all horizon nodes, edit /usr/share/openstack-dashboard/openstack_dashboard/settings.py and set this parameters to change the authentication python class used by django:
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
with
AUTHENTICATION_BACKENDS =('openstack_dashboard.auth.backend.TwoFactorAuthBackend',)
also, make sure that these parameters are set:
TOTP_DEBUG = False
TOTP_VALIDITY_PERIOD = 30
Lastly setup these parameters in /etc/openstack-dashboard/local_settings:
# Send email to the console by default
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# Configure these for your outgoing email host
EMAIL_HOST = '<your mail server>'
EMAIL_PORT = <your mail server port>
# Activation email
ACTIVATION_EMAIL_ADDRESS = "noreply@cloud-provider.tld"
ACTIVATION_EMAIL_SUBJECT = "TOTP Activation Message"
Set up keystone policies directory if not already done:
# under /etc/keystone/keystone.conf
policy_dirs = /etc/keystone/policy.d
# create directory
$ mkdir -p /etc/keystone/policy.d
Fix Keystone policies to allow the token owner to update the user on keystone:
# in /etc/openstack-dashboard/keystone_policy.json update the 'identity:update_user' policy to match this:
"identity:update_user": "rule:admin_required or rule:admin_and_matching_target_user_domain_id or rule:owner",
# create a file under /etc/keystone/policy.d called update_user.json and insert these lines inside:
{
"identity:update_user": "rule:admin_required or rule:admin_and_matching_target_user_domain_id or rule:owner"
}
the previous line uses policy.v3cloudsample.json as a base template (see the official keystone GitHub repo for that).
Lastly, enable the dashboard:
# cp -v 2fa_dashboard_plugin/enabled/_3032_identity_totp_panel.py /usr/share/openstack-dashboard/openstack_dashboard/dashboards/enabled/
# restorecon -Rv /usr/share/openstack-dashboard
# systemctl restart httpd
As of now there is no easy way for an user to recover a lost token. Admins can, as a workaround, disable a provisioned token on demand. The totp_disable command is provided for the Django management shell:
$ cp totp_disable.py /usr/share/openstack-dashboard/openstack_dashboard/management/commands/
$ restorecon -Rv /usr/share/openstack-dashboard
This allows for and Admin to disable totp provisioned tokens for single users:
$ cd /usr/share/openstack-dashboard
# source the keystonerc file for the Openstack Admin user
$ source ~/keystonerc-admin
# get the user ID for a particular user
$ openstack user list
+----------------------------------+------------+
| ID | Name |
+----------------------------------+------------+
| d0bd9f7c1f104ed3924b283d63d734d7 | admin |
| 21b26a2d0daa49609510d032e22a5202 | glance |
| a38cbd05a4a04a908b62158c6bb0dc1c | cinder |
| 19e1cfbdf4674a7e9f5796a8135f4da4 | nova |
| 3537c768427d46279c265b87bf1c0413 | placement |
| 77c7fd3cef744d719812d285673c26cd | neutron |
| 6b44bed7a49f40adb10e369f75244f5a | swift |
| 03a010c254e54b43b370c7a200d517df | gnocchi |
| 73d010772e694b159d00935255205f25 | ceilometer |
| 5e576ec671e541939e8b211f4269fb9c | aodh |
| 96e0e23ca7b7499e982f1773ff0330e1 | demouser |
+----------------------------------+------------+
# disable the totp feature for user demouser
$ ./manage.py totp_disable --user-id 96e0e23ca7b7499e982f1773ff0330e1