mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-06-07 05:45:13 +02:00
feat(iam): allow bootstrap mode and token to be sourced from env vars (#851)
Adds an environment-variable fallback for the iam-svc bootstrap configuration so the token can be injected from a Kubernetes Secret (or any equivalent secret store) without ever appearing in the processor-group YAML — which is typically version-controlled. Resolution order is fixed and per-setting: bootstrap_mode = params["bootstrap_mode"] or $IAM_BOOTSTRAP_MODE bootstrap_token = params["bootstrap_token"] or $IAM_BOOTSTRAP_TOKEN If neither source supplies a value, the service refuses to start with a clear message naming both options. The two settings are resolved independently, which lets operators commit the mode in YAML (it is not a secret) while pulling the token from a Secret-backed ``IAM_BOOTSTRAP_TOKEN`` env var. Validation invariants are unchanged: * mode must be 'token' or 'bootstrap' * mode='token' requires a token (from any source) * mode='bootstrap' must NOT have a token (ambiguous intent) There is no permissive fallback — the service fails closed in every branch where configuration is incomplete. docs/tech-specs/iam-protocol.md gains a 'Configuration sources' subsection under 'Bootstrap modes' that documents the precedence table and the K8s injection pattern. The 'Bootstrap-token lifecycle' step about removing the token after rotation now applies to whichever source was used (Secret, env var, or YAML field).
This commit is contained in:
parent
67b2fc448f
commit
666af1c4b3
2 changed files with 53 additions and 10 deletions
|
|
@ -273,6 +273,25 @@ cannot distinguish:
|
|||
This matches the general IAM error-policy stance (see `iam.md`) and
|
||||
prevents externally enumerating IAM's state.
|
||||
|
||||
### Configuration sources
|
||||
|
||||
The mode and token can be supplied two ways. Resolution order is
|
||||
fixed; there is no permissive fallback.
|
||||
|
||||
| Source | Field |
|
||||
|---|---|
|
||||
| Processor-group YAML / CLI argument | `bootstrap_mode`, `bootstrap_token` |
|
||||
| Environment variable | `IAM_BOOTSTRAP_MODE`, `IAM_BOOTSTRAP_TOKEN` |
|
||||
|
||||
For each setting the service uses the explicit param value if
|
||||
present; otherwise the environment variable; otherwise the service
|
||||
refuses to start. The env-var path is intended for the K8s
|
||||
deployment pattern where the token is injected from a `Secret` via
|
||||
`secretKeyRef`, so the plaintext never has to live in YAML or git.
|
||||
A typical production manifest holds `bootstrap_mode: "token"` in
|
||||
the YAML and pulls `IAM_BOOTSTRAP_TOKEN` from the Secret; the YAML
|
||||
is then safe to version-control.
|
||||
|
||||
### Bootstrap-token lifecycle
|
||||
|
||||
The bootstrap token — whether operator-supplied (`token` mode) or
|
||||
|
|
@ -283,7 +302,8 @@ operator's first admin action after bootstrap should be:
|
|||
1. Create a durable admin user and API key (or issue a durable API
|
||||
key to the bootstrap admin).
|
||||
2. Revoke the bootstrap key via `revoke-api-key`.
|
||||
3. Remove the bootstrap token from any deployment configuration.
|
||||
3. Remove the bootstrap token from any deployment configuration
|
||||
(Secret, env var, or YAML field — wherever it was sourced).
|
||||
|
||||
The `name="bootstrap"` marker makes bootstrap keys easy to detect in
|
||||
tooling (e.g. a `tg-list-api-keys` filter).
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ Shape mirrors trustgraph.config.service.
|
|||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from trustgraph.schema import Error
|
||||
from trustgraph.schema import IamRequest, IamResponse
|
||||
|
|
@ -27,6 +28,13 @@ default_ident = "iam-svc"
|
|||
default_iam_request_queue = iam_request_queue
|
||||
default_iam_response_queue = iam_response_queue
|
||||
|
||||
# Environment variables consulted as a fallback when the
|
||||
# corresponding params field is not set in the processor-group YAML
|
||||
# or via CLI. Intended for K8s Secret / env-var injection so the
|
||||
# bootstrap token never has to live in the YAML (and thus in git).
|
||||
ENV_BOOTSTRAP_MODE = "IAM_BOOTSTRAP_MODE"
|
||||
ENV_BOOTSTRAP_TOKEN = "IAM_BOOTSTRAP_TOKEN"
|
||||
|
||||
|
||||
class Processor(AsyncProcessor):
|
||||
|
||||
|
|
@ -39,26 +47,41 @@ class Processor(AsyncProcessor):
|
|||
"iam_response_queue", default_iam_response_queue,
|
||||
)
|
||||
|
||||
bootstrap_mode = params.get("bootstrap_mode")
|
||||
bootstrap_token = params.get("bootstrap_token")
|
||||
# Resolve bootstrap mode + token. Precedence: explicit
|
||||
# params (CLI / processor-group YAML) → environment variable
|
||||
# → unset (fail-closed). The env-var path is the K8s-native
|
||||
# injection point: an `IAM_BOOTSTRAP_TOKEN` from a Secret
|
||||
# never has to land in the YAML, and therefore never enters
|
||||
# git history.
|
||||
bootstrap_mode = (
|
||||
params.get("bootstrap_mode")
|
||||
or os.environ.get(ENV_BOOTSTRAP_MODE)
|
||||
)
|
||||
bootstrap_token = (
|
||||
params.get("bootstrap_token")
|
||||
or os.environ.get(ENV_BOOTSTRAP_TOKEN)
|
||||
)
|
||||
|
||||
if bootstrap_mode not in ("token", "bootstrap"):
|
||||
raise RuntimeError(
|
||||
"iam-svc: --bootstrap-mode is required. Set to 'token' "
|
||||
"(with --bootstrap-token) for production, or 'bootstrap' "
|
||||
"iam-svc: bootstrap-mode is required. Set to 'token' "
|
||||
"(with bootstrap-token) for production, or 'bootstrap' "
|
||||
"to enable the explicit bootstrap operation over the "
|
||||
"pub/sub bus (dev / quick-start only, not safe under "
|
||||
"public exposure). Refusing to start."
|
||||
"public exposure). Configurable via processor-group "
|
||||
f"params or the {ENV_BOOTSTRAP_MODE} environment "
|
||||
"variable. Refusing to start."
|
||||
)
|
||||
if bootstrap_mode == "token" and not bootstrap_token:
|
||||
raise RuntimeError(
|
||||
"iam-svc: --bootstrap-mode=token requires "
|
||||
"--bootstrap-token. Refusing to start."
|
||||
"iam-svc: bootstrap-mode=token requires bootstrap-token "
|
||||
f"(or the {ENV_BOOTSTRAP_TOKEN} environment "
|
||||
"variable). Refusing to start."
|
||||
)
|
||||
if bootstrap_mode == "bootstrap" and bootstrap_token:
|
||||
raise RuntimeError(
|
||||
"iam-svc: --bootstrap-token is not accepted when "
|
||||
"--bootstrap-mode=bootstrap. Ambiguous intent. "
|
||||
"iam-svc: bootstrap-token is not accepted when "
|
||||
"bootstrap-mode=bootstrap. Ambiguous intent. "
|
||||
"Refusing to start."
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue