|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
use super::common::ChannelTransport;
|
|
|
|
|
use arbiter_crypto::{
|
|
|
|
|
authn::{self, AuthChallenge, USERAGENT_CONTEXT},
|
|
|
|
|
authn::{self, AuthChallenge, OPERATOR_CONTEXT},
|
|
|
|
|
safecell::{SafeCell, SafeCellHandle as _},
|
|
|
|
|
};
|
|
|
|
|
use arbiter_proto::transport::{Error as TransportError, Receiver, Sender};
|
|
|
|
|
@@ -8,7 +8,7 @@ use arbiter_server::{
|
|
|
|
|
actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap},
|
|
|
|
|
crypto::integrity,
|
|
|
|
|
db::{self, schema},
|
|
|
|
|
peers::user_agent::{self, Credentials, UserAgentConnection, auth, vault_gate},
|
|
|
|
|
peers::operator::{self, Credentials, OperatorConnection, auth, vault_gate},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
|
|
|
@@ -21,13 +21,13 @@ fn verifying_key(key: &SigningKey<MlDsa87>) -> VerifyingKey<MlDsa87> {
|
|
|
|
|
<SigningKey<MlDsa87> as Keypair>::verifying_key(key)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sign_useragent_challenge(
|
|
|
|
|
fn sign_operator_challenge(
|
|
|
|
|
key: &SigningKey<MlDsa87>,
|
|
|
|
|
challenge: &AuthChallenge,
|
|
|
|
|
) -> authn::Signature {
|
|
|
|
|
let challenge = challenge.format();
|
|
|
|
|
key.signing_key()
|
|
|
|
|
.sign_deterministic(&challenge, USERAGENT_CONTEXT)
|
|
|
|
|
.sign_deterministic(&challenge, OPERATOR_CONTEXT)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
@@ -41,8 +41,8 @@ fn tamper_challenge(challenge: &AuthChallenge) -> AuthChallenge {
|
|
|
|
|
struct NullOobSender;
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
|
impl Sender<user_agent::OutOfBand> for NullOobSender {
|
|
|
|
|
async fn send(&mut self, _item: user_agent::OutOfBand) -> Result<(), TransportError> {
|
|
|
|
|
impl Sender<operator::OutOfBand> for NullOobSender {
|
|
|
|
|
async fn send(&mut self, _item: operator::OutOfBand) -> Result<(), TransportError> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -166,7 +166,7 @@ pub async fn bootstrap_token_auth() {
|
|
|
|
|
let (mut server_transport, mut test_transport) = ChannelTransport::new();
|
|
|
|
|
let db_for_task = db.clone();
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
let mut props = UserAgentConnection::new(db_for_task, actors);
|
|
|
|
|
let mut props = OperatorConnection::new(db_for_task, actors);
|
|
|
|
|
auth::authenticate(&mut props, &mut server_transport).await
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -188,7 +188,7 @@ pub async fn bootstrap_token_auth() {
|
|
|
|
|
other => panic!("Expected AuthChallenge, got {other:?}"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = sign_useragent_challenge(&new_key, &challenge);
|
|
|
|
|
let signature = sign_operator_challenge(&new_key, &challenge);
|
|
|
|
|
|
|
|
|
|
test_transport
|
|
|
|
|
.send(auth::Inbound::AuthChallengeSolution {
|
|
|
|
|
@@ -206,8 +206,8 @@ pub async fn bootstrap_token_auth() {
|
|
|
|
|
task.await.unwrap().unwrap();
|
|
|
|
|
|
|
|
|
|
let mut conn = db.get().await.unwrap();
|
|
|
|
|
let stored_pubkey: Vec<u8> = schema::useragent_client::table
|
|
|
|
|
.select(schema::useragent_client::public_key)
|
|
|
|
|
let stored_pubkey: Vec<u8> = schema::operator_client::table
|
|
|
|
|
.select(schema::operator_client::public_key)
|
|
|
|
|
.first::<Vec<u8>>(&mut conn)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
@@ -223,7 +223,7 @@ pub async fn bootstrap_invalid_token_auth() {
|
|
|
|
|
let (mut server_transport, mut test_transport) = ChannelTransport::new();
|
|
|
|
|
let db_for_task = db.clone();
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
let mut props = UserAgentConnection::new(db_for_task, actors);
|
|
|
|
|
let mut props = OperatorConnection::new(db_for_task, actors);
|
|
|
|
|
auth::authenticate(&mut props, &mut server_transport).await
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -245,7 +245,7 @@ pub async fn bootstrap_invalid_token_auth() {
|
|
|
|
|
other => panic!("Expected AuthChallenge, got {other:?}"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = sign_useragent_challenge(&new_key, &challenge);
|
|
|
|
|
let signature = sign_operator_challenge(&new_key, &challenge);
|
|
|
|
|
test_transport
|
|
|
|
|
.send(auth::Inbound::AuthChallengeSolution {
|
|
|
|
|
signature: signature.to_bytes(),
|
|
|
|
|
@@ -259,7 +259,7 @@ pub async fn bootstrap_invalid_token_auth() {
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
let mut conn = db.get().await.unwrap();
|
|
|
|
|
let count: i64 = schema::useragent_client::table
|
|
|
|
|
let count: i64 = schema::operator_client::table
|
|
|
|
|
.count()
|
|
|
|
|
.get_result::<i64>(&mut conn)
|
|
|
|
|
.await
|
|
|
|
|
@@ -285,9 +285,9 @@ pub async fn challenge_auth() {
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut conn = db.get().await.unwrap();
|
|
|
|
|
let id: i32 = insert_into(schema::useragent_client::table)
|
|
|
|
|
.values((schema::useragent_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
.returning(schema::useragent_client::id)
|
|
|
|
|
let id: i32 = insert_into(schema::operator_client::table)
|
|
|
|
|
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
.returning(schema::operator_client::id)
|
|
|
|
|
.get_result(&mut conn)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
@@ -307,7 +307,7 @@ pub async fn challenge_auth() {
|
|
|
|
|
let (mut server_transport, mut test_transport) = ChannelTransport::new();
|
|
|
|
|
let db_for_task = db.clone();
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
let mut props = UserAgentConnection::new(db_for_task, actors);
|
|
|
|
|
let mut props = OperatorConnection::new(db_for_task, actors);
|
|
|
|
|
auth::authenticate(&mut props, &mut server_transport).await
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -331,7 +331,7 @@ pub async fn challenge_auth() {
|
|
|
|
|
Err(err) => panic!("Expected Ok response, got Err({err:?})"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = sign_useragent_challenge(&new_key, &challenge);
|
|
|
|
|
let signature = sign_operator_challenge(&new_key, &challenge);
|
|
|
|
|
|
|
|
|
|
test_transport
|
|
|
|
|
.send(auth::Inbound::AuthChallengeSolution {
|
|
|
|
|
@@ -371,8 +371,8 @@ pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut conn = db.get().await.unwrap();
|
|
|
|
|
insert_into(schema::useragent_client::table)
|
|
|
|
|
.values((schema::useragent_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
insert_into(schema::operator_client::table)
|
|
|
|
|
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
.execute(&mut conn)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
@@ -381,8 +381,8 @@ pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
|
|
|
|
|
let (server_transport, mut test_transport) = start_transport_pair();
|
|
|
|
|
let db_for_task = db.clone();
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
let mut props = UserAgentConnection::new(db_for_task, actors);
|
|
|
|
|
user_agent::start(&mut props, server_transport, Box::new(NullOobSender)).await
|
|
|
|
|
let mut props = OperatorConnection::new(db_for_task, actors);
|
|
|
|
|
operator::start(&mut props, server_transport, Box::new(NullOobSender)).await
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test_transport
|
|
|
|
|
@@ -405,7 +405,7 @@ pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
|
|
|
|
|
Err(err) => panic!("Expected Ok response, got Err({err:?})"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = sign_useragent_challenge(&new_key, &challenge);
|
|
|
|
|
let signature = sign_operator_challenge(&new_key, &challenge);
|
|
|
|
|
|
|
|
|
|
test_transport
|
|
|
|
|
.send(auth::Inbound::AuthChallengeSolution {
|
|
|
|
|
@@ -422,7 +422,7 @@ pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
|
|
|
|
|
|
|
|
|
|
assert!(matches!(
|
|
|
|
|
task.await.unwrap(),
|
|
|
|
|
Err(user_agent::Error::Internal(_))
|
|
|
|
|
Err(operator::Error::Internal(_))
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -444,9 +444,9 @@ pub async fn challenge_auth_rejects_invalid_signature() {
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut conn = db.get().await.unwrap();
|
|
|
|
|
let id: i32 = insert_into(schema::useragent_client::table)
|
|
|
|
|
.values((schema::useragent_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
.returning(schema::useragent_client::id)
|
|
|
|
|
let id: i32 = insert_into(schema::operator_client::table)
|
|
|
|
|
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
|
|
|
|
|
.returning(schema::operator_client::id)
|
|
|
|
|
.get_result(&mut conn)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
@@ -466,7 +466,7 @@ pub async fn challenge_auth_rejects_invalid_signature() {
|
|
|
|
|
let (mut server_transport, mut test_transport) = ChannelTransport::new();
|
|
|
|
|
let db_for_task = db.clone();
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
let mut props = UserAgentConnection::new(db_for_task, actors);
|
|
|
|
|
let mut props = OperatorConnection::new(db_for_task, actors);
|
|
|
|
|
auth::authenticate(&mut props, &mut server_transport).await
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -490,7 +490,7 @@ pub async fn challenge_auth_rejects_invalid_signature() {
|
|
|
|
|
Err(err) => panic!("Expected Ok response, got Err({err:?})"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = sign_useragent_challenge(&new_key, &tamper_challenge(&challenge));
|
|
|
|
|
let signature = sign_operator_challenge(&new_key, &tamper_challenge(&challenge));
|
|
|
|
|
|
|
|
|
|
test_transport
|
|
|
|
|
.send(auth::Inbound::AuthChallengeSolution {
|