Skip to content

About

A 1Password secret reference resolver for OmegaConf and Hydra

Topics

Resources

Code of conduct

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

omegaconf-1password

A 1Password secret reference resolver for OmegaConf and Hydra

Build Status codecov License PyPI

Overview

Read secrets from 1Password directly in an OmegaConf or Hydra config, instead of exporting them into the environment first.

slack:
  bot_token: ${op:op://Developer - Infra/Slack Bot/credential}
  app_token: ${op:op://Developer - Infra/Slack App/credential, }
from omegaconf import OmegaConf
from omegaconf_1password import register

register()
cfg = OmegaConf.load("config.yaml")
cfg.slack.bot_token  # read from 1Password on first access

Secrets resolve lazily, so only the references a config actually touches are read. Nothing is written into the process environment, where any child process could read it. And because Hydra saves its composed config with interpolations unresolved, a saved config keeps the op:// reference rather than the secret.

Install

pip install omegaconf-1password

It calls the 1Password CLI, so op has to be installed and signed in. The desktop app integration is the least friction: 1Password → Settings → Developer → "Integrate with other apps".

Usage

Registering

from omegaconf_1password import register

register()              # ${op:...}
register("onepassword") # ${onepassword:...}

Registering more than once is fine, so a library can call it at import time without worrying about ordering.

Defaults

A second argument is returned when the reference cannot be read, which keeps a config usable when an optional credential is missing:

password: ${op:op://Vault/Item/credential, }

Reading directly

from omegaconf_1password import op_read

token = op_read("op://Vault/Item/credential")
token = op_read("op://Vault/Item/credential", "fallback", timeout=10, cache=False)

Caching

Values are cached per reference, because resolving a config can touch the same reference repeatedly and every miss is a subprocess call. Call clear_cache() after rotating a credential, or in a long-lived process that should not hold secrets longer than it needs them. Failed reads are never cached.

With Hydra

from omegaconf_1password import register

register()

@hydra.main(config_path="conf", config_name="config", version_base=None)
def main(cfg):
    ...

Caveats

  • op must be authorized in the process that resolves the config. Desktop app integration authorizes a terminal session, so a daemon or a non-interactive subprocess may need a service account token instead.
  • Each uncached read spawns op, which takes a few hundred milliseconds. Lazy resolution keeps that proportional to the secrets a config actually uses.

Note

This library was generated using copier from the Base Python Project Template repository.

About

A 1Password secret reference resolver for OmegaConf and Hydra

Topics

Resources

Code of conduct

Stars

1 star

Watchers

1 watching

Forks

Releases

Contributors

Languages