move repos into monorepo
This commit is contained in:
111
bin/supervisor/src/auth.rs
Normal file
111
bin/supervisor/src/auth.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
//! Authentication and API key management
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// API key scope/permission level
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ApiKeyScope {
|
||||
/// Full access - can manage keys, runners, jobs
|
||||
Admin,
|
||||
/// Can register new runners
|
||||
Registrar,
|
||||
/// Can create and manage jobs
|
||||
User,
|
||||
}
|
||||
|
||||
impl ApiKeyScope {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
ApiKeyScope::Admin => "admin",
|
||||
ApiKeyScope::Registrar => "registrar",
|
||||
ApiKeyScope::User => "user",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An API key with metadata
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ApiKey {
|
||||
/// The actual key value (UUID or custom string)
|
||||
pub key: String,
|
||||
/// Human-readable name for the key
|
||||
pub name: String,
|
||||
/// Permission scope
|
||||
pub scope: ApiKeyScope,
|
||||
/// When the key was created
|
||||
pub created_at: String,
|
||||
/// Optional expiration timestamp
|
||||
pub expires_at: Option<String>,
|
||||
}
|
||||
|
||||
impl ApiKey {
|
||||
/// Create a new API key with a generated UUID
|
||||
pub fn new(name: String, scope: ApiKeyScope) -> Self {
|
||||
Self {
|
||||
key: Uuid::new_v4().to_string(),
|
||||
name,
|
||||
scope,
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
expires_at: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new API key with a specific key value
|
||||
pub fn with_key(key: String, name: String, scope: ApiKeyScope) -> Self {
|
||||
Self {
|
||||
key,
|
||||
name,
|
||||
scope,
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
expires_at: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Response for auth verification
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AuthVerifyResponse {
|
||||
pub valid: bool,
|
||||
pub name: String,
|
||||
pub scope: String,
|
||||
}
|
||||
|
||||
/// Method authorization requirements
|
||||
/// Maps RPC method names to required scopes
|
||||
pub fn get_method_required_scopes(method: &str) -> Option<Vec<ApiKeyScope>> {
|
||||
use ApiKeyScope::*;
|
||||
|
||||
match method {
|
||||
// Admin-only methods
|
||||
"key.create" | "key.generate" | "key.delete" | "key.list" |
|
||||
"supervisor.info" => {
|
||||
Some(vec![Admin])
|
||||
}
|
||||
|
||||
// Admin or Registrar methods
|
||||
"runner.create" | "runner.remove" => {
|
||||
Some(vec![Admin, Registrar])
|
||||
}
|
||||
|
||||
// Admin or User methods
|
||||
"job.create" | "job.run" | "job.start" | "job.stop" | "job.delete" => {
|
||||
Some(vec![Admin, User])
|
||||
}
|
||||
|
||||
// Public methods (no auth required)
|
||||
"rpc.discover" => None,
|
||||
|
||||
// Any authenticated user (read-only operations)
|
||||
"runner.list" | "runner.ping" |
|
||||
"job.get" | "job.list" | "job.status" | "job.result" | "job.logs" |
|
||||
"auth.verify" => {
|
||||
Some(vec![Admin, Registrar, User])
|
||||
}
|
||||
|
||||
// Default: require authentication
|
||||
_ => Some(vec![Admin, Registrar, User]),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user