NAME
Langertha::Skeid::KeyBroker::OpenBao - OpenBao-backed KeyBroker with AppRole auth and token renewal
VERSION
version 0.003
SYNOPSIS
my $broker = Langertha::Skeid::KeyBroker::OpenBao->new(
addr => $ENV{OPENBAO_ADDR} // 'http://127.0.0.1:8200',
role_id => $ENV{OPENBAO_ROLE_ID},
secret_id => $ENV{OPENBAO_SECRET_ID},
renew_secs => 300, # renew token every 5 minutes
);
my $api_key = $broker->resolve_key('secret/skeid/remote/openai'); # blocking; CLI and tests
# the request path
$broker->key_async('secret/skeid/remote/openai', sub { my ($key, $error) = @_; ... });
addr
The OpenBao address (default OPENBAO_ADDR, else http://127.0.0.1:8200).
role_id
Required. The AppRole role id, injected at container start (OPENBAO_ROLE_ID).
secret_id
Required. The AppRole secret id, injected at container start (OPENBAO_SECRET_ID). Held in memory only.
renew_secs
How often "start_renewal" renews the token, in seconds (default 300; below 1 means 60).
verify_ssl
Whether to verify the OpenBao server's TLS certificate (default 1, override with OPENBAO_VERIFY_SSL=0). Turning it off on an https:// address means anything that can intercept the connection can hand out this process's AppRole token and every secret it resolves. It exists for a dev vault with a self-signed certificate and nothing else.
needs_refresh
True when there is no client token yet or it expires within the next 60 seconds.
refresh
Renews the token through renew-self, blocking. Dies when there is no token to renew with or the renewal fails -- the AppRole credential is then spent and the process has to restart. The request path renews through "resolve_key_async" instead.
resolve_key
my $key = $broker->resolve_key('secret/skeid/remote/groq');
Reads the KV-v2 secret the reference names and returns its api_key field, renewing the token first when it is due. secret/skeid/remote/groq is read from secret/data/skeid/remote/groq. Blocking -- never call it from a request handler. Returns undef for an empty reference, a failed read (warned with the reference and the HTTP status only) or a secret without api_key.
resolve_key_async
Non-blocking resolution against OpenBao, renewing the token first when it is due. Used by "key_async" in Langertha::Skeid::KeyBroker, which is what the request path calls; a cache hit never gets here.
With no IO loop running there is nothing to yield to, so this falls back to the blocking path — that is the CLI and the test suite, not the proxy.
start_renewal
$broker->start_renewal;
Renews the token on a timer instead of waiting for a request to notice it expired, so the request path finds a valid token already there. Called by "build_app" in Langertha::Skeid::Proxy; safe to call twice.
A failed renewal warns while the current token is still valid — a blip is not worth dropping in-flight requests for. Once it has actually expired the process dies, because a Skeid that cannot resolve keys is not a Skeid that should keep answering: the container restarts and logs in again with its AppRole credentials (ADR 0003).
list_secrets
my $names = $broker->list_secrets('secret/metadata/skeid/remote');
The keys under a path, via a blocking LIST. The path is the API path as given -- for KV-v2 that is secret/metadata/...; no secret/ rewriting happens here. Returns an empty arrayref on any failure. For setup scripts, not the request path.
DESCRIPTION
This KeyBroker implementation fetches API keys from OpenBao KV-v2 secrets. Security model:
AppRole credentials (
role_id+secret_id) are injected at container start. Construction logs in with them, blocking, and dies when the login fails.The login token is used only to call
renew-self; the first resolution does that and gets the client token for API calls.renew-selfreturns a new client token, which is also the next renew token.The token is renewed every
renew_secsseconds viarenew-selfonce "start_renewal" runs.If renewal fails after the token expired, the process dies, so the container restarts and logs in again.
No secret is ever written to disk. Tokens and resolved keys live only in memory, and are dropped when the broker is destroyed.
SEE ALSO
Langertha::Skeid::KeyBroker, "build_app" in Langertha::Skeid::Proxy (which builds this broker from OPENBAO_ROLE_ID, OPENBAO_SECRET_ID and OPENBAO_ADDR)
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-skeid/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.