os-mfa


Nameos-mfa JSON
Version 0.4.2 PyPI version JSON
download
home_page
SummaryA minimal utility for managing cli authentication with openstack more securely and conveniently
upload_time2023-05-07 05:34:44
maintainer
docs_urlNone
author
requires_python>=3.6
license
keywords openstack mfa auth
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # os-mfa

Convenient and secure OpenStack authentication and credential management inspired by [broamski/aws-mfa](https://github.com/broamski/aws-mfa)

## What 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](https://docs.openstack.org/newton/user-guide/common/cli-set-environment-variables-using-openstack-rc.html)**

* 🛡️ 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](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#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 using `clouds.yaml` and 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 start

Install os-mfa

```bash
pip install -U os-mfa
```

Download `clouds.yaml` file from your OpenStack dashboard. For example

 1. Click **[API Access](https://dashboard.catalystcloud.nz/project/api_access/)** from the top left of the dashboard
 2. Click **Download OpenStack RC File** on the top right
 3. Select **OpenStack clouds.yaml File** from the drop down

Place the file in your current working directory (`.`) or an alternate [location described by the docs](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#clouds-yaml)

Linux
  * `~/.config/openstack/clouds.yaml`
  * `/etc/openstack/clouds.yaml`

Windows
  * `C:\Users\<username>\.config\openstack\clouds.yaml`
  * `C:\ProgramData\openstack\clouds.yaml`

E.g.

```yaml
# /home/john/clouds.yaml
clouds:
  catalystcloud:
    auth:
      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000
      project_id: 33735662374f4b7a9621631f2e7e5e15
      project_name: acme-incorporated
      user_domain_name: Default
      username: john.smith@acme.com
      password: 1ns3curE123!
    identity_api_version: 3
    interface: public
    region_name: nz-hlz-1
```

Set `$OS_CLOUD` in your environment.

```bash
$ export OS_CLOUD=catalystcloud
```

Run `os-mfa`

```bash
$ os-mfa
Authenticating 'john.smith@example.com' in project 'john-smith'
Enter Password:
MFA Code (Press enter to skip): 654321
Getting token...
```

```
$ 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_CLOUD` again.

```bash
export OS_CLOUD=catalystcloud
```

## What 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 should *not* contain any secrets such as tokens or passwords.
 * They are distinguished by a suffix of `-long-term`

os-mfa will then use the `-long-term` configuration to create a token based configuration as follows.

 1. Prompts the user for their password and MFA code
 2. Swaps the password and MFA code for an OpenStack auth token
 3. Updates the original configuration to use the new token for authentication

The resulting clouds.yaml should look like this

```yaml
# /home/john/clouds.yaml
clouds:
  catalystcloud:
    auth:
      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000
      project_id: 33735662374f4b7a9621631f2e7e5e15
      project_name: acme-incorporated
      token: gAAAAABkTkGx4Dah37lkiGTSEe3-r[...]9dQCVTBRsKjg6NFIYgMYRdAk7TTvIPOaaOE
    identity_api_version: 3
    interface: public
    region_name: nz-hlz-1
  catalystcloud-long-term:
    auth:
      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000
      project_id: 33735662374f4b7a9621631f2e7e5e15
      project_name: acme-incorporated
      user_domain_name: Default
      username: john.smith@acme.com
    identity_api_version: 3
    interface: public
    region_name: nz-hlz-1

```

## Going further

### Multiple projects, users and sessions


Since clouds.yaml supports multiple configurations, you can create configurations for any combination of

 * user
 * project
 * region
 * openstack cloud

```yaml
clouds:
  project1:
    region: nz-hlz-1
    auth:
        project_name: project1
        username: john.smith@acme.com
        # ...
  project2:
    region: nz-por-1
    auth:
        project_name: project2
        username: john.smith@acme.com
        # ...
```

After initializing a token based authentication for each configuration using os-mfa, you can change between sessions at will

```bash
OS_CLOUD=project1
```
```bash
OS_CLOUD=project2
```

## Contributing

Nothing special to report, just raise a PR

### Run tests

```
python -m unittest discover
```

### Building Package

Source: 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

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "os-mfa",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "openstack,mfa,auth",
    "author": "",
    "author_email": "Simon Merrick <s.m3rrick@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/a7/4f/c43c714541df986e8e6e6db13eb33538cc9a33d760713258e409db9d257f/os-mfa-0.4.2.tar.gz",
    "platform": null,
    "description": "# os-mfa\n\nConvenient and secure OpenStack authentication and credential management inspired by [broamski/aws-mfa](https://github.com/broamski/aws-mfa)\n\n## What problem does os-mfa solve?\n\nFirst some quick background. OpenStack provides two main methods of setting credentials for programmatic authentication:\n\n**A) [Environment variables set via 'openrc.sh' files](https://docs.openstack.org/newton/user-guide/common/cli-set-environment-variables-using-openstack-rc.html)**\n\n* \ud83d\udee1\ufe0f Avoids storing passwords in plaintext on disk \ud83d\udc4d\n* \ud83e\udd26 Session credentials are lost if you close or restart your terminal window \ud83d\udc4e\n* \ud83d\udd12 Sessions can't be shared/accessed across multiple terminal sessions \ud83d\udc4e\n* \ud83d\udc94 Not compatible with windows clients \ud83d\udc4e\n\n**B) [clouds.yaml configuration files](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#configuration-files)**\n\n * \ud83d\udcaa Session tokens are durable to terminal restarts/shutdowns \ud83d\udc4d\n * \ud83d\udc97 Compatible and consistent user experience across platforms \ud83d\udc4d\n * \ud83c\udf0f OpenStack sessions are accessible in from any terminal session \ud83d\udc4d\n * \ud83d\ude48 Encourages credentials to be stored in plain text \ud83d\udc4e\n * \u231b Tokens that expire after 12 hours need to be manually refreshed and updated in clouds.yaml \ud83d\udc4e\n\nAs we can see both have advantages and disadvantages. But what if we could have the best parts of both options?\n\n**\ud83c\udf08 os-mfa \ud83e\udd84 leverages the convenience and durability of using `clouds.yaml` and automates the secure management of credentials and tokens**\n\n * \ud83d\udee1\ufe0f Avoids storing passwords in plaintext on disk \ud83d\udc4d\n * \ud83d\udcaa Session tokens are durable to terminal restarts/shutdowns \ud83d\udc4d\n * \ud83d\udc97 Compatible and consistent user experience across platforms \ud83d\udc4d\n * \ud83c\udf0f OpenStack sessions are accessible in from any terminal session \ud83d\udc4d\n * \ud83d\udd00 Trivially switch between multiple authenticated OpenStack sessions \ud83d\udc4d\n * \ud83e\udd1d Ensured compatibility with the OpenStack ecosystem \ud83d\udc4d\n\n## Quick start\n\nInstall os-mfa\n\n```bash\npip install -U os-mfa\n```\n\nDownload `clouds.yaml` file from your OpenStack dashboard. For example\n\n 1. Click **[API Access](https://dashboard.catalystcloud.nz/project/api_access/)** from the top left of the dashboard\n 2. Click **Download OpenStack RC File** on the top right\n 3. Select **OpenStack clouds.yaml File** from the drop down\n\nPlace the file in your current working directory (`.`) or an alternate [location described by the docs](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#clouds-yaml)\n\nLinux\n  * `~/.config/openstack/clouds.yaml`\n  * `/etc/openstack/clouds.yaml`\n\nWindows\n  * `C:\\Users\\<username>\\.config\\openstack\\clouds.yaml`\n  * `C:\\ProgramData\\openstack\\clouds.yaml`\n\nE.g.\n\n```yaml\n# /home/john/clouds.yaml\nclouds:\n  catalystcloud:\n    auth:\n      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000\n      project_id: 33735662374f4b7a9621631f2e7e5e15\n      project_name: acme-incorporated\n      user_domain_name: Default\n      username: john.smith@acme.com\n      password: 1ns3curE123!\n    identity_api_version: 3\n    interface: public\n    region_name: nz-hlz-1\n```\n\nSet `$OS_CLOUD` in your environment.\n\n```bash\n$ export OS_CLOUD=catalystcloud\n```\n\nRun `os-mfa`\n\n```bash\n$ os-mfa\nAuthenticating 'john.smith@example.com' in project 'john-smith'\nEnter Password:\nMFA Code (Press enter to skip): 654321\nGetting token...\n```\n\n```\n$ openstack network list\n+--------------------------------------+------------+--------------------------------------------+\n| ID                                   | Name       | Subnets                                    |\n+--------------------------------------+------------+--------------------------------------------+\n| f10ad6de-a26d-4c29-8c64-2a7418d47f8f | public-net | 5063aab1-aa08-48b2-b81d-730ac732fc51,      |\n|                                      |            | 8a7fe804-7fbe-43d0-aa1d-cfa03034ef22,      |\n|                                      |            | a1549e09-4176-4322-860c-cadc68608b48       |\n+--------------------------------------+------------+--------------------------------------------+\n```\n\nNow if you close/restart or start a new terminal window, resume your existing OpenStack session simply by exporting `$OS_CLOUD` again.\n\n```bash\nexport OS_CLOUD=catalystcloud\n```\n\n## What happened when we ran os-mfa?\n\nThe first time we run os-mfa is creates a *\"long-term\"* configuration in our clouds.yaml without any passwords or secrets.\n\nLong term configurations contain the minimum information required for os-mfa to use to initialize a token based authentication.\n\n * They should *not* contain any secrets such as tokens or passwords.\n * They are distinguished by a suffix of `-long-term`\n\nos-mfa will then use the `-long-term` configuration to create a token based configuration as follows.\n\n 1. Prompts the user for their password and MFA code\n 2. Swaps the password and MFA code for an OpenStack auth token\n 3. Updates the original configuration to use the new token for authentication\n\nThe resulting clouds.yaml should look like this\n\n```yaml\n# /home/john/clouds.yaml\nclouds:\n  catalystcloud:\n    auth:\n      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000\n      project_id: 33735662374f4b7a9621631f2e7e5e15\n      project_name: acme-incorporated\n      token: gAAAAABkTkGx4Dah37lkiGTSEe3-r[...]9dQCVTBRsKjg6NFIYgMYRdAk7TTvIPOaaOE\n    identity_api_version: 3\n    interface: public\n    region_name: nz-hlz-1\n  catalystcloud-long-term:\n    auth:\n      auth_url: https://api.nz-hlz-1.catalystcloud.io:5000\n      project_id: 33735662374f4b7a9621631f2e7e5e15\n      project_name: acme-incorporated\n      user_domain_name: Default\n      username: john.smith@acme.com\n    identity_api_version: 3\n    interface: public\n    region_name: nz-hlz-1\n\n```\n\n## Going further\n\n### Multiple projects, users and sessions\n\n\nSince clouds.yaml supports multiple configurations, you can create configurations for any combination of\n\n * user\n * project\n * region\n * openstack cloud\n\n```yaml\nclouds:\n  project1:\n    region: nz-hlz-1\n    auth:\n        project_name: project1\n        username: john.smith@acme.com\n        # ...\n  project2:\n    region: nz-por-1\n    auth:\n        project_name: project2\n        username: john.smith@acme.com\n        # ...\n```\n\nAfter initializing a token based authentication for each configuration using os-mfa, you can change between sessions at will\n\n```bash\nOS_CLOUD=project1\n```\n```bash\nOS_CLOUD=project2\n```\n\n## Contributing\n\nNothing special to report, just raise a PR\n\n### Run tests\n\n```\npython -m unittest discover\n```\n\n### Building Package\n\nSource: https://realpython.com/pypi-publish-python-package/\n\n```\npython -m pip install pip-tools twine\npip-compile pyproject.toml\nrm -rf dist/*\npython -m build\ntwine check dist/*\ntwine upload -r testpypi dist/*\ntwine upload dist/*\n```\n\n## TODO\n\n * \u2611\ufe0f TBH I am probably going to port this back to python\n * \u2611\ufe0f Alert if no clouds.yaml found\n * \u2611\ufe0f Better error message if OS_CLOUD not set\n * \ud83d\udfe6 CI/CD\n * \ud83d\udfe6 Optionally disable prompt for MFA token\n * \ud83d\udfe6 Store and check expiry of token\n * \ud83d\udfe6 Only reauthenticate if token is not valid\n * \ud83d\udfe6 -f, --force cli option to force authentication\n * \ud83d\udfe6 more unit and integration tests\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "A minimal utility for managing cli authentication with openstack more securely and conveniently",
    "version": "0.4.2",
    "project_urls": {
        "Homepage": "https://github.com/iokiwi/os-mfa"
    },
    "split_keywords": [
        "openstack",
        "mfa",
        "auth"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "be26488f14e3d7e22f51a584078ed94ac93306f85fd2349f0a72573258859471",
                "md5": "16f0a20df2c916f1dad5535a9c0ac853",
                "sha256": "c449d6fadd36bd3e525c633e65163e71ca4110de1d1409cd71bb33110e1d88d6"
            },
            "downloads": -1,
            "filename": "os_mfa-0.4.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "16f0a20df2c916f1dad5535a9c0ac853",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 8634,
            "upload_time": "2023-05-07T05:34:40",
            "upload_time_iso_8601": "2023-05-07T05:34:40.856661Z",
            "url": "https://files.pythonhosted.org/packages/be/26/488f14e3d7e22f51a584078ed94ac93306f85fd2349f0a72573258859471/os_mfa-0.4.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a74fc43c714541df986e8e6e6db13eb33538cc9a33d760713258e409db9d257f",
                "md5": "577f2698eddb91d69077a7dfeb1012f3",
                "sha256": "dfc9373ced3da081f693ee57477d54dba07cec8648dca77fda4c61f7becb1664"
            },
            "downloads": -1,
            "filename": "os-mfa-0.4.2.tar.gz",
            "has_sig": false,
            "md5_digest": "577f2698eddb91d69077a7dfeb1012f3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 8742,
            "upload_time": "2023-05-07T05:34:44",
            "upload_time_iso_8601": "2023-05-07T05:34:44.560581Z",
            "url": "https://files.pythonhosted.org/packages/a7/4f/c43c714541df986e8e6e6db13eb33538cc9a33d760713258e409db9d257f/os-mfa-0.4.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-07 05:34:44",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "iokiwi",
    "github_project": "os-mfa",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "os-mfa"
}
        
Elapsed time: 0.07187s