mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
128 lines
5.4 KiB
Rust
128 lines
5.4 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
pub mod certs;
|
|
pub mod config;
|
|
pub mod coordinator;
|
|
pub mod debug;
|
|
pub mod error;
|
|
pub mod fingerprint;
|
|
pub mod material;
|
|
pub mod metrics;
|
|
pub mod outbound;
|
|
pub mod server;
|
|
pub mod source;
|
|
pub mod state;
|
|
|
|
pub use certs::{
|
|
CertDirectoryLoadOptions, TlsCertPairInspection, TlsCertPairStatus, TlsDirectoryInspection, TlsDomainInspection,
|
|
WebPkiClientVerifierOptions, build_webpki_client_verifier, create_multi_cert_resolver, inspect_cert_directory,
|
|
load_all_certs_from_directory, load_cert_bundle_der_bytes, load_certs, load_private_key,
|
|
};
|
|
pub use config::{ReloadApplyHint, ReloadDetectMode, TlsReloadOptions};
|
|
pub use coordinator::{TlsConsumer, TlsReloadCoordinator};
|
|
pub use debug::{TlsConsumerStatusItem, TlsDebugStatusResponse, TlsDebugStatusResponseBuilder};
|
|
pub use error::TlsRuntimeError;
|
|
pub use fingerprint::TlsFingerprint;
|
|
pub use material::{OutboundTlsMaterial, ServerTlsMaterial, TlsMaterialSnapshot};
|
|
pub use metrics::{
|
|
TLS_OUTBOUND_GLOBAL_CONSUMER, TLS_RUNTIME_FOUNDATION_CONSUMER, init_tls_metrics, record_tls_consumer_stale_generation,
|
|
record_tls_generation, record_tls_publication_fail, record_tls_reload_result, record_tls_reload_skipped,
|
|
};
|
|
pub use outbound::{
|
|
GlobalOutboundTlsStateSummary, GlobalPublishedOutboundTlsState, load_global_outbound_tls_generation,
|
|
load_global_outbound_tls_state, publish_global_outbound_tls_state, summarize_global_outbound_tls_state,
|
|
};
|
|
pub use server::{ReloadableServerCertResolver, spawn_server_cert_reload_loop};
|
|
pub use source::{TlsFileLayout, TlsSource, TlsSourceKind};
|
|
pub use state::OutboundOnlySnapshotArgs;
|
|
pub use state::{TlsGeneration, TlsPublishedState, TlsReloadRuntimeState, TlsRuntimeStatusSnapshot};
|
|
pub use state::{TlsRuntimeConsumerSection, TlsRuntimeOutboundSection, TlsRuntimeRuntimeSection, TlsRuntimeServerSection};
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use rcgen::generate_simple_self_signed;
|
|
use std::collections::HashMap;
|
|
|
|
#[test]
|
|
fn tls_source_requires_existing_directory() {
|
|
let source = TlsSource::from_directory("/definitely/missing/rustfs/tls-runtime-test");
|
|
let err = source.validate_directory().expect_err("missing directory should fail");
|
|
assert!(matches!(err, TlsRuntimeError::DirectoryNotFound { .. }));
|
|
}
|
|
|
|
#[test]
|
|
fn fingerprint_changes_when_server_material_changes() {
|
|
let cert_a = generate_simple_self_signed(vec!["a.example.com".to_string()]).expect("cert A should generate");
|
|
let cert_b = generate_simple_self_signed(vec!["b.example.com".to_string()]).expect("cert B should generate");
|
|
|
|
let single_a = ServerTlsMaterial::SingleCert {
|
|
certs: vec![cert_a.cert.der().clone()],
|
|
key: rustls::pki_types::PrivateKeyDer::try_from(cert_a.signing_key.serialize_der()).expect("key A should convert"),
|
|
};
|
|
let single_b = ServerTlsMaterial::SingleCert {
|
|
certs: vec![cert_b.cert.der().clone()],
|
|
key: rustls::pki_types::PrivateKeyDer::try_from(cert_b.signing_key.serialize_der()).expect("key B should convert"),
|
|
};
|
|
|
|
let bytes_a = match &single_a {
|
|
ServerTlsMaterial::SingleCert { certs, key } => {
|
|
let mut bytes = Vec::new();
|
|
for cert in certs {
|
|
bytes.extend_from_slice(cert.as_ref());
|
|
}
|
|
bytes.extend_from_slice(key.secret_der());
|
|
bytes
|
|
}
|
|
ServerTlsMaterial::MultiCert { .. } => unreachable!(),
|
|
};
|
|
let bytes_b = match &single_b {
|
|
ServerTlsMaterial::SingleCert { certs, key } => {
|
|
let mut bytes = Vec::new();
|
|
for cert in certs {
|
|
bytes.extend_from_slice(cert.as_ref());
|
|
}
|
|
bytes.extend_from_slice(key.secret_der());
|
|
bytes
|
|
}
|
|
ServerTlsMaterial::MultiCert { .. } => unreachable!(),
|
|
};
|
|
|
|
let fp_a = TlsFingerprint::from_optional_bytes(Some(&bytes_a), None, None, None, None);
|
|
let fp_b = TlsFingerprint::from_optional_bytes(Some(&bytes_b), None, None, None, None);
|
|
assert_ne!(fp_a, fp_b);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn coordinator_can_publish_initial_state() {
|
|
let source = TlsSource::from_directory(std::env::temp_dir());
|
|
let coordinator = TlsReloadCoordinator::new(source.clone(), TlsReloadOptions::default());
|
|
let snapshot = TlsMaterialSnapshot {
|
|
source,
|
|
server: Some(ServerTlsMaterial::MultiCert {
|
|
cert_key_pairs: HashMap::new(),
|
|
}),
|
|
outbound: OutboundTlsMaterial {
|
|
root_ca_pem: Vec::new(),
|
|
mtls_identity: None,
|
|
},
|
|
fingerprint: TlsFingerprint::default(),
|
|
};
|
|
|
|
let published = coordinator.publish_initial_state(snapshot).await;
|
|
assert_eq!(published.generation, TlsGeneration(1));
|
|
}
|
|
}
|