Enforce exact recovery ownership before cold start
This commit is contained in:
parent
f21a847991
commit
2bc5982a62
1 changed files with 1076 additions and 238 deletions
|
|
@ -13,7 +13,8 @@ use ed25519_dalek::SigningKey;
|
|||
use lazaret_core::codec::{CodecError, decode, encode};
|
||||
use lazaret_core::configuration::ConfinedPathPlan;
|
||||
use lazaret_core::identity::{
|
||||
CertificateDigest, ClientId, ContainerId, SessionAnchorId, SessionId, TrustManifestDigest,
|
||||
CertificateDigest, ClientId, ContainerId, DeviceId, HostPath, InodeId, MountIdentity,
|
||||
SessionAnchorId, SessionId, TrustManifestDigest,
|
||||
};
|
||||
use lazaret_core::protocol::{
|
||||
ProtocolValidationError, issue_protocol_credential, issue_session_capability,
|
||||
|
|
@ -23,9 +24,10 @@ use lazaret_core::records::{
|
|||
ClientEnrollmentRequest, ClientEnrollmentResponse, ControlRequest, ControlResponse,
|
||||
DurableDecision, GenerationIdentity, NonInteractiveSessionMessage,
|
||||
NonInteractiveSessionRequest, ProtocolCredential, ProtocolCredentialRole,
|
||||
ProtocolPublicationIdentity, ProtocolSubjectId, ProtocolVersion, SandboxCredentialBundle,
|
||||
Session, SessionBinding, SessionExit, SessionPhase, SessionRegistrationRequest,
|
||||
SessionRegistrationResponse, TlsCredential, TlsRole, TlsSubjectId, TrustManifest,
|
||||
ProtocolPublicationIdentity, ProtocolSubjectId, ProtocolVersion, PublicationOwnership,
|
||||
SandboxCredentialBundle, Session, SessionBinding, SessionExit, SessionPhase,
|
||||
SessionRegistrationRequest, SessionRegistrationResponse, TlsCredential, TlsRole, TlsSubjectId,
|
||||
TrustManifest,
|
||||
};
|
||||
use rcgen::{
|
||||
BasicConstraints, CertificateParams, CertificateSigningRequestParams, CertifiedIssuer,
|
||||
|
|
@ -46,6 +48,7 @@ use crate::domain_store::{DomainStoreError, DomainStoreMutation, HostCoordinator
|
|||
use crate::lifecycle::{
|
||||
HostCoordinatorLifecycle, LifecycleAction, SessionAdmissionIdentity, SessionLifecycleAdapter,
|
||||
};
|
||||
use lazaret_linux::filesystem::mount_identity;
|
||||
use lazaret_linux::process::{ProcessExit, TargetCommand, child_broker};
|
||||
use lazaret_runtime_supervisor::sandbox::RunscCommand;
|
||||
|
||||
|
|
@ -53,10 +56,10 @@ 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;
|
||||
const CONTROL_SOCKET_NAME: &str = "c.sock";
|
||||
const PUBLICATION_IDENTITY_NAME: &str = "protocol-identity.postcard";
|
||||
const STAGED_CONTROL_SOCKET_NAME: &str = ".c.staged";
|
||||
const STAGED_PUBLICATION_IDENTITY_NAME: &str = ".protocol-identity.staged";
|
||||
pub(crate) const CONTROL_SOCKET_NAME: &str = "c.sock";
|
||||
pub(crate) const PUBLICATION_IDENTITY_NAME: &str = "protocol-identity.postcard";
|
||||
pub(crate) const STAGED_CONTROL_SOCKET_NAME: &str = ".c.staged";
|
||||
pub(crate) const STAGED_PUBLICATION_IDENTITY_NAME: &str = ".protocol-identity.staged";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ControlError {
|
||||
|
|
@ -1009,6 +1012,10 @@ pub struct StagedControlFace {
|
|||
}
|
||||
|
||||
impl StagedControlFace {
|
||||
pub(crate) fn recovery_ownership(&self) -> Result<PublicationOwnership, ControlError> {
|
||||
publication_recovery_ownership(&self.paths)
|
||||
}
|
||||
|
||||
/// Stages an undiscoverable private control face before durable publication.
|
||||
///
|
||||
/// # Errors
|
||||
|
|
@ -1160,7 +1167,51 @@ impl Drop for StagedControlFace {
|
|||
}
|
||||
}
|
||||
|
||||
fn publication_recovery_ownership(
|
||||
paths: &ControlPaths,
|
||||
) -> Result<PublicationOwnership, ControlError> {
|
||||
let socket_path = if paths.staged_socket.exists() {
|
||||
&paths.staged_socket
|
||||
} else {
|
||||
&paths.socket
|
||||
};
|
||||
let identity_path = if paths.staged_identity.exists() {
|
||||
&paths.staged_identity
|
||||
} else {
|
||||
&paths.identity
|
||||
};
|
||||
Ok(PublicationOwnership {
|
||||
staged_socket_path: Some(HostPath::new(
|
||||
STAGED_CONTROL_SOCKET_NAME.as_bytes().to_vec(),
|
||||
)),
|
||||
staged_identity_path: Some(HostPath::new(
|
||||
STAGED_PUBLICATION_IDENTITY_NAME.as_bytes().to_vec(),
|
||||
)),
|
||||
socket_path: Some(HostPath::new(CONTROL_SOCKET_NAME.as_bytes().to_vec())),
|
||||
identity_path: Some(HostPath::new(PUBLICATION_IDENTITY_NAME.as_bytes().to_vec())),
|
||||
socket_identity: Some(publication_path_identity(paths, socket_path)?),
|
||||
identity_file_identity: Some(publication_path_identity(paths, identity_path)?),
|
||||
})
|
||||
}
|
||||
|
||||
fn publication_path_identity(
|
||||
paths: &ControlPaths,
|
||||
path: &Path,
|
||||
) -> Result<MountIdentity, ControlError> {
|
||||
let metadata = std::fs::symlink_metadata(path)?;
|
||||
let root = mount_identity(&paths.root_file)?;
|
||||
Ok(MountIdentity {
|
||||
mount_id: root.mount_id,
|
||||
device: DeviceId::new(metadata.dev()),
|
||||
inode: InodeId::new(metadata.ino()),
|
||||
})
|
||||
}
|
||||
|
||||
impl PublishedControlFace {
|
||||
pub(crate) fn recovery_ownership(&self) -> Result<PublicationOwnership, ControlError> {
|
||||
publication_recovery_ownership(&self.paths)
|
||||
}
|
||||
|
||||
/// Selects blocking or polling admission for the publication listener.
|
||||
///
|
||||
/// # Errors
|
||||
|
|
|
|||
Loading…
Reference in a new issue