Using TOTP for Multi-Factor Authentication in OpenStack
This guide explains the configuration and usage of Time-based One-Time Passwords (TOTP) with OpenStack Keystone.
Official documentation: Keystone MFA (Multi-Factor Authentication)
TOTP has been tested and validated with OpenStack 6.6.0 and above. Earlier OpenStack versions may encounter issues.
Prerequisites
- An OpenStack user account
- The
openstackCLI installed - A TOTP-compatible app (e.g., FreeOTP, Google Authenticator, Authy, ...)
Generating a TOTP Secret
Here is a helper script to facilitate the setup and use of TOTP:
#!/usr/bin/env bash
source myopenrc.sh
token_info=$(openstack token issue --format json)
OS_USERID=$(echo "$token_info" | jq -r '.user_id')
token=$(echo "$token_info" | jq -r '.id')
endpoint="https://api.pub1.infomaniak.cloud/identity"
TOTPKEY=$(head -c 20 /dev/urandom | base32 | tr -d '=' | cut -c1-32)
oathtool --totp -b "${TOTPKEY}"
openstack credential create \
--type totp \
--project "${OS_PROJECT_ID}" \
"${OS_USERID}" \
"${TOTPKEY}"
Activate the TOTP mecanism:
# Activate the TOTP
$ openstack user set --multi-factor-auth-rule password,totp $OS_USERID
$ openstack user set --enable-multi-factor-auth $OS_USERID
Test that it works:
# Test a simple command with the TOTP activated
$ openstack server list
Not all required auth rules were satisfied: [['password', 'totp']]
$ openstack --os-auth-type v3multifactor --os-auth-methods v3password,v3totp --os-passcode $(oathtool --totp -b "${TOTPKEY}") project list
Password:
+----------------------------------+-------------------+
| ID | Name |
+----------------------------------+-------------------+
| 3e6c6bf32ce6431f909024df4a0c8a73 | totp-test-project |
+----------------------------------+-------------------+
How to disable the TOTP mecanism:
$ openstack --os-auth-type v3multifactor --os-auth-methods v3password,v3totp --os-passcode $(oathtool --totp -b "${TOTPKEY}") user set --disable-multi-factor-auth $OS_USERID
$ openstack project list
+----------------------------------+-------------------+
| ID | Name |
+----------------------------------+-------------------+
| 3e6c6bf32ce6431f909024df4a0c8a73 | totp-test-project |
+----------------------------------+-------------------+
Enrolling in a TOTP App
To easily add a new secret to your TOTP app, you generate a QR code.
First, install the qrcode package:
sudo apt install python3-qrcode
Then, run the following Python script:
import qrcode
secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # Use the secret generated in the previous step (the Base64-encoded string)
uri = 'otpauth://totp/infomaniak-public-cloud?secret={}&issuer=Keystone'.format(secret)
img = qrcode.make(uri)
img.save('totp.png')
Scan the generated totp.png file using your TOTP app (e.g., FreeOTP, Google Authenticator, Authy, ...).
You can also directly get the TOTP code with the oathtool:
$ oathtool --totp -b $TOTPKEY
556557
Authenticating Using TOTP
Request a token using the passcode:
curl -i -H "Content-Type: application/json" -d '{ "auth": { "identity": { "methods": [ "totp" ], "totp": { "user": { "id": "<user-id>", "passcode": "123456" } } } } }' $endpoint/v3/auth/tokens
Response: HTTP/1.1 201 CREATED The token is in the X-Subject-Token header.
Using the CLI with MFA
Example clouds.yaml entry:
clouds:
public_cloud:
auth_type: "v3multifactor"
auth_methods:
- v3password
- v3totp
auth:
auth_url: $endpoint/v3
username: myuser
user_id: <user-id>
password: <your-password>
Use with:
openstack --os-cloud public_cloud --os-passcode 123456 server list -c Name -c Status
If the passcode is missing:
openstack server list
Not all required auth rules were satisfied: [['totp', 'password']]
Caching the Token (Optional)
To avoid entering the TOTP passcode for every command, add the following to your clouds.yaml file:
cache:
auth: true