Skip to main content

datasette-secrets

PyPI Changelog Tests License

Manage secrets such as API keys for use with other Datasette plugins

This plugin requires a Datasette 1.0 alpha release.

Datasette plugins sometimes need access to secrets, such as API keys used to integrate with tools hosted outside of Datasette - things like geocoders or hosted AI language models.

This plugin provides ways to configure those secrets:

  • Secrets can be configured using environment variables, such as DATASETTE_SECRETS_OPENAI_API_KEY
  • Secrets can be stored, encrypted, in a SQLite database table which administrator users can then update through the Datasette web interface

Installation

Install this plugin in the same environment as Datasette.

datasette install datasette-secrets

Configuration

First you will need to generate an encryption key for this plugin to use. Run this command:

datasette secrets generate-encryption-key

Store this secret somewhere secure. It will be used to both encrypt and decrypt secrets stored by this plugin - if you lose it you will not be able to recover your secrets.

Configure the plugin with these these two plugin settings:

plugins:
  datasette-secrets:
    encryption_key:
      $env: DATASETTE_SECRETS_ENCRYPTION_KEY
    database: name_of_database

The encryption_key setting should be set to the encryption key you generated earlier. You can store it in an environment variable if you prefer.

database is the name of the database that the encrypted keys should be stored in. Omit this setting to use the internal database.

Using the internal database

While the secrets stored in the datasette_secrets table are encrypted, we still recommend hiding that table from view.

One way to do that is to keep the table in Datasette's internal database, which is invisible to all users, even users who are logged in.

By default, the internal database is an in-memory database that is reset when Datasette restarts. This is no good for persistent secret storage!

Instead, you should switch Datasette to using an on-disk internal database. You can do this by starting Datasette with the --internal option:

datasette data.db --internal internal.db

Your secrets will be stored in the datasette_secrets table in that database file.

Permissions

Only users with the manage-secrets permission will have access to manage secrets through the Datasette web interface.

You can grant that permission to the root user (or the user with an ID of your choice) by including this in your datasette.yml file:

permissions:
  manage-secrets:
    id: root

Then start Datasette like this (with --root to get a URL to login as the root user):

datasette data.db --internal internal.db -c datasette.yml --root

Alternatively, use the -s option to set that setting without creating a configuration file:

datasette data.db --internal internal.db \
  -s permissions.manage-secrets.id root \
  --root

Usage

users with the manage-secrets permission will see a new "Manage secrets" link in the Datasette navigation menu. This interface can also be accessed at /-/secrets.

The page with the list of secrets will show the user who last updated each secret. This will use the actors_from_ids() mechanism, displaying the actor's username if available, otherwise the name, otherwise the id.

For plugin authors

Plugins can depend on this plugin if they want to implement secrets.

datasette-secrets to the dependencies list in pyproject.toml.

Then declare the name and description of any secrets you need using the register_secrets() plugin hook:

from datasette import hookimpl
from datasette_secrets import Secret

@hookimpl
def register_secrets():
    return [
        Secret(
            name="OPENAI_API_KEY",
            description="An OpenAI API key"
        ),
    ]

You can also provide optional obtain_url and obtain_label fields to link to a page where a user can obtain an API key:

@hookimpl
def register_secrets():
    return [
        Secret(
            name="OPENAI_API_KEY",
            obtain_url="https://platform.openai.com/api-keys",
            obtain_label="Get an OpenAI API key"
        ),
    ]

The hook can take an optional datasette argument. It can return a list or an async def function that, when awaited, returns a list.

The list should consist of Secret() instances, each with a name and an optional description. The description can contain HTML.

To obtain the current value of the secret, use the await get_secret() method:

from datasette_secrets import get_secret

# Third argument is the actor_id, optional
secret = await get_secret(datasette, "OPENAI_API_KEY", "root")

If the Datasette administrator set a DATASETTE_SECRETS_OPENAI_API_KEY environment variable, that will be returned.

Otherwise the encrypted value in the database table will be decrypted and returned - or None if there is no configured secret.

The last_used_at column is updated every time a secret is accessed. The last_used_by column will be set to the actor ID passed to get_secret(), or null if no actor ID was passed.

Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:

cd datasette-secrets
python3 -m venv venv
source venv/bin/activate

Now install the dependencies and test dependencies:

pip install -e '.[test]'

To run the tests:

pytest

Metadata

Release files for datasette-secrets 0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for datasette-secrets 0.2
File Size Uploaded Provenance Actions
datasette_secrets-0.2.tar.gz 16.6 kB Without provenance Details for datasette_secrets-0.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for datasette-secrets 0.2
File Interpreter ABI Platform Actions
datasette_secrets-0.2-py3-none-any.whl Python 3 none any Details for datasette_secrets-0.2-py3-none-any.whl

Total release size: 29.6 kB

Release files / datasette_secrets-0.2.tar.gz

Download URL datasette_secrets-0.2.tar.gz
Size 16.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5727ecb4be6e385ad44ba7c1b30f80e8fc3036fbcc184518c6b3e0a830c53b91
BLAKE2b-256 checksum
How to use checksums
f3c78b9b3fbe357d103f98d575721694331604ec81fa8deaa506d310e76cadcd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.0.0 CPython/3.12.3

Release files / datasette_secrets-0.2-py3-none-any.whl

Download URL datasette_secrets-0.2-py3-none-any.whl
Size 13.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a5e21d4e4d550ebc668b3e795ffc57b99ecbd6f852fe55a0b44f17a4d6a49455
BLAKE2b-256 checksum
How to use checksums
a4022b6bbbbd670362422823a2b76c078a6d2d6994de991b798dbed0c59be779
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.0.0 CPython/3.12.3

Security for datasette-secrets 0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page