Skip to content

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 openstack CLI 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

References