core: add community token issuer seam
This commit is contained in:
@@ -2,7 +2,11 @@ use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{MachineAccessMode, OperationSecurityLevel, PlatformApiKeyScope};
|
||||
use crate::{
|
||||
IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest, IssuedAgentTokenResponse,
|
||||
MachineAccessMode, MembershipRole, OperationSecurityLevel, PlatformApiKeyScope, UserId,
|
||||
WorkspaceId,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct VerifiedMachineCredential {
|
||||
@@ -26,3 +30,117 @@ pub trait MachineCredentialVerifier: Send + Sync {
|
||||
}
|
||||
|
||||
pub type SharedMachineCredentialVerifier = Arc<dyn MachineCredentialVerifier>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct TokenIssuerActor {
|
||||
pub user_id: UserId,
|
||||
pub workspace_id: WorkspaceId,
|
||||
pub role: MembershipRole,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
|
||||
pub enum TokenIssuerError {
|
||||
#[error("machine tokens are not available in this edition")]
|
||||
NotSupportedInEdition,
|
||||
#[error("invalid grant: {0}")]
|
||||
InvalidGrant(String),
|
||||
#[error("agent key is unknown")]
|
||||
AgentKeyUnknown,
|
||||
#[error("operation is not strict")]
|
||||
OperationNotStrict,
|
||||
#[error("operation is not published for agent")]
|
||||
OperationNotPublishedForAgent,
|
||||
#[error("registry failure: {0}")]
|
||||
RegistryFailure(String),
|
||||
#[error("replay guard failure: {0}")]
|
||||
ReplayGuardFailure(String),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait MachineTokenIssuer: Send + Sync {
|
||||
async fn issue_short_lived(
|
||||
&self,
|
||||
request: IssueAgentTokenRequest,
|
||||
actor: &TokenIssuerActor,
|
||||
) -> Result<IssuedAgentTokenResponse, TokenIssuerError>;
|
||||
|
||||
async fn issue_one_time(
|
||||
&self,
|
||||
request: IssueOneTimeAgentTokenRequest,
|
||||
actor: &TokenIssuerActor,
|
||||
) -> Result<IssuedAgentTokenResponse, TokenIssuerError>;
|
||||
}
|
||||
|
||||
pub type SharedMachineTokenIssuer = Arc<dyn MachineTokenIssuer>;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct NoMachineTokenIssuer;
|
||||
|
||||
#[async_trait]
|
||||
impl MachineTokenIssuer for NoMachineTokenIssuer {
|
||||
async fn issue_short_lived(
|
||||
&self,
|
||||
_request: IssueAgentTokenRequest,
|
||||
_actor: &TokenIssuerActor,
|
||||
) -> Result<IssuedAgentTokenResponse, TokenIssuerError> {
|
||||
Err(TokenIssuerError::NotSupportedInEdition)
|
||||
}
|
||||
|
||||
async fn issue_one_time(
|
||||
&self,
|
||||
_request: IssueOneTimeAgentTokenRequest,
|
||||
_actor: &TokenIssuerActor,
|
||||
) -> Result<IssuedAgentTokenResponse, TokenIssuerError> {
|
||||
Err(TokenIssuerError::NotSupportedInEdition)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{MachineTokenIssuer, NoMachineTokenIssuer, TokenIssuerActor, TokenIssuerError};
|
||||
use crate::{
|
||||
AgentTokenGrantType, IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest, MembershipRole,
|
||||
UserId, WorkspaceId,
|
||||
};
|
||||
|
||||
fn actor() -> TokenIssuerActor {
|
||||
TokenIssuerActor {
|
||||
user_id: UserId::new("user_01"),
|
||||
workspace_id: WorkspaceId::new("ws_01"),
|
||||
role: MembershipRole::Owner,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_machine_token_issuer_rejects_short_lived_issue() {
|
||||
let result = NoMachineTokenIssuer
|
||||
.issue_short_lived(
|
||||
IssueAgentTokenRequest {
|
||||
grant_type: AgentTokenGrantType::AgentKey,
|
||||
agent_key: Some("crk_agent_secret".to_owned()),
|
||||
refresh_token: None,
|
||||
scope: vec![],
|
||||
},
|
||||
&actor(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(result, Err(TokenIssuerError::NotSupportedInEdition));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_machine_token_issuer_rejects_one_time_issue() {
|
||||
let result = NoMachineTokenIssuer
|
||||
.issue_one_time(
|
||||
IssueOneTimeAgentTokenRequest {
|
||||
agent_key: "crk_agent_secret".to_owned(),
|
||||
operation_id: "op_01".into(),
|
||||
scope: vec![],
|
||||
},
|
||||
&actor(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(result, Err(TokenIssuerError::NotSupportedInEdition));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,9 @@ pub use ext::audit::{
|
||||
AuditTargetKind, NoopAuditSink, SharedAuditSink,
|
||||
};
|
||||
pub use ext::auth::{
|
||||
MachineCredentialVerifier, MachineCredentialVerifierError, SharedMachineCredentialVerifier,
|
||||
VerifiedMachineCredential,
|
||||
MachineCredentialVerifier, MachineCredentialVerifierError, MachineTokenIssuer,
|
||||
NoMachineTokenIssuer, SharedMachineCredentialVerifier, SharedMachineTokenIssuer,
|
||||
TokenIssuerActor, TokenIssuerError, VerifiedMachineCredential,
|
||||
};
|
||||
pub use ext::capability::{CapabilityProfile, CommunityCapabilityProfile};
|
||||
pub use ids::{
|
||||
|
||||
Reference in New Issue
Block a user