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. 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

References