Add resource-scoped bearer access metadata

This commit is contained in:
Eric Wendland 2026-05-17 02:58:58 +02:00
commit d072843cac
10 changed files with 344 additions and 11 deletions

View file

@ -161,8 +161,32 @@ pub enum AuthCommand {
#[derive(Debug, Subcommand)]
pub enum SecretCommand {
Status,
Create { resource: String },
Rotate { resource: String },
Create {
resource: String,
},
Rotate {
resource: String,
},
Bearer {
#[command(subcommand)]
command: SecretBearerCommand,
},
}
#[derive(Debug, Subcommand)]
pub enum SecretBearerCommand {
Create {
resource: String,
#[arg(long = "capability", required = true)]
capabilities: Vec<String>,
#[arg(long)]
expires_at_ms: Option<i64>,
},
List,
Revoke {
resource: String,
secret: String,
},
}
#[derive(Debug, Subcommand)]
@ -396,6 +420,21 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
SecretCommand::Status => ControlRequest::SecretStatus,
SecretCommand::Create { resource } => ControlRequest::SecretCreate { resource },
SecretCommand::Rotate { resource } => ControlRequest::SecretRotate { resource },
SecretCommand::Bearer { command } => match command {
SecretBearerCommand::Create {
resource,
capabilities,
expires_at_ms,
} => ControlRequest::SecretBearerCreate {
resource,
capabilities,
expires_at_ms,
},
SecretBearerCommand::List => ControlRequest::SecretBearerList,
SecretBearerCommand::Revoke { resource, secret } => {
ControlRequest::SecretBearerRevoke { resource, secret }
}
},
},
Command::Cas { command } => match command {
CasCommand::Add { path } => ControlRequest::CasAdd { path },
@ -653,6 +692,46 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
println!("resource: {}", secret.resource);
println!("epoch: {}", secret.epoch);
}
ControlResponse::SecretBearerCreated { access } => {
println!("bearer secret: {}", access.secret);
println!("resource: {}", access.resource);
println!(
"capabilities: {}",
access
.capabilities
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(",")
);
if let Some(expires_at) = access.expires_at {
println!("expires_at_ms: {}", expires_at.0);
}
println!("may_delegate: {}", access.may_delegate);
}
ControlResponse::SecretBearerList { access } => {
if access.is_empty() {
println!("no bearer access");
} else {
for item in access {
println!(
"{}\t{}\t{}\tmay_delegate={}",
item.secret,
item.resource,
item.capabilities
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(","),
item.may_delegate
);
}
}
}
ControlResponse::SecretBearerRevoked { resource, secret } => {
println!("revoked bearer secret: {secret}");
println!("resource: {resource}");
}
ControlResponse::AuthExplain(explain) => {
println!("allowed: {}", explain.allowed);
println!("subject: {}", explain.subject);