Package: os-mfa
os-mfaConvenient and secure OpenStack authentication and credential management inspired bybroamski/aws-mfaWhat problem does os-mfa solve?First some quick background. OpenStack provides two main methods of setting credentials for programmatic authentication:A)Environment variables set via 'openrc.sh' files🛡️ Avoids storing passwords in plaintext on disk 👍🤦 Session credentials are lost if you close or restart your terminal window 👎🔒 Sessions can't be shared/accessed across multiple terminal sessions 👎💔 Not compatible with windows clients 👎B)clouds.yaml configuration files💪 Session tokens are durable to terminal restarts/shutdowns 👍💗 Compatible and consistent user experience across platforms 👍🌏 OpenStack sessions are accessible in from any terminal session 👍🙈 Encourages credentials to be stored in plain text 👎⌛ Tokens that expire after 12 hours need to be manually refreshed and updated in clouds.yaml 👎As we can see both have advantages and disadvantages. But what if we could have the best parts of both options?🌈 os-mfa 🦄 leverages the convenience and durability of usingclouds.yamland automates the secure management of credentials and tokens🛡️ Avoids storing passwords in plaintext on disk 👍💪 Session tokens are durable to terminal restarts/shutdowns 👍💗 Compatible and consistent user experience across platforms 👍🌏 OpenStack sessions are accessible in from any terminal session 👍🔀 Trivially switch between multiple authenticated OpenStack sessions 👍🤝 Ensured compatibility with the OpenStack ecosystem 👍Quick startInstall os-mfapipinstall-Uos-mfaDownloadclouds.yamlfile from your OpenStack dashboard. For exampleClickAPI Accessfrom the top left of the dashboardClickDownload OpenStack RC Fileon the top rightSelectOpenStack clouds.yaml Filefrom the drop downPlace the file in your current working directory (.) or an alternatelocation described by the docsLinux~/.config/openstack/clouds.yaml/etc/openstack/clouds.yamlWindowsC:\Users\<username>\.config\openstack\clouds.yamlC:\ProgramData\openstack\clouds.yamlE.g.# /home/john/clouds.yamlclouds:catalystcloud:auth:auth_url:https://api.nz-hlz-1.catalystcloud.io:5000project_id:33735662374f4b7a9621631f2e7e5e15project_name:acme-incorporateduser_domain_name:Defaultusername:john.smith@acme.compassword:1ns3curE123!identity_api_version:3interface:publicregion_name:nz-hlz-1Set$OS_CLOUDin your environment.$exportOS_CLOUD=catalystcloudRunos-mfa$os-mfa
Authenticating'john.smith@example.com'inproject'john-smith'EnterPassword:
MFACode(Pressentertoskip):654321Gettingtoken...$ openstack network list
+--------------------------------------+------------+--------------------------------------------+
| ID                                   | Name       | Subnets                                    |
+--------------------------------------+------------+--------------------------------------------+
| f10ad6de-a26d-4c29-8c64-2a7418d47f8f | public-net | 5063aab1-aa08-48b2-b81d-730ac732fc51,      |
|                                      |            | 8a7fe804-7fbe-43d0-aa1d-cfa03034ef22,      |
|                                      |            | a1549e09-4176-4322-860c-cadc68608b48       |
+--------------------------------------+------------+--------------------------------------------+Now if you close/restart or start a new terminal window, resume your existing OpenStack session simply by exporting$OS_CLOUDagain.exportOS_CLOUD=catalystcloudWhat happened when we ran os-mfa?The first time we run os-mfa is creates a"long-term"configuration in our clouds.yaml without any passwords or secrets.Long term configurations contain the minimum information required for os-mfa to use to initialize a token based authentication.They shouldnotcontain any secrets such as tokens or passwords.They are distinguished by a suffix of-long-termos-mfa will then use the-long-termconfiguration to create a token based configuration as follows.Prompts the user for their password and MFA codeSwaps the password and MFA code for an OpenStack auth tokenUpdates the original configuration to use the new token for authenticationThe resulting clouds.yaml should look like this# /home/john/clouds.yamlclouds:catalystcloud:auth:auth_url:https://api.nz-hlz-1.catalystcloud.io:5000project_id:33735662374f4b7a9621631f2e7e5e15project_name:acme-incorporatedtoken:gAAAAABkTkGx4Dah37lkiGTSEe3-r[...]9dQCVTBRsKjg6NFIYgMYRdAk7TTvIPOaaOEidentity_api_version:3interface:publicregion_name:nz-hlz-1catalystcloud-long-term:auth:auth_url:https://api.nz-hlz-1.catalystcloud.io:5000project_id:33735662374f4b7a9621631f2e7e5e15project_name:acme-incorporateduser_domain_name:Defaultusername:john.smith@acme.comidentity_api_version:3interface:publicregion_name:nz-hlz-1Going furtherMultiple projects, users and sessionsSince clouds.yaml supports multiple configurations, you can create configurations for any combination ofuserprojectregionopenstack cloudclouds:project1:region:nz-hlz-1auth:project_name:project1username:john.smith@acme.com# ...project2:region:nz-por-1auth:project_name:project2username:john.smith@acme.com# ...After initializing a token based authentication for each configuration using os-mfa, you can change between sessions at willOS_CLOUD=project1OS_CLOUD=project2ContributingNothing special to report, just raise a PRRun testspython -m unittest discoverBuilding PackageSource:https://realpython.com/pypi-publish-python-package/python -m pip install pip-tools twine
pip-compile pyproject.toml
rm -rf dist/*
python -m build
twine check dist/*
twine upload -r testpypi dist/*
twine upload dist/*TODO☑️ TBH I am probably going to port this back to python☑️ Alert if no clouds.yaml found☑️ Better error message if OS_CLOUD not set🟦 CI/CD🟦 Optionally disable prompt for MFA token🟦 Store and check expiry of token🟦 Only reauthenticate if token is not valid🟦 -f, --force cli option to force authentication🟦 more unit and integration tests