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. Be sure to source the script, not execute it, otherwise, the environment settings will not persist and it will not work as expected.
#!/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 mechanism:
# 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 mechanism:
$ 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 can generate a QR code.
Here is a Python script to help you with that.
import qrcode
def print_qr_unicode(qr):
matrix = qr.get_matrix()
# Render two rows per terminal line using half-block characters.
for i in range(0, len(matrix), 2):
row_top = matrix[i]
row_bottom = (
matrix[i + 1] if i + 1 < len(matrix) else [False] * len(row_top)
)
line = []
for top, bottom in zip(row_top, row_bottom):
if top and bottom:
line.append("█")
elif top and not bottom:
line.append("▀")
elif not top and bottom:
line.append("▄")
else:
line.append(" ")
print("".join(line))
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
)
)
qr = qrcode.QRCode(border=2)
qr.add_data(uri)
qr.make(fit=True)
img = qr.make_image()
img.save("totp.png")
print(
"Saved QR code image to totp.png (use this if your terminal can't render the blocks)."
)
print_qr_unicode(qr)
Use the following commands to generate your QR code:
mkdir /tmp/totp
cd /tmp/totp
python3 -venv .venv
pip install qrcode
pip install image
python3 totp_script.txt
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
Using the CLI with MFA
You can authenticate against your Public Cloud using YAML configuration files. See the connection tutorial.
Configuring MFA Authentication
Add your cloud configuration to clouds.yaml:
clouds:
public_cloud:
auth_type: "v3multifactor"
auth_methods:
- v3password
- v3totp
auth:
auth_url: $endpoint/v3
username: myuser
user_id: <user-id>
password: <your-password>
Running CLI Commands
Execute commands with your TOTP passcode:
openstack --os-cloud public_cloud --os-passcode 123456 server list -c Name -c Status
If the passcode is missing, you'll see:
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, enable token caching by adding the following to your clouds.yaml file:
cache:
auth: true
Complete example:
clouds:
PCP-XXXXXXX:
auth:
auth_url: https://api.pub1.infomaniak.cloud/identity/v3
project_name: PCP-XXXXXXX
username: PCU-XXXXXXX
password: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
user_domain_name: Default
project_domain_name: Default
region_name: dc3-a
identity_api_version: 3
cache:
auth: true