Mechanical rename (package agent_credential_broker; entry points
agent-broker{,-mcp,-plugin}; env AGENT_BROKER_*; paths agent-broker;
agent-browser credential provider 'broker'; MCP server name agent-broker).
New backend 'openbao': stdlib-only HTTP client for OpenBao/Vault KV v2
(approle login or token file/env; metadata-only ref index; lazy re-login
on 401/403; token renewal). bitwarden-cli backend kept as transition.
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Vault backend abstraction -- the ONLY layer that talks to the vault.
|
|
|
|
bitwarden-cli official `bw` subprocesses against a
|
|
Bitwarden-compatible server (transition backend).
|
|
openbao OpenBao/Vault HTTP API (KV v2 + AppRole), stdlib
|
|
urllib only -- the target backend for agent
|
|
credentials.
|
|
|
|
A failing backend surfaces as VAULT_BACKEND_ERROR; there is no fallback.
|
|
|
|
The backend owns authentication, the unlocked session and vault reads.
|
|
Everything else (policy, refs, adapters, sanitizer, MCP, unix socket)
|
|
is backend-agnostic.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ..errors import BrokerError
|
|
|
|
|
|
class VaultBackend:
|
|
"""Interface consumed by BrokerCore.
|
|
|
|
unlock(password) authenticate + establish session (raises
|
|
UNLOCK_FAILED on bad password, VAULT_BACKEND_ERROR
|
|
otherwise)
|
|
lock() invalidate session + drop in-memory material
|
|
list_metadata() items with secret fields stripped (ref index)
|
|
get_item(item_id) full normalized item, fetched on demand
|
|
"""
|
|
|
|
name = "abstract"
|
|
|
|
def __init__(self, config):
|
|
self.config = config
|
|
|
|
def configured(self) -> bool:
|
|
raise NotImplementedError
|
|
|
|
def unlock(self, password: str) -> None:
|
|
raise NotImplementedError
|
|
|
|
def lock(self) -> None:
|
|
raise NotImplementedError
|
|
|
|
def logout(self) -> None:
|
|
"""End the vault session AND the stored account login. Default
|
|
equals lock() for backends without a persistent login."""
|
|
self.lock()
|
|
|
|
def list_metadata(self) -> list[dict]:
|
|
raise NotImplementedError
|
|
|
|
def get_item(self, item_id: str) -> dict:
|
|
raise NotImplementedError
|
|
|
|
|
|
def make_backend(config) -> VaultBackend:
|
|
name = config.vault_backend
|
|
if name == "bitwarden-cli":
|
|
from .bwcli import BitwardenCliBackend
|
|
return BitwardenCliBackend(config)
|
|
if name == "openbao":
|
|
from .openbao import OpenBaoBackend
|
|
return OpenBaoBackend(config)
|
|
raise BrokerError(
|
|
"UNCONFIGURED",
|
|
f"unknown vault_backend {name!r} "
|
|
"(supported: 'bitwarden-cli', 'openbao')",
|
|
)
|