Decouple client contracts and close private role registries
This commit is contained in:
parent
786049534d
commit
22325aa76a
1 changed files with 1041 additions and 321 deletions
|
|
@ -10,6 +10,8 @@ use std::path::{Path, PathBuf};
|
|||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use ed25519_dalek::SigningKey;
|
||||
pub use lazaret_control_client::{CONTROL_ALPN, CONTROL_SERVER_NAME, PendingClientEnrollment};
|
||||
use lazaret_control_client::{ControlClient, ControlClientError};
|
||||
use lazaret_core::codec::{CodecError, decode, encode};
|
||||
use lazaret_core::configuration::ConfinedPathPlan;
|
||||
use lazaret_core::identity::{
|
||||
|
|
@ -38,7 +40,7 @@ use rcgen::{
|
|||
use rustix::fs::{Mode, OFlags, fchmod, openat};
|
||||
use rustix::net::sockopt::socket_peercred;
|
||||
use rustls::pki_types::{
|
||||
CertificateDer, CertificateSigningRequestDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName,
|
||||
CertificateDer, CertificateSigningRequestDer, PrivateKeyDer, PrivatePkcs8KeyDer,
|
||||
};
|
||||
use rustls::server::{NoServerSessionStorage, WebPkiClientVerifier};
|
||||
use rustls::{ClientConfig, ClientConnection, RootCertStore, ServerConfig, ServerConnection};
|
||||
|
|
@ -53,12 +55,9 @@ use lazaret_linux::filesystem::mount_identity;
|
|||
use lazaret_linux::process::{ProcessExit, TargetCommand, child_broker};
|
||||
use lazaret_runtime_supervisor::sandbox::RunscCommand;
|
||||
|
||||
pub const CONTROL_ALPN: &[u8] = b"lazaret-control/1";
|
||||
pub const CONTROL_SERVER_NAME: &str = "coordinator.lazaret.invalid";
|
||||
pub const MAX_ENROLLMENT_BYTES: usize = 8_192;
|
||||
const MAX_CONTROL_BYTES: usize = 65_536;
|
||||
pub(crate) const CONTROL_SOCKET_NAME: &str = "c.sock";
|
||||
pub(crate) const PUBLICATION_IDENTITY_NAME: &str = "protocol-identity.postcard";
|
||||
pub(crate) use lazaret_control_client::{CONTROL_SOCKET_NAME, PUBLICATION_IDENTITY_NAME};
|
||||
pub(crate) const STAGED_CONTROL_SOCKET_NAME: &str = ".c.staged";
|
||||
pub(crate) const STAGED_PUBLICATION_IDENTITY_NAME: &str = ".protocol-identity.staged";
|
||||
|
||||
|
|
@ -69,6 +68,7 @@ pub enum ControlError {
|
|||
Certificate(rcgen::Error),
|
||||
Tls(rustls::Error),
|
||||
Protocol(ProtocolValidationError),
|
||||
Client(ControlClientError),
|
||||
DomainStore(DomainStoreError),
|
||||
InvalidPath(&'static str),
|
||||
InvalidPublication(&'static str),
|
||||
|
|
@ -90,6 +90,7 @@ impl fmt::Display for ControlError {
|
|||
Self::Certificate(error) => write!(formatter, "certificate operation failed: {error}"),
|
||||
Self::Tls(error) => write!(formatter, "TLS failed: {error}"),
|
||||
Self::Protocol(error) => write!(formatter, "protocol validation failed: {error}"),
|
||||
Self::Client(error) => write!(formatter, "{error}"),
|
||||
Self::DomainStore(error) => write!(formatter, "session persistence failed: {error}"),
|
||||
Self::InvalidPath(reason) => write!(formatter, "invalid control path: {reason}"),
|
||||
Self::InvalidPublication(reason) => {
|
||||
|
|
@ -124,6 +125,7 @@ impl std::error::Error for ControlError {
|
|||
Self::Certificate(error) => Some(error),
|
||||
Self::Tls(error) => Some(error),
|
||||
Self::Protocol(error) => Some(error),
|
||||
Self::Client(error) => Some(error),
|
||||
Self::DomainStore(error) => Some(error),
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -145,6 +147,7 @@ from_error!(CodecError, Codec);
|
|||
from_error!(rcgen::Error, Certificate);
|
||||
from_error!(rustls::Error, Tls);
|
||||
from_error!(ProtocolValidationError, Protocol);
|
||||
from_error!(ControlClientError, Client);
|
||||
from_error!(DomainStoreError, DomainStore);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
|
@ -162,50 +165,6 @@ impl FileIdentity {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PendingClientEnrollment {
|
||||
request: ClientEnrollmentRequest,
|
||||
private_key: PrivatePkcs8KeyDer<'static>,
|
||||
}
|
||||
|
||||
impl PendingClientEnrollment {
|
||||
/// Creates an Ed25519 CSR whose signed subject binds the exact generation and Client CLI ID.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns an error when key generation, encoding, or CSR signing fails.
|
||||
pub fn create(
|
||||
generation_identity: GenerationIdentity,
|
||||
cli_id: ClientId,
|
||||
) -> Result<Self, ControlError> {
|
||||
let binding = enrollment_binding(&generation_identity, cli_id)?;
|
||||
let mut params = CertificateParams::default();
|
||||
params.distinguished_name = DistinguishedName::new();
|
||||
params.distinguished_name.push(DnType::CommonName, binding);
|
||||
params.key_usages = vec![KeyUsagePurpose::DigitalSignature];
|
||||
params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ClientAuth];
|
||||
let key = KeyPair::generate_for(&PKCS_ED25519)?;
|
||||
let csr = params.serialize_request(&key)?;
|
||||
Ok(Self {
|
||||
request: ClientEnrollmentRequest {
|
||||
protocol_version: ProtocolVersion::V1,
|
||||
generation_identity,
|
||||
cli_id,
|
||||
certificate_signing_request_der: csr.der().to_vec(),
|
||||
},
|
||||
private_key: PrivatePkcs8KeyDer::from(key.serialize_der()),
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn request(&self) -> &ClientEnrollmentRequest {
|
||||
&self.request
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn private_key(&self) -> PrivateKeyDer<'static> {
|
||||
PrivateKeyDer::Pkcs8(self.private_key.clone_key())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TrustAnchor {
|
||||
generation_identity: GenerationIdentity,
|
||||
tls_ca: CertifiedIssuer<'static, KeyPair>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue