use std::fs;
use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::{Args, Subcommand};
use ed25519_dalek::pkcs8::DecodePrivateKey;
use ed25519_dalek::SigningKey;
use gradatum_auth::jwt::{JwtService, TokenScope};
#[derive(Debug, Subcommand)]
pub enum TokenCmd {
Issue(TokenIssueArgs),
}
#[derive(Debug, Args)]
pub struct TokenIssueArgs {
#[arg(long)]
pub root: PathBuf,
#[arg(long)]
pub sub: String,
#[arg(long, default_value = "vault_read")]
pub scopes: String,
#[arg(long, default_value = "main")]
pub tenant: String,
#[arg(long)]
pub ttl_secs: Option<u64>,
}
pub fn run(cmd: TokenCmd) -> Result<()> {
match cmd {
TokenCmd::Issue(args) => run_issue(args),
}
}
fn run_issue(args: TokenIssueArgs) -> Result<()> {
let priv_path = args.root.join("config/jwt.private.pem");
let pem = fs::read_to_string(&priv_path)
.with_context(|| format!("lecture de la clé privée {}", priv_path.display()))?;
let signing = SigningKey::from_pkcs8_pem(&pem)
.map_err(|e| anyhow::anyhow!("décodage PKCS8 PEM échoué: {e}"))?;
let ttl_service = args.ttl_secs.unwrap_or(86400);
let jwt = JwtService::new(
signing,
"gradatum-admin-issued".to_string(),
"gradatum".to_string(),
3600, ttl_service,
);
let scopes: Vec<String> = args
.scopes
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
let token = jwt
.sign(&args.sub, &scopes, TokenScope::Service, &args.tenant)
.map_err(|e| anyhow::anyhow!("signature JWT échouée: {e}"))?;
println!("{token}");
Ok(())
}