anaconda-auth#
A client library for Anaconda APIs to authenticate and securely store API keys. This library is used by other client packages to provide a centralized auth capability for the ecosystem. You will need to use this package to log in to anaconda.com 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 services.
This package provides a Panel OAuth plugin
called anaconda_auth.
Installation#
conda install anaconda-auth
Usage#
The primary usage of this package is to provide CLI actions for login, logout, user information, and api-keys to Anaconda API Services.
❯ anaconda auth
Usage: anaconda auth [OPTIONS] COMMAND [ARGS]...
Anaconda 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 │
╰────────────────────────────────────────────────────────────────────────────────────────────╯
Change site#
To change the default site for all anaconda CLI plugins you can run
anaconda sites add --name <site-name> --domain <domain> --default [extra-flags]
For the list of extra flags see the next section. This will edit your ~/.anaconda/config.toml.
Configuration#
You can configure anaconda-auth by either:
Setting parameters in the
plugin.authsection of the~/.anaconda/config.tomlfile.Setting one or more sites in the
[sites.<name>]section of the~/.anaconda/config.tomlfile.Setting one or more
ANACONDA_AUTH_environment variables or using a.envfile in your working directory.
ANACONDA_AUTH_ env vars or a .env file take precedence over the ~/.anaconda/config.toml file.
Anaconda parameters#
The following parameters in the plugin.auth section control the login actions and API requests to Anaconda Services.
Parameter |
Env variable |
Description |
Default value |
|---|---|---|---|
|
|
Authentication and API request domain |
|
|
|
SSL verification for all requests |
|
|
|
Where to store the login token; can be |
|
|
|
API key; if |
|
|
|
Extra request headers in JSON format |
|
|
|
Configures |
|
|
|
Configures |
|
|
|
Disable automatic configuration of conda’s |
|
Example#
Here’s an example ~/.anaconda/config.toml where SSL verification is turned
off for login and API requests and where the preferred token storage is anaconda-keyring.
[plugin.auth]
ssl_verify = false
preferred_token_storage = "system"
Multi-site configuration#
This plugin supports configuration of multiple sites for use with
anaconda login and BaseClient. Each of the above parameters can be
set within a [sites.<name>] table within ~/.anaconda/config.toml.
For example
[sites.on-prem]
domain = "my.site.foo.com"
ssl_verify = false
When utilizing a site with BaseClient(site="<name>") the global
[plugin.auth] table acts as a fallback, the site config will utilize any value in [plugin.auth] that is not explicitly overridden in the [sites] table. Finally, all value of any configured site can be overridden with the ANACONDA_AUTH_* env vars above.
You can have any number of this tables within the config file. To set
a site as default use default_site = "<name>" where the <name> is the
name of one of the sites tables. For example, you can have an extra
site in addition to the default anaconda.com site make it the default
for BaseClient() and CLI operations.
default_site = "on-prem"
[sites."anaconda.com"]
# Empty table means use default values
[sites.on-prem]
domain = "my.site.foo.com"
ssl_verify = false
CLI commands#
A top-level --at <site-name> flag is added to all anaconda CLI commands to switch the site.
anaconda --at <site-name> <cmd> [flags]
This works across all Anaconda CLI plugins and subcommands.
Multi-site configuration can be controlled using the anaconda sites
subcommand to list, add, modify, and remove sites.
❯ anaconda sites
Usage: anaconda sites [OPTIONS] COMMAND [ARGS]...
Manage your Anaconda site configuration
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────╮
│ --help -h Show this message and exit. │
╰───────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ────────────────────────────────────────────────────────────────────────────────────╮
│ list List configured sites by name and domain. │
│ show Show the site configuration for the default site or look up by the provided name or │
│ domain. │
│ add Add new site configuration to ~/.anaconda/config.toml │
│ modify Modify site configuration in ~/.anaconda/config.toml │
│ remove Remove site configuration by name or domain. │
╰───────────────────────────────────────────────────────────────────────────────────────────────╯
API Keys and tokens#
When you login with anaconda-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.auth section of the config.toml file takes two
possible values:
Storage location |
Description |
|---|---|
|
Use the system keyring, if available. Otherwise, use |
|
A file-based keyring at |
"anaconda-keyring" is the default value.
Non-interactive use#
If you want to utilize Anaconda Services on a system where you do not have interactive access to a browser to
use the login command, you have two options:
On a system where you can log in, use
anaconda auth api-keycommand to print the API key to the terminal. You can then utilize the API key on the non-interactive system with theANACONDA_AUTH_API_KEYenv var (or in a.envfile) or set thekeyparameter in theplugin.authsection of the~/.anaconda/config.tomlfile.With
preferred_token_storageset to"anaconda-keyring", run thelogincommand to create the~/.anaconda/keyringfile. Then, copy~/.anaconda/keyringto the non-interactive system.
Python API#
from anaconda_auth import login
login()
The login() function initiates a browser-based login flow for your
default site. It will automatically
open your browser and, once you have completed the login flow, it will store an
API key on your system.
login() takes an optional keyword argument site="<name or domain>"
to login to another configured site in your ~/.anaconda/config.toml.
Typically, these API keys will have a one year expiration, so you will only need to log in 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_auth import logout
logout()
logout() takes an optional keyword argument site="<name or domain>"
to logout from another configured site in your ~/.anaconda/config.toml.
Without the site= argument the default site from your configuration is
used.
API requests#
The BaseClient class is a subclass of requests.Session.
It will attempt to 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_auth.client import BaseClient
client = BaseClient()
response = client.get("/api/<endpoint>")
response.raise_for_status()
print(response.json())
BaseClient accepts the following optional arguments.
site: Site name from~/.anaconda/config.tomldomain: Domain to use for requests, defaults to your default sitessl_verify: Enable SSL verification, defaults toTrueapi_key: API key to use for requests, if unspecified, uses token set byanaconda loginuser_agent: Defaults toanaconda-auth/<package-version>api_version: Requested API version, defaults to latest available from the domainextra_headers: Dictionary or JSON string of extra headers to send in requests
When using the site="<name>" argument all other keyword args will
override the configuration loaded from ~/.anaconda/config.toml.
To create a Client class specific to your package, subclass BaseClient and set an appropriate user-agent and API version for your needs.
from anaconda_auth.client import BaseClient
class Client(BaseClient):
_user_agent = "anaconda-<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, the user is running the CLI command interactively and 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 fromrequests.exceptions.HTTPError, the request was made without an API key or token to an endpoint that requires authentication.InvalidAuthentication: Derived fromrequests.exceptions.HTTPError, the request was made using an API key or token, but Anaconda determined 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 auth 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 log in or configure the API key.
❯ anaconda auth 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 anaconda.com
or set your API key using the ANACONDA_AUTH_API_KEY env var
or set
[plugin.auth]
api_key = "<api-key>"
in ~/.anaconda/config.toml
To see a more detailed error message run the command again as
anaconda --verbose auth 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.com/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_auth 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_auth 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_auth or --oauth-provider anaconda_auth
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