fnox 1.40.0 adds custom providers written as Lua plugins, a read-only Kubernetes Secrets provider, 1Password Environments, file-backed plain providers and Bitwarden folder scoping. The daemon now runs on Windows. This release also fixes Azure service principal authentication, repeated hardware PIN prompts for age identities, and fnox set dropping piped values.
Added
- Custom providers as Lua plugins (#968) by @jdx. You can now write a secrets backend that fnox doesn't support as a Lua 5.4 plugin and share it as a git repository. Declare the plugin under
[plugins], then use it withtype = "lua":[plugins] corp = "acme/fnox-plugin-corp#v1.2.0" # git URL or owner/repo, optional #ref [providers.corp] type = "lua" plugin = "corp" # or a path such as ./plugins/corp.lua [secrets] DATABASE_URL = { provider = "corp", value = "prod/database-url" }
- A plugin is a
provider.luathat returns hooks.getis required.get_batch,put,encryptandtestare optional, and the hooks you define decide whetherfnox setandfnox importcan write to the provider. A provider'soptionstable (string values, which can be secret references) is passed to the plugin asctx.options. Plugins can use thefnox.http,fnox.json,fnox.cmd,fnox.logandfnox.base64modules.fnox.auth_error(msg)triggers the provider'sauth_commandflow. - New commands:
fnox plugin install,update,link,lsanduninstall, plusfnox provider add NAME lua --plugin .... - fnox installs a declared plugin the first time a provider uses it (
git clone). Plugins go in$FNOX_DATA_DIR/plugins, which defaults to$XDG_DATA_HOME/fnoxor~/.local/share/fnox. SetFNOX_PLUGINS_DIRto use a different location. If a project declares a different source or ref than the installed one, fnox won't load the plugin until you runfnox plugin update <name>. - Plugins run with your user's permissions. Only install plugins from sources you trust, and pin a ref. See
docs/providers/lua.mdfor details.
- A plugin is a
- Kubernetes Secrets provider (#953) by @jdx. A read-only
kubernetesprovider reads existing Secrets through the Kubernetes API. It only makes namedGETrequests and never lists, watches or writes Secrets. A reference can besecret,secret/keyornamespace/secret/key. The optionalcontext,namespace,kubeconfigandprefixsettings control where it looks, and theFNOX_K8S_CONTEXTenvironment variable can also select the context. Daemon caching is always disabled for this provider, even withdaemon_cache = true.[providers.kubernetes] type = "kubernetes" context = "production" namespace = "payments" [secrets] DATABASE_URL = { provider = "kubernetes", value = "database/url" }
- 1Password Environments (#955) by @jdx. The
1passwordprovider can read variables from a 1Password Environment usingenvironment://<environment-id>/<VARIABLE>references. You can mix these with vault item references in the same config. fnox reads each Environment once per provider instance, and a variable missing from the Environment is an error. This needs the betaopCLI with theop environmentcommand. - Read values from a plaintext file with the
plainprovider (#954) by @joshbode. The newfileandformatsettings make each secret'svaluea key to look up in that file.formatcan beenv,shell,json,yamlortoml, and you must set it wheneverfileis set. A relative path resolves against the config file that declares the provider. The file is read-only, and a missing key counts as a missing secret, sodefaultandif_missingstill apply.[providers.dotenv] type = "plain" file = "secrets.env" format = "env" [secrets] API_TOKEN = { provider = "dotenv", value = "SERVICE_TOKEN" }
- Bitwarden folder scoping (#965) by @andersonkrs. The new optional
foldersetting limits lookups to one Bitwarden folder. For nested folders, use the full path, such asfolder = "MyApp/Production". This lets items with the same name exist in different folders. It works with bothbwandrbw. - Azure managed identity (#964) by @jdx.
azure-sm,azure-kmsandazure-acacceptauth = "managed-identity", with an optionalmanaged_identity_client_idfor a user-assigned identity. fnox never tries managed identity on its own; you have to setauth. - Daemon on Windows (#974) by @jdx. On Windows, the daemon now uses a per-user named pipe where other platforms use a Unix socket, so Windows gets cached secrets too. Only the current user can access the pipe, and both the client and the daemon check the user on the other end. The wire protocol and the
fnox-clientAPI are unchanged.
Fixed
- Azure service principal environment variables (#964) by @jdx. Azure providers authenticate as a service principal again when
AZURE_TENANT_ID,AZURE_CLIENT_IDandAZURE_CLIENT_SECRETare all set. Without them, fnox falls back to theaz/azdlogin. For sovereign clouds, setAZURE_AUTHORITY_HOST. These variables can also be fnox secrets resolved byfnox exec. - Hardware PIN prompts for age identities (#978) by @andersonkrs and @jdx. With PIN-protected age identities (
age-plugin-tpm --pin,age-plugin-yubikey), a value used by several providers made one command ask for the PIN up to three times. Now a successful decrypt is reused for the rest of the request, so you get one prompt perfnox get,execorexport, or per daemon request. Nothing is kept between requests, and a failed decrypt can be retried. fnox setwith piped stdin and metadata flags (#976) by @jdx.echo val | fnox set A -d "desc"(or with--defaultor--if-missing) said it worked but saved no value. fnox now stores the piped value along with the metadata. If stdin is empty, only the metadata is updated, as before.
Changed
fnox importparsing (#954) by @joshbode.fnox importnow accepts the{secrets, metadata}document thatfnox export --format json|yaml|tomlproduces. Theenvparser now follows Docker Compose dotenv rules for inline comments. For example,PORT=8080 # defaultnow imports as8080, where it used to keep the comment as part of the value.#without whitespace before it, as inID=val#ue, and#inside quotes are still part of the value.
New Contributors
- @joshbode made their first contribution in #954
- @andersonkrs made their first contribution in #965
Full Changelog: v1.39.0...v1.40.0
💚 Sponsor fnox
fnox is built and maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.
If fnox handles secrets or config for you or your team, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep fnox secure, free, and independent.