Secrets Plugin
使用白名单逻辑 secret reference 取值,不把 secret value 放入 App Plan。
lenso.secrets@1 提供一个 resolve request。consumer 请求 database/url 这样的
逻辑 reference;App Composition 把 requirement 绑定到一个 provider。secret value
绝不属于 Plan configuration、diagnostic、error 或 Debug output。
配置 Env provider
linked Rust Env provider 适用于本地开发和受控 host 部署:
{
"references": {
"database/url": "APP_DATABASE_URL",
"auth/signing-key": "APP_AUTH_SIGNING_KEY"
}
}
在 native App 中注册 factory,并把 consumer 的 exactly-one lenso.secrets@1
requirement 绑定到这个 Instance:
use lenso_native_adapter::NativePluginRegistry;
use lenso_secrets_env_module::EnvSecretsFactory;
let native = NativePluginRegistry::new()
.with_factory(EnvSecretsFactory::new());
白名单不能为空。逻辑 reference 是最长 256 bytes 的 canonical path:不能有开头或
结尾 slash、空 segment、. segment 或 .. segment。重复 reference 与不可移植的
environment variable name 会让 Plan admission 失败。
在 Plugin 中解析
use lenso_capability_secrets::{
ResolveRequest, SecretsClient, SecretsInvocationError,
};
use lenso_kernel::{PluginDependencies, RuntimeFailure};
fn client(dependencies: &PluginDependencies) -> Result<SecretsClient, RuntimeFailure> {
SecretsClient::from_dependencies(dependencies)
}
async fn database_url(secrets: &SecretsClient) -> Result<String, SecretsInvocationError> {
let response = secrets.resolve(ResolveRequest {
reference: "database/url".into(),
}).await?;
Ok(response.value)
}
invalid_reference 表示 request 格式非法;unknown_reference 表示格式有效但不在
该 Instance 的白名单中。已配置 source 不可用属于 Runtime Failure,而不是 Domain
Error,也不是尝试另一个 provider 的信号。
Env provider 会在 prepare 中验证全部 source,同时不输出 environment variable
name 或 value。每次 resolve 都重新读取当前进程环境,因此 host 侧 rotation 无需
修改 Plan 即可生效。source 后续消失时,解析会如实失败。
实现其他 provider
生产 cloud provider 应属于自己的 Plugin。它实现生成的 SecretsProvider,只返回
请求的 value,并自行拥有 authentication、rotation、availability 与 audit policy:
use futures::future::LocalBoxFuture;
use lenso_capability_secrets::{
ResolveRequest, ResolveResponse, SecretsInvocationError, SecretsProvider,
};
use lenso_kernel::InvocationContext;
#[derive(Debug)]
struct CloudSecrets;
impl SecretsProvider for CloudSecrets {
fn resolve(
&self,
context: InvocationContext,
request: ResolveRequest,
) -> LocalBoxFuture<'static, Result<ResolveResponse, SecretsInvocationError>> {
Box::pin(async move {
// 对选定 backend 认证、授权 request.reference、读取 value,
// 并显式映射预期失败。
todo!()
})
}
}
不要增加隐式 provider fallback,也不要把 cloud SDK 放进 Kernel。
owner repository 当前将 registry publication 标为 parked。依赖 cargo add 前请检查
package registry;source implementation 与 registry availability 是两件事。