fix(server::user_agent): useragents now self-sign themselves on bootstrap
This commit is contained in:
@@ -2,17 +2,9 @@ syntax = "proto3";
|
|||||||
|
|
||||||
package arbiter.user_agent.auth;
|
package arbiter.user_agent.auth;
|
||||||
|
|
||||||
enum KeyType {
|
|
||||||
KEY_TYPE_UNSPECIFIED = 0;
|
|
||||||
KEY_TYPE_ED25519 = 1;
|
|
||||||
KEY_TYPE_ECDSA_SECP256K1 = 2;
|
|
||||||
KEY_TYPE_RSA = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AuthChallengeRequest {
|
message AuthChallengeRequest {
|
||||||
bytes pubkey = 1;
|
bytes pubkey = 1;
|
||||||
optional string bootstrap_token = 2;
|
optional string bootstrap_token = 2;
|
||||||
KeyType key_type = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message AuthChallenge {
|
message AuthChallenge {
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ use kameo::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::flow_coordinator::ApprovalError,
|
actors::flow_coordinator::ApprovalError,
|
||||||
peers::{client::ClientProfile, user_agent::{UserAgentSession, session::BeginNewClientApproval}},
|
peers::{
|
||||||
|
client::ClientProfile,
|
||||||
|
user_agent::{UserAgentSession, session::BeginNewClientApproval},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ use kameo::{
|
|||||||
};
|
};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{actors::flow_coordinator::client_connect_approval::ClientApprovalController, peers::{client::{ClientProfile, session::ClientSession}, user_agent::UserAgentSession}};
|
use crate::{
|
||||||
|
actors::flow_coordinator::client_connect_approval::ClientApprovalController,
|
||||||
|
peers::{
|
||||||
|
client::{ClientProfile, session::ClientSession},
|
||||||
|
user_agent::UserAgentSession,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub mod client_connect_approval;
|
pub mod client_connect_approval;
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ use thiserror::Error;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::{
|
actors::{
|
||||||
bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator,
|
bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator, vault::Vault,
|
||||||
vault::Vault,
|
|
||||||
},
|
},
|
||||||
db,
|
db,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ impl Vault {
|
|||||||
Ok(nonce)
|
Ok(nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_unsealed<'a>(state: &'a mut State) -> Result<&'a mut Unsealed, Error> {
|
fn expect_unsealed(state: &mut State) -> Result<&mut Unsealed, Error> {
|
||||||
match state {
|
match state {
|
||||||
State::Unsealed(unsealed) => Ok(unsealed),
|
State::Unsealed(unsealed) => Ok(unsealed),
|
||||||
State::Unbootstrapped => Err(Error::NotBootstrapped),
|
State::Unbootstrapped => Err(Error::NotBootstrapped),
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::{actors::vault, crypto::integrity::hashing::Hashable};
|
use crate::{
|
||||||
use arbiter_crypto::safecell::SafeCellHandle as _;
|
actors::vault::{self, GetState},
|
||||||
use hmac::{Hmac, Mac as _};
|
crypto::integrity::hashing::Hashable,
|
||||||
|
};
|
||||||
|
use hmac::Hmac;
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite};
|
use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite};
|
||||||
@@ -199,6 +201,11 @@ pub async fn verify_entity<E: Integrable>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn is_signing_available(vault: &ActorRef<Vault>) -> Result<bool, Error> {
|
||||||
|
let state = vault.ask(GetState).await.map_err(|_| Error::VaultSend)?;
|
||||||
|
Ok(matches!(state, vault::VaultState::Unsealed))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use diesel::{ExpressionMethods as _, QueryDsl};
|
use diesel::{ExpressionMethods as _, QueryDsl};
|
||||||
@@ -208,7 +215,10 @@ mod tests {
|
|||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::{GlobalActors, vault::{Bootstrap, Vault}},
|
actors::{
|
||||||
|
GlobalActors,
|
||||||
|
vault::{Bootstrap, Vault},
|
||||||
|
},
|
||||||
db::{self, schema},
|
db::{self, schema},
|
||||||
};
|
};
|
||||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use tonic::Status;
|
|||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::client::{ClientConnection, session::ClientSession},
|
|
||||||
grpc::request_tracker::RequestTracker,
|
grpc::request_tracker::RequestTracker,
|
||||||
|
peers::client::{ClientConnection, session::ClientSession},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ use tonic::Status;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::client::{self, ClientConnection, auth},
|
|
||||||
grpc::request_tracker::RequestTracker,
|
grpc::request_tracker::RequestTracker,
|
||||||
|
peers::client::{self, ClientConnection, auth},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AuthTransportAdapter<'a> {
|
pub struct AuthTransportAdapter<'a> {
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ use tonic::Status;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
|
|
||||||
grpc::{
|
grpc::{
|
||||||
Convert, TryConvert,
|
Convert, TryConvert,
|
||||||
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
||||||
},
|
},
|
||||||
|
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload {
|
fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ use tonic::Status;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
|
|
||||||
actors::vault::VaultState,
|
actors::vault::VaultState,
|
||||||
|
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) async fn dispatch(
|
pub(super) async fn dispatch(
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use tonic::{Request, Response, Status, async_trait};
|
|||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::{client::ClientConnection, user_agent::UserAgentConnection},
|
|
||||||
grpc::user_agent::start,
|
grpc::user_agent::start,
|
||||||
|
peers::{client::ClientConnection, user_agent::UserAgentConnection},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod request_tracker;
|
mod request_tracker;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ use tonic::Status;
|
|||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
|
|
||||||
grpc::request_tracker::RequestTracker,
|
grpc::request_tracker::RequestTracker,
|
||||||
|
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
@@ -124,7 +124,7 @@ pub async fn start(
|
|||||||
) {
|
) {
|
||||||
let mut request_tracker = RequestTracker::default();
|
let mut request_tracker = RequestTracker::default();
|
||||||
|
|
||||||
let pubkey = match auth::start(&mut conn, &mut bi, &mut request_tracker).await {
|
let (id, pubkey) = match auth::start(&mut conn, &mut bi, &mut request_tracker).await {
|
||||||
Ok(pubkey) => pubkey,
|
Ok(pubkey) => pubkey,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = ?e, "Authentication failed");
|
warn!(error = ?e, "Authentication failed");
|
||||||
@@ -132,13 +132,19 @@ pub async fn start(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info!(?pubkey, "User authenticated successfully");
|
||||||
|
|
||||||
let (oob_sender, oob_receiver) = mpsc::channel(16);
|
let (oob_sender, oob_receiver) = mpsc::channel(16);
|
||||||
let oob_adapter = OutOfBandAdapter(oob_sender);
|
let oob_adapter = OutOfBandAdapter(oob_sender);
|
||||||
|
|
||||||
let actor = UserAgentSession::spawn(UserAgentSession::new(conn, Box::new(oob_adapter)));
|
let actor = UserAgentSession::spawn(UserAgentSession::new(
|
||||||
|
conn,
|
||||||
|
id,
|
||||||
|
pubkey,
|
||||||
|
Box::new(oob_adapter),
|
||||||
|
));
|
||||||
let actor_for_cleanup = actor.clone();
|
let actor_for_cleanup = actor.clone();
|
||||||
|
|
||||||
info!(?pubkey, "User authenticated successfully");
|
|
||||||
dispatch_loop(bi, actor, oob_receiver, request_tracker).await;
|
dispatch_loop(bi, actor, oob_receiver, request_tracker).await;
|
||||||
actor_for_cleanup.kill();
|
actor_for_cleanup.kill();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ use tonic::Status;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peers::user_agent::{UserAgentConnection, auth},
|
|
||||||
grpc::request_tracker::RequestTracker,
|
grpc::request_tracker::RequestTracker,
|
||||||
|
peers::user_agent::{UserAgentConnection, auth},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AuthTransportAdapter<'a> {
|
pub struct AuthTransportAdapter<'a> {
|
||||||
@@ -140,7 +140,6 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
|
|||||||
AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest {
|
AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest {
|
||||||
pubkey,
|
pubkey,
|
||||||
bootstrap_token,
|
bootstrap_token,
|
||||||
key_type: _,
|
|
||||||
}) => {
|
}) => {
|
||||||
let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else {
|
let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else {
|
||||||
warn!(
|
warn!(
|
||||||
@@ -168,7 +167,7 @@ pub async fn start(
|
|||||||
conn: &mut UserAgentConnection,
|
conn: &mut UserAgentConnection,
|
||||||
bi: &mut GrpcBi<UserAgentRequest, UserAgentResponse>,
|
bi: &mut GrpcBi<UserAgentRequest, UserAgentResponse>,
|
||||||
request_tracker: &mut RequestTracker,
|
request_tracker: &mut RequestTracker,
|
||||||
) -> Result<authn::PublicKey, auth::Error> {
|
) -> Result<(i32, authn::PublicKey), auth::Error> {
|
||||||
let transport = AuthTransportAdapter::new(bi, request_tracker);
|
let transport = AuthTransportAdapter::new(bi, request_tracker);
|
||||||
auth::authenticate(conn, transport).await
|
auth::authenticate(conn, transport).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ use tonic::Status;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
grpc::{
|
||||||
|
Convert, TryConvert,
|
||||||
|
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
||||||
|
},
|
||||||
peers::user_agent::{
|
peers::user_agent::{
|
||||||
UserAgentSession,
|
UserAgentSession,
|
||||||
session::connection::{
|
session::connection::{
|
||||||
@@ -31,10 +35,6 @@ use crate::{
|
|||||||
SignTransactionError as SessionSignTransactionError,
|
SignTransactionError as SessionSignTransactionError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
grpc::{
|
|
||||||
Convert, TryConvert,
|
|
||||||
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload {
|
fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ use tonic::Status;
|
|||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
db::models::NewEvmWalletAccess,
|
||||||
|
grpc::Convert,
|
||||||
peers::user_agent::{
|
peers::user_agent::{
|
||||||
OutOfBand, UserAgentSession,
|
OutOfBand, UserAgentSession,
|
||||||
session::connection::{
|
session::connection::{
|
||||||
@@ -28,8 +30,6 @@ use crate::{
|
|||||||
HandleRevokeEvmWalletAccess, HandleSdkClientList,
|
HandleRevokeEvmWalletAccess, HandleSdkClientList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db::models::NewEvmWalletAccess,
|
|
||||||
grpc::Convert,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload {
|
fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload {
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
use crate::context::ServerContext;
|
use crate::context::ServerContext;
|
||||||
|
|
||||||
pub mod actors;
|
pub mod actors;
|
||||||
pub mod peers;
|
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod evm;
|
pub mod evm;
|
||||||
pub mod grpc;
|
pub mod grpc;
|
||||||
|
pub mod peers;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ use tracing::error;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::{
|
actors::{
|
||||||
GlobalActors, flow_coordinator::{self, RequestClientApproval}, vault::Vault
|
GlobalActors,
|
||||||
|
flow_coordinator::{self, RequestClientApproval},
|
||||||
|
vault::Vault,
|
||||||
},
|
},
|
||||||
crypto::integrity::{self, AttestationStatus},
|
crypto::integrity::{self, AttestationStatus},
|
||||||
db::{
|
db::{
|
||||||
@@ -187,10 +189,7 @@ async fn create_nonce(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn approve_new_client(
|
async fn approve_new_client(actors: &GlobalActors, profile: ClientProfile) -> Result<(), Error> {
|
||||||
actors: &GlobalActors,
|
|
||||||
profile: ClientProfile,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let result = actors
|
let result = actors
|
||||||
.flow_coordinator
|
.flow_coordinator
|
||||||
.ask(RequestClientApproval { client: profile })
|
.ask(RequestClientApproval { client: profile })
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ use tracing::{error, info};
|
|||||||
use crate::{
|
use crate::{
|
||||||
actors::GlobalActors,
|
actors::GlobalActors,
|
||||||
crypto::integrity::{Integrable, hashing::Hashable},
|
crypto::integrity::{Integrable, hashing::Hashable},
|
||||||
db, peers::client::session::ClientSession,
|
db,
|
||||||
|
peers::client::session::ClientSession,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
pub mod user_agent;
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
pub mod user_agent;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ fn parse_auth_event(payload: Inbound) -> AuthEvents {
|
|||||||
pub async fn authenticate<T>(
|
pub async fn authenticate<T>(
|
||||||
props: &mut UserAgentConnection,
|
props: &mut UserAgentConnection,
|
||||||
transport: T,
|
transport: T,
|
||||||
) -> Result<authn::PublicKey, Error>
|
) -> Result<(i32, authn::PublicKey), Error>
|
||||||
where
|
where
|
||||||
T: Bi<Inbound, Result<Outbound, Error>> + Send,
|
T: Bi<Inbound, Result<Outbound, Error>> + Send,
|
||||||
{
|
{
|
||||||
@@ -82,7 +82,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
match state.process_event(parse_auth_event(payload)).await {
|
match state.process_event(parse_auth_event(payload)).await {
|
||||||
Ok(AuthStates::AuthOk(key)) => return Ok(key.clone()),
|
Ok(AuthStates::AuthOk(result)) => return Ok((result.id, result.pubkey.clone())),
|
||||||
Err(AuthError::ActionFailed(err)) => {
|
Err(AuthError::ActionFailed(err)) => {
|
||||||
error!(?err, "State machine action failed");
|
error!(?err, "State machine action failed");
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
|
use super::super::{UserAgentConnection, UserAgentCredentials};
|
||||||
use arbiter_crypto::authn::{self, USERAGENT_CONTEXT};
|
use arbiter_crypto::authn::{self, USERAGENT_CONTEXT};
|
||||||
use arbiter_proto::transport::Bi;
|
use arbiter_proto::transport::Bi;
|
||||||
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update};
|
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update};
|
||||||
use diesel_async::{AsyncConnection, RunQueryDsl};
|
use diesel_async::{AsyncConnection, RunQueryDsl};
|
||||||
use kameo::actor::ActorRef;
|
use kameo::actor::ActorRef;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use super::super::{UserAgentCredentials, UserAgentConnection};
|
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use crate::peers::user_agent::auth::Outbound;
|
use crate::peers::user_agent::auth::Outbound;
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::{
|
actors::{bootstrap::ConsumeToken, vault::Vault},
|
||||||
bootstrap::ConsumeToken,
|
|
||||||
vault::Vault,
|
|
||||||
},
|
|
||||||
crypto::integrity,
|
crypto::integrity,
|
||||||
db::{DatabasePool, schema::useragent_client},
|
db::{DatabasePool, schema::useragent_client},
|
||||||
};
|
};
|
||||||
@@ -27,6 +24,7 @@ pub struct BootstrapAuthRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ChallengeContext {
|
pub struct ChallengeContext {
|
||||||
|
pub id: i32,
|
||||||
pub challenge_nonce: i32,
|
pub challenge_nonce: i32,
|
||||||
pub key: authn::PublicKey,
|
pub key: authn::PublicKey,
|
||||||
}
|
}
|
||||||
@@ -35,13 +33,18 @@ pub struct ChallengeSolution {
|
|||||||
pub solution: Vec<u8>,
|
pub solution: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AuthOk {
|
||||||
|
pub id: i32,
|
||||||
|
pub pubkey: authn::PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
smlang::statemachine!(
|
smlang::statemachine!(
|
||||||
name: Auth,
|
name: Auth,
|
||||||
custom_error: true,
|
custom_error: true,
|
||||||
transitions: {
|
transitions: {
|
||||||
*Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext),
|
*Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext),
|
||||||
Init + BootstrapAuthRequest(BootstrapAuthRequest) / async verify_bootstrap_token = AuthOk(authn::PublicKey),
|
Init + BootstrapAuthRequest(BootstrapAuthRequest) / async verify_bootstrap_token = AuthOk(AuthOk),
|
||||||
SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(authn::PublicKey),
|
SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(AuthOk),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -110,12 +113,12 @@ async fn create_nonce(
|
|||||||
db: &DatabasePool,
|
db: &DatabasePool,
|
||||||
vault: &ActorRef<Vault>,
|
vault: &ActorRef<Vault>,
|
||||||
pubkey: &authn::PublicKey,
|
pubkey: &authn::PublicKey,
|
||||||
) -> Result<i32, Error> {
|
) -> Result<(i32, i32), Error> {
|
||||||
let mut db_conn = db.get().await.map_err(|e| {
|
let mut db_conn = db.get().await.map_err(|e| {
|
||||||
error!(error = ?e, "Database pool error");
|
error!(error = ?e, "Database pool error");
|
||||||
Error::internal("Database unavailable")
|
Error::internal("Database unavailable")
|
||||||
})?;
|
})?;
|
||||||
let new_nonce = db_conn
|
let (id, new_nonce) = db_conn
|
||||||
.exclusive_transaction(|conn| {
|
.exclusive_transaction(|conn| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let (id, new_nonce): (i32, i32) = update(useragent_client::table)
|
let (id, new_nonce): (i32, i32) = update(useragent_client::table)
|
||||||
@@ -144,59 +147,36 @@ async fn create_nonce(
|
|||||||
Error::internal("Database error")
|
Error::internal("Database error")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Result::<_, Error>::Ok(new_nonce)
|
Result::<_, Error>::Ok((id, new_nonce))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
Ok(new_nonce)
|
Ok((id, new_nonce))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register_key(
|
async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result<i32, Error> {
|
||||||
db: &DatabasePool,
|
|
||||||
vault: &ActorRef<Vault>,
|
|
||||||
pubkey: &authn::PublicKey,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let pubkey_bytes = pubkey.to_bytes();
|
let pubkey_bytes = pubkey.to_bytes();
|
||||||
let mut conn = db.get().await.map_err(|e| {
|
let mut conn = db.get().await.map_err(|e| {
|
||||||
error!(error = ?e, "Database pool error");
|
error!(error = ?e, "Database pool error");
|
||||||
Error::internal("Database unavailable")
|
Error::internal("Database unavailable")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
conn.transaction(|conn| {
|
const NONCE_START: i32 = 1;
|
||||||
Box::pin(async move {
|
|
||||||
const NONCE_START: i32 = 1;
|
|
||||||
|
|
||||||
let id: i32 = diesel::insert_into(useragent_client::table)
|
let id: i32 = diesel::insert_into(useragent_client::table)
|
||||||
.values((
|
.values((
|
||||||
useragent_client::public_key.eq(pubkey_bytes),
|
useragent_client::public_key.eq(pubkey_bytes),
|
||||||
useragent_client::nonce.eq(NONCE_START),
|
useragent_client::nonce.eq(NONCE_START),
|
||||||
))
|
))
|
||||||
.returning(useragent_client::id)
|
.returning(useragent_client::id)
|
||||||
.get_result(conn)
|
.get_result(&mut conn)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!(error = ?e, "Database error");
|
error!(error = ?e, "Database error");
|
||||||
Error::internal("Database operation failed")
|
Error::internal("Database operation failed")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let entity = UserAgentCredentials {
|
Ok(id)
|
||||||
pubkey: pubkey.clone(),
|
|
||||||
nonce: NONCE_START,
|
|
||||||
};
|
|
||||||
|
|
||||||
integrity::sign_entity(conn, vault, &entity, id)
|
|
||||||
.await
|
|
||||||
.map_err(|e| {
|
|
||||||
error!(error = ?e, "Failed to sign integrity tag for new user-agent key");
|
|
||||||
Error::internal("Failed to register public key")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Result::<_, Error>::Ok(())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AuthContext<'a, T> {
|
pub struct AuthContext<'a, T> {
|
||||||
@@ -222,7 +202,7 @@ where
|
|||||||
) -> Result<ChallengeContext, Self::Error> {
|
) -> Result<ChallengeContext, Self::Error> {
|
||||||
verify_integrity(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
verify_integrity(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||||
|
|
||||||
let nonce = create_nonce(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
let (id, nonce) = create_nonce(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||||
|
|
||||||
self.transport
|
self.transport
|
||||||
.send(Ok(Outbound::AuthChallenge { nonce }))
|
.send(Ok(Outbound::AuthChallenge { nonce }))
|
||||||
@@ -233,6 +213,7 @@ where
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(ChallengeContext {
|
Ok(ChallengeContext {
|
||||||
|
id,
|
||||||
challenge_nonce: nonce,
|
challenge_nonce: nonce,
|
||||||
key: pubkey,
|
key: pubkey,
|
||||||
})
|
})
|
||||||
@@ -243,7 +224,7 @@ where
|
|||||||
async fn verify_bootstrap_token(
|
async fn verify_bootstrap_token(
|
||||||
&mut self,
|
&mut self,
|
||||||
BootstrapAuthRequest { pubkey, token }: BootstrapAuthRequest,
|
BootstrapAuthRequest { pubkey, token }: BootstrapAuthRequest,
|
||||||
) -> Result<authn::PublicKey, Self::Error> {
|
) -> Result<AuthOk, Self::Error> {
|
||||||
let token_ok: bool = self
|
let token_ok: bool = self
|
||||||
.conn
|
.conn
|
||||||
.actors
|
.actors
|
||||||
@@ -264,12 +245,12 @@ where
|
|||||||
|
|
||||||
match token_ok {
|
match token_ok {
|
||||||
true => {
|
true => {
|
||||||
register_key(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
let id = register_key(&self.conn.db, &pubkey).await?;
|
||||||
self.transport
|
self.transport
|
||||||
.send(Ok(Outbound::AuthSuccess))
|
.send(Ok(Outbound::AuthSuccess))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| Error::Transport)?;
|
.map_err(|_| Error::Transport)?;
|
||||||
Ok(pubkey)
|
Ok(AuthOk { id, pubkey })
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
error!("Invalid bootstrap token provided");
|
error!("Invalid bootstrap token provided");
|
||||||
@@ -287,11 +268,12 @@ where
|
|||||||
async fn verify_solution(
|
async fn verify_solution(
|
||||||
&mut self,
|
&mut self,
|
||||||
ChallengeContext {
|
ChallengeContext {
|
||||||
|
id,
|
||||||
challenge_nonce,
|
challenge_nonce,
|
||||||
key,
|
key,
|
||||||
}: &ChallengeContext,
|
}: &ChallengeContext,
|
||||||
ChallengeSolution { solution }: ChallengeSolution,
|
ChallengeSolution { solution }: ChallengeSolution,
|
||||||
) -> Result<authn::PublicKey, Self::Error> {
|
) -> Result<AuthOk, Self::Error> {
|
||||||
let signature = authn::Signature::try_from(solution.as_slice()).map_err(|_| {
|
let signature = authn::Signature::try_from(solution.as_slice()).map_err(|_| {
|
||||||
error!("Failed to decode signature in challenge solution");
|
error!("Failed to decode signature in challenge solution");
|
||||||
Error::InvalidChallengeSolution
|
Error::InvalidChallengeSolution
|
||||||
@@ -305,7 +287,7 @@ where
|
|||||||
.send(Ok(Outbound::AuthSuccess))
|
.send(Ok(Outbound::AuthSuccess))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| Error::Transport)?;
|
.map_err(|_| Error::Transport)?;
|
||||||
Ok(key.clone())
|
Ok(AuthOk { id: *id, pubkey: key.clone() })
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
self.transport
|
self.transport
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
actors::GlobalActors,
|
actors::GlobalActors, crypto::integrity::Integrable, db, peers::client::ClientProfile,
|
||||||
crypto::integrity::Integrable,
|
|
||||||
db, peers::client::ClientProfile,
|
|
||||||
};
|
};
|
||||||
use arbiter_crypto::authn;
|
use arbiter_crypto::authn;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
use arbiter_crypto::authn;
|
use arbiter_crypto::authn;
|
||||||
|
use diesel::{ExpressionMethods, QueryDsl};
|
||||||
|
use diesel_async::{AsyncConnection, RunQueryDsl};
|
||||||
|
use kameo_actors::message_bus::Register;
|
||||||
|
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
|
|
||||||
use arbiter_proto::transport::Sender;
|
use arbiter_proto::transport::Sender;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use kameo::{Actor, actor::ActorRef, messages};
|
use kameo::{Actor, actor::ActorRef, messages, prelude::Message};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{actors::flow_coordinator::{RegisterUserAgent, client_connect_approval::ClientApprovalController}, peers::client::ClientProfile};
|
use crate::{
|
||||||
|
actors::{
|
||||||
|
flow_coordinator::{RegisterUserAgent, client_connect_approval::ClientApprovalController},
|
||||||
|
vault::events,
|
||||||
|
}, crypto::integrity, db::schema::useragent_client, peers::{client::ClientProfile, user_agent::UserAgentCredentials}
|
||||||
|
};
|
||||||
mod state;
|
mod state;
|
||||||
use state::{DummyContext, UserAgentEvents, UserAgentStateMachine};
|
use state::{DummyContext, UserAgentEvents, UserAgentStateMachine};
|
||||||
|
|
||||||
@@ -50,6 +58,8 @@ pub struct PendingClientApproval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserAgentSession {
|
pub struct UserAgentSession {
|
||||||
|
id: i32,
|
||||||
|
pubkey: authn::PublicKey,
|
||||||
props: UserAgentConnection,
|
props: UserAgentConnection,
|
||||||
state: UserAgentStateMachine<DummyContext>,
|
state: UserAgentStateMachine<DummyContext>,
|
||||||
sender: Box<dyn Sender<OutOfBand>>,
|
sender: Box<dyn Sender<OutOfBand>>,
|
||||||
@@ -60,31 +70,22 @@ pub struct UserAgentSession {
|
|||||||
pub mod connection;
|
pub mod connection;
|
||||||
|
|
||||||
impl UserAgentSession {
|
impl UserAgentSession {
|
||||||
pub(crate) fn new(props: UserAgentConnection, sender: Box<dyn Sender<OutOfBand>>) -> Self {
|
pub(crate) fn new(
|
||||||
|
props: UserAgentConnection,
|
||||||
|
id: i32,
|
||||||
|
pubkey: authn::PublicKey,
|
||||||
|
sender: Box<dyn Sender<OutOfBand>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
id,
|
||||||
props,
|
props,
|
||||||
|
pubkey,
|
||||||
state: UserAgentStateMachine::new(DummyContext),
|
state: UserAgentStateMachine::new(DummyContext),
|
||||||
sender,
|
sender,
|
||||||
pending_client_approvals: Default::default(),
|
pending_client_approvals: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_test(db: crate::db::DatabasePool, actors: crate::actors::GlobalActors) -> Self {
|
|
||||||
struct DummySender;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Sender<OutOfBand> for DummySender {
|
|
||||||
async fn send(
|
|
||||||
&mut self,
|
|
||||||
_item: OutOfBand,
|
|
||||||
) -> Result<(), arbiter_proto::transport::Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::new(UserAgentConnection::new(db, actors), Box::new(DummySender))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transition(&mut self, event: UserAgentEvents) -> Result<(), Error> {
|
fn transition(&mut self, event: UserAgentEvents) -> Result<(), Error> {
|
||||||
self.state.process_event(event).map_err(|e| {
|
self.state.process_event(event).map_err(|e| {
|
||||||
error!(?e, "State transition failed");
|
error!(?e, "State transition failed");
|
||||||
@@ -127,6 +128,61 @@ impl UserAgentSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Message<events::VaultBootstrapped> for UserAgentSession {
|
||||||
|
type Reply = Result<(), Error>;
|
||||||
|
|
||||||
|
async fn handle(
|
||||||
|
&mut self,
|
||||||
|
_: events::VaultBootstrapped,
|
||||||
|
ctx: &mut kameo::prelude::Context<Self, Self::Reply>,
|
||||||
|
) -> Self::Reply {
|
||||||
|
let Ok(mut conn) = self.props.db.get().await else {
|
||||||
|
error!("Failed to get database connection for vault bootstrapped event");
|
||||||
|
ctx.stop();
|
||||||
|
return Err(Error::internal("Failed to get database connection"));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let result = conn.exclusive_transaction(|conn| {
|
||||||
|
Box::pin(async {
|
||||||
|
let nonce: i32 = useragent_client::table
|
||||||
|
.filter(useragent_client::id.eq(self.id))
|
||||||
|
.select(useragent_client::nonce)
|
||||||
|
.first::<i32>(conn)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
error!(?e, "Failed to get nonce for useragent bootstrapping");
|
||||||
|
Error::internal("Failed to sign user agent credentials")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let entity = UserAgentCredentials {
|
||||||
|
pubkey: self.pubkey.clone(),
|
||||||
|
nonce,
|
||||||
|
};
|
||||||
|
|
||||||
|
integrity::sign_entity(conn, &self.props.actors.vault, &entity, self.id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
error!(?e, "Failed to sign user agent credentials during vault bootstrapping");
|
||||||
|
Error::internal("Failed to sign user agent credentials")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Result::<_, Error>::Ok(())
|
||||||
|
})
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
error!(?err, "Error during vault bootstrapping");
|
||||||
|
ctx.stop();
|
||||||
|
Err(err)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Actor for UserAgentSession {
|
impl Actor for UserAgentSession {
|
||||||
type Args = Self;
|
type Args = Self;
|
||||||
|
|
||||||
@@ -136,6 +192,21 @@ impl Actor for UserAgentSession {
|
|||||||
args: Self::Args,
|
args: Self::Args,
|
||||||
this: kameo::prelude::ActorRef<Self>,
|
this: kameo::prelude::ActorRef<Self>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
|
args.props
|
||||||
|
.actors
|
||||||
|
.events
|
||||||
|
.tell(Register(
|
||||||
|
this.clone().recipient::<events::VaultBootstrapped>(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
error!(
|
||||||
|
?err,
|
||||||
|
"Failed to register user agent connection with event bus"
|
||||||
|
);
|
||||||
|
Error::internal("Failed to register user agent connection with event bus")
|
||||||
|
})?;
|
||||||
|
|
||||||
args.props
|
args.props
|
||||||
.actors
|
.actors
|
||||||
.flow_coordinator
|
.flow_coordinator
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use kameo::prelude::Context;
|
|||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
use x25519_dalek::{EphemeralSecret, PublicKey};
|
use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||||
|
|
||||||
use crate::{actors::vault::VaultState, peers::user_agent::session::state::{UnsealContext, UserAgentEvents}};
|
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
|
||||||
use crate::actors::{
|
use crate::actors::{
|
||||||
evm::{
|
evm::{
|
||||||
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
|
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
|
||||||
@@ -27,10 +27,11 @@ use crate::db::models::{
|
|||||||
};
|
};
|
||||||
use crate::evm::policies::{Grant, SpecificGrant};
|
use crate::evm::policies::{Grant, SpecificGrant};
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer,
|
actors::vault::VaultState,
|
||||||
|
peers::user_agent::session::state::{UnsealContext, UserAgentEvents},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{UserAgentSession, state, Error};
|
use super::{Error, UserAgentSession, state};
|
||||||
|
|
||||||
impl UserAgentSession {
|
impl UserAgentSession {
|
||||||
fn take_unseal_secret(&mut self) -> Result<(EphemeralSecret, PublicKey), Error> {
|
fn take_unseal_secret(&mut self) -> Result<(EphemeralSecret, PublicKey), Error> {
|
||||||
|
|||||||
@@ -5,14 +5,10 @@ use arbiter_crypto::{
|
|||||||
use arbiter_proto::ClientMetadata;
|
use arbiter_proto::ClientMetadata;
|
||||||
use arbiter_proto::transport::{Receiver, Sender};
|
use arbiter_proto::transport::{Receiver, Sender};
|
||||||
use arbiter_server::{
|
use arbiter_server::{
|
||||||
actors::{
|
actors::{GlobalActors, vault::Bootstrap},
|
||||||
GlobalActors,
|
|
||||||
|
|
||||||
vault::Bootstrap,
|
|
||||||
},
|
|
||||||
peers::client::{ClientConnection, ClientCredentials, auth, connect_client},
|
|
||||||
crypto::integrity,
|
crypto::integrity,
|
||||||
db::{self, schema},
|
db::{self, schema},
|
||||||
|
peers::client::{ClientConnection, ClientCredentials, auth, connect_client},
|
||||||
};
|
};
|
||||||
use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into};
|
use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ use tokio::sync::mpsc;
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault {
|
pub async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault {
|
||||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
actor
|
actor
|
||||||
.bootstrap(SafeCell::new(b"test-seal-key".to_vec()))
|
.bootstrap(SafeCell::new(b"test-seal-key".to_vec()))
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -5,15 +5,10 @@ use arbiter_crypto::{
|
|||||||
|
|
||||||
use arbiter_proto::transport::{Receiver, Sender};
|
use arbiter_proto::transport::{Receiver, Sender};
|
||||||
use arbiter_server::{
|
use arbiter_server::{
|
||||||
actors::{
|
actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap},
|
||||||
GlobalActors,
|
|
||||||
bootstrap::GetToken,
|
|
||||||
vault::Bootstrap,
|
|
||||||
|
|
||||||
},
|
|
||||||
peers::user_agent::{UserAgentConnection, UserAgentCredentials, auth},
|
|
||||||
crypto::integrity,
|
crypto::integrity,
|
||||||
db::{self, schema},
|
db::{self, schema},
|
||||||
|
peers::user_agent::{UserAgentConnection, UserAgentCredentials, auth},
|
||||||
};
|
};
|
||||||
use diesel::{ExpressionMethods as _, QueryDsl, insert_into};
|
use diesel::{ExpressionMethods as _, QueryDsl, insert_into};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ use arbiter_server::{
|
|||||||
actors::{
|
actors::{
|
||||||
GlobalActors,
|
GlobalActors,
|
||||||
vault::{Bootstrap, Seal},
|
vault::{Bootstrap, Seal},
|
||||||
|
|
||||||
},
|
},
|
||||||
peers::user_agent::{
|
|
||||||
UserAgentSession,
|
|
||||||
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
|
||||||
},
|
|
||||||
db,
|
db,
|
||||||
|
peers::user_agent::{
|
||||||
|
UserAgentSession,
|
||||||
|
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
|
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ use std::collections::{HashMap, HashSet};
|
|||||||
|
|
||||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||||
use arbiter_server::{
|
use arbiter_server::{
|
||||||
actors::{GlobalActors, vault::{CreateNew, Error, Vault}},
|
actors::{
|
||||||
|
GlobalActors,
|
||||||
|
vault::{CreateNew, Error, Vault},
|
||||||
|
},
|
||||||
db::{self, models, schema},
|
db::{self, models, schema},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,7 +164,9 @@ async fn decrypt_roundtrip_after_high_concurrency() {
|
|||||||
let writes = write_concurrently(actor, "roundtrip", 40).await;
|
let writes = write_concurrently(actor, "roundtrip", 40).await;
|
||||||
let expected: HashMap<i32, Vec<u8>> = writes.into_iter().collect();
|
let expected: HashMap<i32, Vec<u8>> = writes.into_iter().collect();
|
||||||
|
|
||||||
let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
decryptor
|
decryptor
|
||||||
.try_unseal(SafeCell::new(b"test-seal-key".to_vec()))
|
.try_unseal(SafeCell::new(b"test-seal-key".to_vec()))
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||||
use arbiter_server::{
|
use arbiter_server::{
|
||||||
actors::{GlobalActors, vault::{Error, Vault}},
|
actors::{
|
||||||
|
GlobalActors,
|
||||||
|
vault::{Error, Vault},
|
||||||
|
},
|
||||||
crypto::encryption::v1::{Nonce, ROOT_KEY_TAG},
|
crypto::encryption::v1::{Nonce, ROOT_KEY_TAG},
|
||||||
db::{self, models, schema},
|
db::{self, models, schema},
|
||||||
peers::user_agent::{
|
|
||||||
UserAgentSession,
|
|
||||||
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use diesel::{QueryDsl, SelectableHelper};
|
use diesel::{QueryDsl, SelectableHelper};
|
||||||
@@ -18,7 +17,9 @@ use crate::common;
|
|||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
async fn test_bootstrap() {
|
async fn test_bootstrap() {
|
||||||
let db = db::create_test_pool().await;
|
let db = db::create_test_pool().await;
|
||||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
||||||
actor.bootstrap(seal_key).await.unwrap();
|
actor.bootstrap(seal_key).await.unwrap();
|
||||||
@@ -52,7 +53,9 @@ async fn test_bootstrap_rejects_double() {
|
|||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
async fn test_create_new_before_bootstrap_fails() {
|
async fn test_create_new_before_bootstrap_fails() {
|
||||||
let db = db::create_test_pool().await;
|
let db = db::create_test_pool().await;
|
||||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let err = actor
|
let err = actor
|
||||||
.create_new(SafeCell::new(b"data".to_vec()))
|
.create_new(SafeCell::new(b"data".to_vec()))
|
||||||
@@ -65,7 +68,9 @@ async fn test_create_new_before_bootstrap_fails() {
|
|||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
async fn test_decrypt_before_bootstrap_fails() {
|
async fn test_decrypt_before_bootstrap_fails() {
|
||||||
let db = db::create_test_pool().await;
|
let db = db::create_test_pool().await;
|
||||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let err = actor.decrypt(1).await.unwrap_err();
|
let err = actor.decrypt(1).await.unwrap_err();
|
||||||
assert!(matches!(err, Error::NotBootstrapped));
|
assert!(matches!(err, Error::NotBootstrapped));
|
||||||
@@ -78,7 +83,9 @@ async fn test_new_restores_sealed_state() {
|
|||||||
let actor = common::bootstrapped_vault(&db).await;
|
let actor = common::bootstrapped_vault(&db).await;
|
||||||
drop(actor);
|
drop(actor);
|
||||||
|
|
||||||
let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let err = actor2.decrypt(1).await.unwrap_err();
|
let err = actor2.decrypt(1).await.unwrap_err();
|
||||||
assert!(matches!(err, Error::NotBootstrapped));
|
assert!(matches!(err, Error::NotBootstrapped));
|
||||||
}
|
}
|
||||||
@@ -96,7 +103,9 @@ async fn test_unseal_correct_password() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
drop(actor);
|
drop(actor);
|
||||||
|
|
||||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
||||||
actor.try_unseal(seal_key).await.unwrap();
|
actor.try_unseal(seal_key).await.unwrap();
|
||||||
|
|
||||||
@@ -117,7 +126,9 @@ async fn test_unseal_wrong_then_correct_password() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
drop(actor);
|
drop(actor);
|
||||||
|
|
||||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let bad_key = SafeCell::new(b"wrong-password".to_vec());
|
let bad_key = SafeCell::new(b"wrong-password".to_vec());
|
||||||
let err = actor.try_unseal(bad_key).await.unwrap_err();
|
let err = actor.try_unseal(bad_key).await.unwrap_err();
|
||||||
|
|||||||
@@ -61,11 +61,6 @@ Future<Connection> connectAndAuthorize(
|
|||||||
final req = ua_auth.AuthChallengeRequest(
|
final req = ua_auth.AuthChallengeRequest(
|
||||||
pubkey: pubkey,
|
pubkey: pubkey,
|
||||||
bootstrapToken: bootstrapToken,
|
bootstrapToken: bootstrapToken,
|
||||||
keyType: switch (key.alg) {
|
|
||||||
KeyAlgorithm.rsa => ua_auth.KeyType.KEY_TYPE_RSA,
|
|
||||||
KeyAlgorithm.ecdsa => ua_auth.KeyType.KEY_TYPE_ECDSA_SECP256K1,
|
|
||||||
KeyAlgorithm.ed25519 => ua_auth.KeyType.KEY_TYPE_ED25519,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
final response = await connection.ask(
|
final response = await connection.ask(
|
||||||
UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)),
|
UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)),
|
||||||
|
|||||||
@@ -414,6 +414,79 @@ class GasLimitExceededViolation extends $pb.GeneratedMessage {
|
|||||||
void clearMaxPriorityFeePerGas() => $_clearField(2);
|
void clearMaxPriorityFeePerGas() => $_clearField(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EvalViolation_ChainIdMismatch extends $pb.GeneratedMessage {
|
||||||
|
factory EvalViolation_ChainIdMismatch({
|
||||||
|
$fixnum.Int64? expected,
|
||||||
|
$fixnum.Int64? actual,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (expected != null) result.expected = expected;
|
||||||
|
if (actual != null) result.actual = actual;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvalViolation_ChainIdMismatch._();
|
||||||
|
|
||||||
|
factory EvalViolation_ChainIdMismatch.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory EvalViolation_ChainIdMismatch.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'EvalViolation.ChainIdMismatch',
|
||||||
|
package:
|
||||||
|
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..a<$fixnum.Int64>(
|
||||||
|
1, _omitFieldNames ? '' : 'expected', $pb.PbFieldType.OU6,
|
||||||
|
defaultOrMaker: $fixnum.Int64.ZERO)
|
||||||
|
..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'actual', $pb.PbFieldType.OU6,
|
||||||
|
defaultOrMaker: $fixnum.Int64.ZERO)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
EvalViolation_ChainIdMismatch clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
EvalViolation_ChainIdMismatch copyWith(
|
||||||
|
void Function(EvalViolation_ChainIdMismatch) updates) =>
|
||||||
|
super.copyWith(
|
||||||
|
(message) => updates(message as EvalViolation_ChainIdMismatch))
|
||||||
|
as EvalViolation_ChainIdMismatch;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EvalViolation_ChainIdMismatch create() =>
|
||||||
|
EvalViolation_ChainIdMismatch._();
|
||||||
|
@$core.override
|
||||||
|
EvalViolation_ChainIdMismatch createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EvalViolation_ChainIdMismatch getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<EvalViolation_ChainIdMismatch>(create);
|
||||||
|
static EvalViolation_ChainIdMismatch? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$fixnum.Int64 get expected => $_getI64(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set expected($fixnum.Int64 value) => $_setInt64(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasExpected() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearExpected() => $_clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$fixnum.Int64 get actual => $_getI64(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set actual($fixnum.Int64 value) => $_setInt64(1, value);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasActual() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearActual() => $_clearField(2);
|
||||||
|
}
|
||||||
|
|
||||||
enum EvalViolation_Kind {
|
enum EvalViolation_Kind {
|
||||||
invalidTarget,
|
invalidTarget,
|
||||||
gasLimitExceeded,
|
gasLimitExceeded,
|
||||||
@@ -421,6 +494,7 @@ enum EvalViolation_Kind {
|
|||||||
volumetricLimitExceeded,
|
volumetricLimitExceeded,
|
||||||
invalidTime,
|
invalidTime,
|
||||||
invalidTransactionType,
|
invalidTransactionType,
|
||||||
|
chainIdMismatch,
|
||||||
notSet
|
notSet
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,6 +506,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
$0.Empty? volumetricLimitExceeded,
|
$0.Empty? volumetricLimitExceeded,
|
||||||
$0.Empty? invalidTime,
|
$0.Empty? invalidTime,
|
||||||
$0.Empty? invalidTransactionType,
|
$0.Empty? invalidTransactionType,
|
||||||
|
EvalViolation_ChainIdMismatch? chainIdMismatch,
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (invalidTarget != null) result.invalidTarget = invalidTarget;
|
if (invalidTarget != null) result.invalidTarget = invalidTarget;
|
||||||
@@ -442,6 +517,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
if (invalidTime != null) result.invalidTime = invalidTime;
|
if (invalidTime != null) result.invalidTime = invalidTime;
|
||||||
if (invalidTransactionType != null)
|
if (invalidTransactionType != null)
|
||||||
result.invalidTransactionType = invalidTransactionType;
|
result.invalidTransactionType = invalidTransactionType;
|
||||||
|
if (chainIdMismatch != null) result.chainIdMismatch = chainIdMismatch;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,6 +538,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
4: EvalViolation_Kind.volumetricLimitExceeded,
|
4: EvalViolation_Kind.volumetricLimitExceeded,
|
||||||
5: EvalViolation_Kind.invalidTime,
|
5: EvalViolation_Kind.invalidTime,
|
||||||
6: EvalViolation_Kind.invalidTransactionType,
|
6: EvalViolation_Kind.invalidTransactionType,
|
||||||
|
7: EvalViolation_Kind.chainIdMismatch,
|
||||||
0: EvalViolation_Kind.notSet
|
0: EvalViolation_Kind.notSet
|
||||||
};
|
};
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
@@ -469,7 +546,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
package:
|
package:
|
||||||
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
|
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
|
||||||
createEmptyInstance: create)
|
createEmptyInstance: create)
|
||||||
..oo(0, [1, 2, 3, 4, 5, 6])
|
..oo(0, [1, 2, 3, 4, 5, 6, 7])
|
||||||
..a<$core.List<$core.int>>(
|
..a<$core.List<$core.int>>(
|
||||||
1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY)
|
1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY)
|
||||||
..aOM<GasLimitExceededViolation>(
|
..aOM<GasLimitExceededViolation>(
|
||||||
@@ -483,6 +560,9 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
subBuilder: $0.Empty.create)
|
subBuilder: $0.Empty.create)
|
||||||
..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType',
|
..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType',
|
||||||
subBuilder: $0.Empty.create)
|
subBuilder: $0.Empty.create)
|
||||||
|
..aOM<EvalViolation_ChainIdMismatch>(
|
||||||
|
7, _omitFieldNames ? '' : 'chainIdMismatch',
|
||||||
|
subBuilder: EvalViolation_ChainIdMismatch.create)
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
@@ -510,6 +590,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
|
@$pb.TagNumber(7)
|
||||||
EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!;
|
EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!;
|
||||||
@$pb.TagNumber(1)
|
@$pb.TagNumber(1)
|
||||||
@$pb.TagNumber(2)
|
@$pb.TagNumber(2)
|
||||||
@@ -517,6 +598,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
|
@$pb.TagNumber(7)
|
||||||
void clearKind() => $_clearField($_whichOneof(0));
|
void clearKind() => $_clearField($_whichOneof(0));
|
||||||
|
|
||||||
@$pb.TagNumber(1)
|
@$pb.TagNumber(1)
|
||||||
@@ -582,6 +664,18 @@ class EvalViolation extends $pb.GeneratedMessage {
|
|||||||
void clearInvalidTransactionType() => $_clearField(6);
|
void clearInvalidTransactionType() => $_clearField(6);
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
$0.Empty ensureInvalidTransactionType() => $_ensure(5);
|
$0.Empty ensureInvalidTransactionType() => $_ensure(5);
|
||||||
|
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
EvalViolation_ChainIdMismatch get chainIdMismatch => $_getN(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
set chainIdMismatch(EvalViolation_ChainIdMismatch value) =>
|
||||||
|
$_setField(7, value);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$core.bool hasChainIdMismatch() => $_has(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
void clearChainIdMismatch() => $_clearField(7);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
EvalViolation_ChainIdMismatch ensureChainIdMismatch() => $_ensure(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction was classified but no grant covers it
|
/// Transaction was classified but no grant covers it
|
||||||
|
|||||||
@@ -195,12 +195,31 @@ const EvalViolation$json = {
|
|||||||
'9': 0,
|
'9': 0,
|
||||||
'10': 'invalidTransactionType'
|
'10': 'invalidTransactionType'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'1': 'chain_id_mismatch',
|
||||||
|
'3': 7,
|
||||||
|
'4': 1,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.arbiter.shared.evm.EvalViolation.ChainIdMismatch',
|
||||||
|
'9': 0,
|
||||||
|
'10': 'chainIdMismatch'
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
'3': [EvalViolation_ChainIdMismatch$json],
|
||||||
'8': [
|
'8': [
|
||||||
{'1': 'kind'},
|
{'1': 'kind'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use evalViolationDescriptor instead')
|
||||||
|
const EvalViolation_ChainIdMismatch$json = {
|
||||||
|
'1': 'ChainIdMismatch',
|
||||||
|
'2': [
|
||||||
|
{'1': 'expected', '3': 1, '4': 1, '5': 4, '10': 'expected'},
|
||||||
|
{'1': 'actual', '3': 2, '4': 1, '5': 4, '10': 'actual'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
|
||||||
'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX'
|
'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX'
|
||||||
@@ -211,7 +230,10 @@ final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
|
|||||||
'YuRW1wdHlIAFIXdm9sdW1ldHJpY0xpbWl0RXhjZWVkZWQSOwoMaW52YWxpZF90aW1lGAUgASgL'
|
'YuRW1wdHlIAFIXdm9sdW1ldHJpY0xpbWl0RXhjZWVkZWQSOwoMaW52YWxpZF90aW1lGAUgASgL'
|
||||||
'MhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSC2ludmFsaWRUaW1lElIKGGludmFsaWRfdHJhbn'
|
'MhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSC2ludmFsaWRUaW1lElIKGGludmFsaWRfdHJhbn'
|
||||||
'NhY3Rpb25fdHlwZRgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhZpbnZhbGlkVHJh'
|
'NhY3Rpb25fdHlwZRgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhZpbnZhbGlkVHJh'
|
||||||
'bnNhY3Rpb25UeXBlQgYKBGtpbmQ=');
|
'bnNhY3Rpb25UeXBlEl8KEWNoYWluX2lkX21pc21hdGNoGAcgASgLMjEuYXJiaXRlci5zaGFyZW'
|
||||||
|
'QuZXZtLkV2YWxWaW9sYXRpb24uQ2hhaW5JZE1pc21hdGNoSABSD2NoYWluSWRNaXNtYXRjaBpF'
|
||||||
|
'Cg9DaGFpbklkTWlzbWF0Y2gSGgoIZXhwZWN0ZWQYASABKARSCGV4cGVjdGVkEhYKBmFjdHVhbB'
|
||||||
|
'gCIAEoBFIGYWN0dWFsQgYKBGtpbmQ=');
|
||||||
|
|
||||||
@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead')
|
@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead')
|
||||||
const NoMatchingGrantError$json = {
|
const NoMatchingGrantError$json = {
|
||||||
|
|||||||
@@ -24,12 +24,10 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
|||||||
factory AuthChallengeRequest({
|
factory AuthChallengeRequest({
|
||||||
$core.List<$core.int>? pubkey,
|
$core.List<$core.int>? pubkey,
|
||||||
$core.String? bootstrapToken,
|
$core.String? bootstrapToken,
|
||||||
KeyType? keyType,
|
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (pubkey != null) result.pubkey = pubkey;
|
if (pubkey != null) result.pubkey = pubkey;
|
||||||
if (bootstrapToken != null) result.bootstrapToken = bootstrapToken;
|
if (bootstrapToken != null) result.bootstrapToken = bootstrapToken;
|
||||||
if (keyType != null) result.keyType = keyType;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,8 +48,6 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
|||||||
..a<$core.List<$core.int>>(
|
..a<$core.List<$core.int>>(
|
||||||
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
|
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
|
||||||
..aOS(2, _omitFieldNames ? '' : 'bootstrapToken')
|
..aOS(2, _omitFieldNames ? '' : 'bootstrapToken')
|
||||||
..aE<KeyType>(3, _omitFieldNames ? '' : 'keyType',
|
|
||||||
enumValues: KeyType.values)
|
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
@@ -90,15 +86,6 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
|||||||
$core.bool hasBootstrapToken() => $_has(1);
|
$core.bool hasBootstrapToken() => $_has(1);
|
||||||
@$pb.TagNumber(2)
|
@$pb.TagNumber(2)
|
||||||
void clearBootstrapToken() => $_clearField(2);
|
void clearBootstrapToken() => $_clearField(2);
|
||||||
|
|
||||||
@$pb.TagNumber(3)
|
|
||||||
KeyType get keyType => $_getN(2);
|
|
||||||
@$pb.TagNumber(3)
|
|
||||||
set keyType(KeyType value) => $_setField(3, value);
|
|
||||||
@$pb.TagNumber(3)
|
|
||||||
$core.bool hasKeyType() => $_has(2);
|
|
||||||
@$pb.TagNumber(3)
|
|
||||||
void clearKeyType() => $_clearField(3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthChallenge extends $pb.GeneratedMessage {
|
class AuthChallenge extends $pb.GeneratedMessage {
|
||||||
|
|||||||
@@ -14,31 +14,6 @@ import 'dart:core' as $core;
|
|||||||
|
|
||||||
import 'package:protobuf/protobuf.dart' as $pb;
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
class KeyType extends $pb.ProtobufEnum {
|
|
||||||
static const KeyType KEY_TYPE_UNSPECIFIED =
|
|
||||||
KeyType._(0, _omitEnumNames ? '' : 'KEY_TYPE_UNSPECIFIED');
|
|
||||||
static const KeyType KEY_TYPE_ED25519 =
|
|
||||||
KeyType._(1, _omitEnumNames ? '' : 'KEY_TYPE_ED25519');
|
|
||||||
static const KeyType KEY_TYPE_ECDSA_SECP256K1 =
|
|
||||||
KeyType._(2, _omitEnumNames ? '' : 'KEY_TYPE_ECDSA_SECP256K1');
|
|
||||||
static const KeyType KEY_TYPE_RSA =
|
|
||||||
KeyType._(3, _omitEnumNames ? '' : 'KEY_TYPE_RSA');
|
|
||||||
|
|
||||||
static const $core.List<KeyType> values = <KeyType>[
|
|
||||||
KEY_TYPE_UNSPECIFIED,
|
|
||||||
KEY_TYPE_ED25519,
|
|
||||||
KEY_TYPE_ECDSA_SECP256K1,
|
|
||||||
KEY_TYPE_RSA,
|
|
||||||
];
|
|
||||||
|
|
||||||
static final $core.List<KeyType?> _byValue =
|
|
||||||
$pb.ProtobufEnum.$_initByValueList(values, 3);
|
|
||||||
static KeyType? valueOf($core.int value) =>
|
|
||||||
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
|
||||||
|
|
||||||
const KeyType._(super.value, super.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
class AuthResult extends $pb.ProtobufEnum {
|
class AuthResult extends $pb.ProtobufEnum {
|
||||||
static const AuthResult AUTH_RESULT_UNSPECIFIED =
|
static const AuthResult AUTH_RESULT_UNSPECIFIED =
|
||||||
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');
|
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');
|
||||||
|
|||||||
@@ -15,22 +15,6 @@ import 'dart:convert' as $convert;
|
|||||||
import 'dart:core' as $core;
|
import 'dart:core' as $core;
|
||||||
import 'dart:typed_data' as $typed_data;
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
@$core.Deprecated('Use keyTypeDescriptor instead')
|
|
||||||
const KeyType$json = {
|
|
||||||
'1': 'KeyType',
|
|
||||||
'2': [
|
|
||||||
{'1': 'KEY_TYPE_UNSPECIFIED', '2': 0},
|
|
||||||
{'1': 'KEY_TYPE_ED25519', '2': 1},
|
|
||||||
{'1': 'KEY_TYPE_ECDSA_SECP256K1', '2': 2},
|
|
||||||
{'1': 'KEY_TYPE_RSA', '2': 3},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Descriptor for `KeyType`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
|
||||||
final $typed_data.Uint8List keyTypeDescriptor = $convert.base64Decode(
|
|
||||||
'CgdLZXlUeXBlEhgKFEtFWV9UWVBFX1VOU1BFQ0lGSUVEEAASFAoQS0VZX1RZUEVfRUQyNTUxOR'
|
|
||||||
'ABEhwKGEtFWV9UWVBFX0VDRFNBX1NFQ1AyNTZLMRACEhAKDEtFWV9UWVBFX1JTQRAD');
|
|
||||||
|
|
||||||
@$core.Deprecated('Use authResultDescriptor instead')
|
@$core.Deprecated('Use authResultDescriptor instead')
|
||||||
const AuthResult$json = {
|
const AuthResult$json = {
|
||||||
'1': 'AuthResult',
|
'1': 'AuthResult',
|
||||||
@@ -67,14 +51,6 @@ const AuthChallengeRequest$json = {
|
|||||||
'10': 'bootstrapToken',
|
'10': 'bootstrapToken',
|
||||||
'17': true
|
'17': true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'1': 'key_type',
|
|
||||||
'3': 3,
|
|
||||||
'4': 1,
|
|
||||||
'5': 14,
|
|
||||||
'6': '.arbiter.user_agent.auth.KeyType',
|
|
||||||
'10': 'keyType'
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
'8': [
|
'8': [
|
||||||
{'1': '_bootstrap_token'},
|
{'1': '_bootstrap_token'},
|
||||||
@@ -84,9 +60,8 @@ const AuthChallengeRequest$json = {
|
|||||||
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
|
||||||
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIsCg9ib290c3'
|
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIsCg9ib290c3'
|
||||||
'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQESOwoIa2V5X3R5cGUYAyABKA4y'
|
'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQFCEgoQX2Jvb3RzdHJhcF90b2tl'
|
||||||
'IC5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC5LZXlUeXBlUgdrZXlUeXBlQhIKEF9ib290c3RyYX'
|
'bg==');
|
||||||
'BfdG9rZW4=');
|
|
||||||
|
|
||||||
@$core.Deprecated('Use authChallengeDescriptor instead')
|
@$core.Deprecated('Use authChallengeDescriptor instead')
|
||||||
const AuthChallenge$json = {
|
const AuthChallenge$json = {
|
||||||
|
|||||||
Reference in New Issue
Block a user