Skip to main content

A client auth library for Anaconda.cloud APIs

Project description

anaconda-cloud-auth

A client library for Anaconda.cloud APIs to authenticate and securely store API keys. This library is used by other Anaconda.cloud client packages to provide a centralized auth capability for the ecosystem. You will need to use this package to login to Anaconda.cloud before utilizing many of the other client packages.

This package provides a requests client class that handles loading the API key for requests made to Anaconda Cloud services.

This package provides a Panel OAuth plugin called anaconda_cloud.

Installation

conda install anaconda-cloud-auth

Usage

The primary usage of this package is to provide CLI actions for login, logout, user information, and api-keys to Anaconda Cloud API Services.

❯ anaconda cloud

 Usage: anaconda cloud [OPTIONS] COMMAND [ARGS]...

 Anaconda.cloud auth commands

╭─ Options ──────────────────────────────────────────────────────────────────────────────────╮
│ --version  -V                                                                              │
│ --help               Show this message and exit.                                           │
╰────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────────────────╮
│ api-key   Display API Key for signed-in user                                               │
│ login     Login                                                                            │
│ logout    Logout                                                                           │
│ whoami    Display information about the currently signed-in user                           │
╰────────────────────────────────────────────────────────────────────────────────────────────╯

Configuration

You can configure anaconda-cloud-auth by either

  1. Setting parameters in the plugin.cloud section of the ~/.anaconda/config.toml file
  2. Setting one or more ANACONDA_CLOUD_ environment variables or use a .env file in your working directory

ANACONDA_CLOUD_ env vars or .env file take precedence over the ~/.anaconda/config.toml file.

Anaconda Cloud parameters

The following parameters in the plugin.cloud section control the login actions and API requests to Anaconda Cloud Services.

Parameter Env variable Description Default value
domain ANACONDA_CLOUD_DOMAIN Authentication and API request domain "anaconda.cloud"
ssl_verify ANACONDA_CLOUD_SSL_VERIFY SSL verification for all requests True
preferred_token_storage ANACONDA_CLOUD_PREFERRED_TOKEN_STORAGE Where to store the login token, can be "anaconda-keyring" or "system" "anaconda-keyring"
api_key ANACONDA_CLOUD_API_KEY API key, if None defaults to keyring storage None
extra_headers ANACONDA_CLOUD_EXTRA_HEADERS Extra request headers in JSON format None

Example

Here's an example ~/.anaconda/config.toml where SSL verification is turned off for login and API requests and the preferred token storage is anaconda-keyring.

[plugin.cloud]
ssl_verify = false
preferred_token_storage = "system"

API Keys and tokens

When you login with anaconda-cloud-auth an auth token is stored in the preferred keyring storage location and is deleted when you run logout. The auth token will need to be renewed once a year.

The preferred_storage configuration parameter in the plugin.cloud section of the config.toml file takes two possible values

Storage location Description
"system" Use the system keyring if available, otherwise use anaconda-keyring
"anaconda-keyring" A file-based keyring at ~/.anaconda/keyring

"anaconda-keyring" is the default value.

Non-interactive use

If you want to utilize Anaconda Cloud Services on a system where you do not have interactive access to a browser to use the login command you have two options

  1. Use anaconda cloud api-key command on a system where you can login to print the API key to the terminal. You can then utilize the API key on the non-interactive system with the ANACONDA_CLOUD_API_KEY env var (or in .env file) or set the key parameter in the plugin.cloud_api section of the ~/.anaconda/config.toml file.
  2. With preferred_token_storage set to "anaconda-keyring" run the login command to create the ~/.anaconda/keyring file. Then copy ~/.anaconda/keyring to the non-interactive system.

Python API

from anaconda_cloud_auth import login

login()

The login() function initiates a browser-based login flow. It will automatically open your browser and once you have completed the login flow it will store an API key on your system.

Typically, these API keys will have a one year expiration so you will only need to login once and requests using the client class will read the token from the keyring storage.

If you call login() while there is a valid (non-expired) API key no action is taken. You can replace the valid API key with login(force=True).

To remove the API key from your keyring storage use the logout() function.

from anaconda_cloud_auth import logout

logout()

API requests

The BaseClient class is a subclass of requests.Session. It will attempt load the API key from the keyring on each request unless overridden by the api_key argument.

The BaseClient class can be used for non-authenticated requests even when the user has not logged in or provided an API in the request.

from anaconda_cloud_auth.client import BaseClient

client = BaseClient()

response = client.get("/api/<endpoint>")
response.raise_for_status()
print(response.json())

BaseClient accepts the following optional arguments.

  • domain: Domain to use for requests, defaults to anaconda.cloud
  • ssl_verify: Enable SSL verification, defaults to True
  • api_key: API key to use for requests, if unspecified uses token set by anaconda login
  • user_agent: Defaults to anaconda-cloud-auth/<package-version>
  • api_version: Requested API version, defaults to latest available from the domain
  • extra_headers: Dictionary or JSON string of extra headers to send in requests

To create a Client class specific to your package, subclass BaseClient and set an appropriate user-agent and API version for your needs. This is automatically done if you use the cookiecutter in this repository to create a new package.

from anaconda_cloud_auth.client import BaseClient
class Client(BaseClient):
    _user_agent = "anaconda-cloud-<package>/<version>"
    _api_version = "<api-version>"

CLI Error handlers

This plugin defines an error handler for the HTTPError exception when using .raise_for_status() on a response using BaseClient or subclasses of BaseClient. Errors are not caught automatically when using the BaseClient or subclasses outside of anaconda CLI subcommands.

Login required

For the following cases if running the CLI command interactively the user is asked if they wish to continue with interactive login. Once completed the command will be re-tried.

  • TokenNotFoundError: The subcommand requested to load the token from the keyring but none were present
  • TokenExpiredError: The token was successfully loaded but has expired
  • AuthenticationMissing: Derived from requests.exceptions.HTTPError, the request was made without an API key or token to an endpoint that requires authentication.
  • InvalidAuthentication: Derived from requests.exceptions.HTTPError, the request was made using an API key or token but Anaconda Cloud determines that the API was invalid

Here's an example demonstrating that the user has not previously run anaconda login but attempted a CLI command that at some point requires authentication. By typing y the login action is triggered and their browser will open.

❯ anaconda cloud api-key
TokenNotFoundError: Login is required to complete this action.
Continue with interactive login? [y/n]: y
<api-key>

If the user typed n or the command was not run on an interactive terminal an error message is shown instructing the user how to login or configure the API key.

❯ anaconda cloud whoami
AuthenticationMissingError: Login is required to complete this action.
Continue with interactive login? [y/n]: n

To configure your credentials you can run
  anaconda login --at cloud

or set your API key using the ANACONDA_CLOUD_API_KEY env var

or set

[plugin.cloud]
api_key = "<api-key>"

in ~/.anaconda/config.toml

To see a more detailed error message run the command again as
  anaconda --verbose cloud whoami

HTTPError

In addition to the two special cases above all HTTPError exceptions thrown during CLI subcommands will be handled to provide the error code and reason.

For example a subcommand using BaseClient or a subclass of it may make a bad request.

@plugin.subcommand('do-something')
def do_something(inputs: Annotated[Any, typer.Argument()]):
    client = Client()
    res = client.post('api/something', data=inputs)
    res.raise_for_status()

For this example subcommand the user may provide incorrect inputs that are passed to the endpoint. By using .raise_for_status() the error is passed along to the CLI user and a short response is printed.

> anaconda plugin do-something 'input-data'
HTTPError: 422 Client Error: Unprocessable Entity for url: https://anaconda.cloud/api/something

To see a more detailed error message run the command again as
  anaconda --verbose plugin do-something

Panel OAuth Provider

In order to use the anaconda_cloud auth plugin you will need an OAuth client ID (key) and secret. The client must be configured as follows

Set scopes: offline_access, openid, email, profile
Set redirect url to http://localhost:5006
Set grant type: Authorization Code
Set response types: ID Token, Token, Code
Set access token type: JWT
Set Authentication Method: HTTP Body

To run the app with the anaconda_cloud auth provider you will need to set several environment variables or command-line arguments. See the Panel OAuth documentation for more details

PANEL_OAUTH_PROVIDER=anaconda_cloud or --oauth-provider anaconda_cloud
PANEL_OAUTH_KEY=<key>               or --oauth-key=<key>
PANEL_OAUTH_SECRET=<secret>         or --oauth-secret=<key>
PANEL_COOKIE_SECRET=<cookie-name>   or --cookie-secret=<value>
PANEL_OAUTH_REFRESH_TOKENS=1        or --oauth-refresh-tokens
PANEL_OAUTH_OPTIONAL=1              or --oauth-optional
panel serve <arguments> ...

If you do not specify the .env file, the production configuration should be the default. Please file an issue if you see any errors.

Setup for development

Ensure you have conda installed. Then run:

make setup

Run the unit tests

make test

Run the unit tests across isolated environments with tox

make tox

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anaconda_cloud_auth-0.7.0.tar.gz (36.4 kB view hashes)

Uploaded Source

Built Distribution

anaconda_cloud_auth-0.7.0-py3-none-any.whl (26.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page