You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
Upgrade rustls
This commit is contained in:
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -161,9 +161,9 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "apalis-core"
|
name = "apalis-core"
|
||||||
version = "0.4.9"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1deb48475efcdece1f23a0553209ee842f264c2a5e9bcc4928bfa6a15a044cde"
|
checksum = "5dbe998f2a77a65433e3e893f7ffba5b0c4835a9601ccab02aa868d1d3ed71eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-stream",
|
"async-stream",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -184,9 +184,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "apalis-cron"
|
name = "apalis-cron"
|
||||||
version = "0.4.9"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43310b7e0132f9520b09224fb6faafb32eec82a672aa79c09e46b5b488ed505b"
|
checksum = "9fc57450bd6a857d2370bb5504cf3d7f2a1fb85c7b68bdb7f92f50aac0e26aac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"apalis-core",
|
"apalis-core",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@@ -2252,7 +2252,7 @@ dependencies = [
|
|||||||
"http 0.2.11",
|
"http 0.2.11",
|
||||||
"hyper",
|
"hyper",
|
||||||
"rustls 0.22.2",
|
"rustls 0.22.2",
|
||||||
"rustls-native-certs 0.7.0",
|
"rustls-native-certs",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
@@ -2910,6 +2910,7 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
"rustls-pemfile 2.0.0",
|
"rustls-pemfile 2.0.0",
|
||||||
|
"rustls-pki-types",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -3053,7 +3054,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
"rustls 0.22.2",
|
"rustls 0.22.2",
|
||||||
"rustls-native-certs 0.6.3",
|
"rustls-native-certs",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
@@ -4441,9 +4442,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "psl"
|
name = "psl"
|
||||||
version = "2.1.18"
|
version = "2.1.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e109d6dd5679c4dce63a1c6bd7b61ed6758368af1ccf0701dfb02c021fbb9d0d"
|
checksum = "9667155e4837711406c6a5d26be83cdf53932f182d2ce8785529fd2c1a7e9e97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"psl-types",
|
"psl-types",
|
||||||
]
|
]
|
||||||
@@ -4804,18 +4805,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-native-certs"
|
|
||||||
version = "0.6.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
|
|
||||||
dependencies = [
|
|
||||||
"openssl-probe",
|
|
||||||
"rustls-pemfile 1.0.4",
|
|
||||||
"schannel",
|
|
||||||
"security-framework",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-native-certs"
|
name = "rustls-native-certs"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@@ -285,11 +285,8 @@ where
|
|||||||
|
|
||||||
pub fn build_tls_server_config(config: &HttpTlsConfig) -> Result<ServerConfig, anyhow::Error> {
|
pub fn build_tls_server_config(config: &HttpTlsConfig) -> Result<ServerConfig, anyhow::Error> {
|
||||||
let (key, chain) = config.load()?;
|
let (key, chain) = config.load()?;
|
||||||
let key = rustls::PrivateKey(key);
|
|
||||||
let chain = chain.into_iter().map(rustls::Certificate).collect();
|
|
||||||
|
|
||||||
let mut config = rustls::ServerConfig::builder()
|
let mut config = rustls::ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_single_cert(chain, key)
|
.with_single_cert(chain, key)
|
||||||
.context("failed to build TLS server config")?;
|
.context("failed to build TLS server config")?;
|
||||||
|
@@ -32,6 +32,7 @@ serde_with = { version = "3.4.0", features = ["hex", "chrono"] }
|
|||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
|
||||||
pem-rfc7468 = "0.7.0"
|
pem-rfc7468 = "0.7.0"
|
||||||
|
rustls-pki-types = "1.1.0"
|
||||||
rustls-pemfile = "2.0.0"
|
rustls-pemfile = "2.0.0"
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
rand_chacha = "0.3.1"
|
rand_chacha = "0.3.1"
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
|
|
||||||
use std::{borrow::Cow, io::Cursor, ops::Deref};
|
use std::{borrow::Cow, io::Cursor};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -22,6 +22,7 @@ use camino::Utf8PathBuf;
|
|||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
use mas_keystore::PrivateKey;
|
use mas_keystore::PrivateKey;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
@@ -197,7 +198,9 @@ impl TlsConfig {
|
|||||||
/// - a password was provided but the key was not encrypted
|
/// - a password was provided but the key was not encrypted
|
||||||
/// - decoding the certificate chain as PEM
|
/// - decoding the certificate chain as PEM
|
||||||
/// - the certificate chain is empty
|
/// - the certificate chain is empty
|
||||||
pub fn load(&self) -> Result<(Vec<u8>, Vec<Vec<u8>>), anyhow::Error> {
|
pub fn load(
|
||||||
|
&self,
|
||||||
|
) -> Result<(PrivateKeyDer<'static>, Vec<CertificateDer<'static>>), anyhow::Error> {
|
||||||
let password = match &self.password {
|
let password = match &self.password {
|
||||||
Some(PasswordOrFile::Password(password)) => Some(Cow::Borrowed(password.as_str())),
|
Some(PasswordOrFile::Password(password)) => Some(Cow::Borrowed(password.as_str())),
|
||||||
Some(PasswordOrFile::PasswordFile(path)) => {
|
Some(PasswordOrFile::PasswordFile(path)) => {
|
||||||
@@ -230,9 +233,7 @@ impl TlsConfig {
|
|||||||
|
|
||||||
// Re-serialize the key to PKCS#8 DER, so rustls can consume it
|
// Re-serialize the key to PKCS#8 DER, so rustls can consume it
|
||||||
let key = key.to_pkcs8_der()?;
|
let key = key.to_pkcs8_der()?;
|
||||||
// This extracts the Vec out of the Zeroizing by copying it
|
let key = PrivatePkcs8KeyDer::from(key.to_vec()).into();
|
||||||
// XXX: maybe we should keep that zeroizing?
|
|
||||||
let key = key.deref().clone();
|
|
||||||
|
|
||||||
let certificate_chain_pem = match &self.certificate {
|
let certificate_chain_pem = match &self.certificate {
|
||||||
CertificateOrFile::Certificate(pem) => Cow::Borrowed(pem.as_str()),
|
CertificateOrFile::Certificate(pem) => Cow::Borrowed(pem.as_str()),
|
||||||
@@ -240,7 +241,9 @@ impl TlsConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut certificate_chain_reader = Cursor::new(certificate_chain_pem.as_bytes());
|
let mut certificate_chain_reader = Cursor::new(certificate_chain_pem.as_bytes());
|
||||||
let certificate_chain = rustls_pemfile::certs(&mut certificate_chain_reader)?;
|
let certificate_chain: Result<Vec<_>, _> =
|
||||||
|
rustls_pemfile::certs(&mut certificate_chain_reader).collect();
|
||||||
|
let certificate_chain = certificate_chain?;
|
||||||
|
|
||||||
if certificate_chain.is_empty() {
|
if certificate_chain.is_empty() {
|
||||||
bail!("TLS certificate chain is empty (or invalid)")
|
bail!("TLS certificate chain is empty (or invalid)")
|
||||||
|
@@ -30,7 +30,7 @@ pub use self::{
|
|||||||
compat_sessions::{CompatSession, CompatSsoLogin},
|
compat_sessions::{CompatSession, CompatSsoLogin},
|
||||||
cursor::{Cursor, NodeCursor},
|
cursor::{Cursor, NodeCursor},
|
||||||
node::{Node, NodeType},
|
node::{Node, NodeType},
|
||||||
oauth::{OAuth2Client, OAuth2Consent, OAuth2Session},
|
oauth::{OAuth2Client, OAuth2Session},
|
||||||
upstream_oauth::{UpstreamOAuth2Link, UpstreamOAuth2Provider},
|
upstream_oauth::{UpstreamOAuth2Link, UpstreamOAuth2Provider},
|
||||||
users::{User, UserEmail},
|
users::{User, UserEmail},
|
||||||
viewer::{Anonymous, Viewer, ViewerSession},
|
viewer::{Anonymous, Viewer, ViewerSession},
|
||||||
|
@@ -23,7 +23,7 @@ hyper-rustls = { version = "0.25.0", features = ["http1", "http2"], default-feat
|
|||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
opentelemetry.workspace = true
|
opentelemetry.workspace = true
|
||||||
rustls = { version = "0.22.2", optional = true }
|
rustls = { version = "0.22.2", optional = true }
|
||||||
rustls-native-certs = { version = "0.6.3", optional = true }
|
rustls-native-certs = { version = "0.7.0", optional = true }
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
serde_urlencoded = "0.7.1"
|
serde_urlencoded = "0.7.1"
|
||||||
|
@@ -75,15 +75,11 @@ async fn tls_roots() -> Result<rustls::RootCertStore, NativeRootsInitError> {
|
|||||||
#[cfg(feature = "webpki-roots")]
|
#[cfg(feature = "webpki-roots")]
|
||||||
#[allow(clippy::unused_async)]
|
#[allow(clippy::unused_async)]
|
||||||
async fn tls_roots() -> Result<rustls::RootCertStore, Infallible> {
|
async fn tls_roots() -> Result<rustls::RootCertStore, Infallible> {
|
||||||
let mut roots = rustls::RootCertStore::empty();
|
let root_store = rustls::RootCertStore {
|
||||||
roots.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
|
roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
|
||||||
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
};
|
||||||
ta.subject,
|
|
||||||
ta.spki,
|
Ok(root_store)
|
||||||
ta.name_constraints,
|
|
||||||
)
|
|
||||||
}));
|
|
||||||
Ok(roots)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "native-roots")]
|
#[cfg(feature = "native-roots")]
|
||||||
@@ -131,7 +127,6 @@ pub enum NativeRootsLoadError {
|
|||||||
async fn make_tls_config() -> Result<rustls::ClientConfig, ClientInitError> {
|
async fn make_tls_config() -> Result<rustls::ClientConfig, ClientInitError> {
|
||||||
let roots = tls_roots().await?;
|
let roots = tls_roots().await?;
|
||||||
let tls_config = rustls::ClientConfig::builder()
|
let tls_config = rustls::ClientConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_root_certificates(roots)
|
.with_root_certificates(roots)
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
|
@@ -24,10 +24,7 @@ use anyhow::Context;
|
|||||||
use hyper::{service::service_fn, Request, Response};
|
use hyper::{service::service_fn, Request, Response};
|
||||||
use mas_listener::{server::Server, shutdown::ShutdownStream, ConnectionInfo};
|
use mas_listener::{server::Server, shutdown::ShutdownStream, ConnectionInfo};
|
||||||
use tokio::signal::unix::SignalKind;
|
use tokio::signal::unix::SignalKind;
|
||||||
use tokio_rustls::rustls::{
|
use tokio_rustls::rustls::{server::WebPkiClientVerifier, RootCertStore, ServerConfig};
|
||||||
server::AllowAnyAnonymousOrAuthenticatedClient, Certificate, PrivateKey, RootCertStore,
|
|
||||||
ServerConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
static CA_CERT_PEM: &[u8] = include_bytes!("./certs/ca.pem");
|
static CA_CERT_PEM: &[u8] = include_bytes!("./certs/ca.pem");
|
||||||
static SERVER_CERT_PEM: &[u8] = include_bytes!("./certs/server.pem");
|
static SERVER_CERT_PEM: &[u8] = include_bytes!("./certs/server.pem");
|
||||||
@@ -75,27 +72,30 @@ async fn main() -> Result<(), anyhow::Error> {
|
|||||||
|
|
||||||
fn load_tls_config() -> Result<Arc<ServerConfig>, anyhow::Error> {
|
fn load_tls_config() -> Result<Arc<ServerConfig>, anyhow::Error> {
|
||||||
let mut ca_cert_reader = BufReader::new(CA_CERT_PEM);
|
let mut ca_cert_reader = BufReader::new(CA_CERT_PEM);
|
||||||
let ca_cert = rustls_pemfile::certs(&mut ca_cert_reader).context("Invalid CA certificate")?;
|
let ca_cert = rustls_pemfile::certs(&mut ca_cert_reader)
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.context("Invalid CA certificate")?;
|
||||||
let mut ca_cert_store = RootCertStore::empty();
|
let mut ca_cert_store = RootCertStore::empty();
|
||||||
ca_cert_store.add_parsable_certificates(&ca_cert);
|
ca_cert_store.add_parsable_certificates(ca_cert);
|
||||||
|
|
||||||
let mut server_cert_reader = BufReader::new(SERVER_CERT_PEM);
|
let mut server_cert_reader = BufReader::new(SERVER_CERT_PEM);
|
||||||
let server_cert: Vec<_> = rustls_pemfile::certs(&mut server_cert_reader)
|
let server_cert: Vec<_> = rustls_pemfile::certs(&mut server_cert_reader)
|
||||||
.context("Invalid server certificate")?
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.into_iter()
|
.context("Invalid server certificate")?;
|
||||||
.map(Certificate)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut server_key_reader = BufReader::new(SERVER_KEY_PEM);
|
let mut server_key_reader = BufReader::new(SERVER_KEY_PEM);
|
||||||
let mut server_key = rustls_pemfile::rsa_private_keys(&mut server_key_reader)
|
let server_key = rustls_pemfile::rsa_private_keys(&mut server_key_reader)
|
||||||
|
.next()
|
||||||
|
.context("No RSA private key found")?
|
||||||
.context("Invalid server TLS keys")?;
|
.context("Invalid server TLS keys")?;
|
||||||
let server_key = PrivateKey(server_key.pop().context("Missing server TLS key")?);
|
|
||||||
|
|
||||||
let client_cert_verifier = Arc::new(AllowAnyAnonymousOrAuthenticatedClient::new(ca_cert_store));
|
let client_cert_verifier = WebPkiClientVerifier::builder(Arc::new(ca_cert_store))
|
||||||
|
.allow_unauthenticated()
|
||||||
|
.build()?;
|
||||||
|
|
||||||
let mut config = ServerConfig::builder()
|
let mut config = ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_client_cert_verifier(client_cert_verifier)
|
.with_client_cert_verifier(client_cert_verifier)
|
||||||
.with_single_cert(server_cert, server_key)?;
|
.with_single_cert(server_cert, server_key.into())?;
|
||||||
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||||
|
|
||||||
Ok(Arc::new(config))
|
Ok(Arc::new(config))
|
||||||
|
@@ -20,7 +20,10 @@ use std::{
|
|||||||
|
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
rustls::{Certificate, ProtocolVersion, ServerConfig, ServerConnection, SupportedCipherSuite},
|
rustls::{
|
||||||
|
pki_types::CertificateDer, ProtocolVersion, ServerConfig, ServerConnection,
|
||||||
|
SupportedCipherSuite,
|
||||||
|
},
|
||||||
TlsAcceptor,
|
TlsAcceptor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,7 +34,7 @@ pub struct TlsStreamInfo {
|
|||||||
pub negotiated_cipher_suite: SupportedCipherSuite,
|
pub negotiated_cipher_suite: SupportedCipherSuite,
|
||||||
pub sni_hostname: Option<String>,
|
pub sni_hostname: Option<String>,
|
||||||
pub alpn_protocol: Option<Vec<u8>>,
|
pub alpn_protocol: Option<Vec<u8>>,
|
||||||
pub peer_certificates: Option<Vec<Certificate>>,
|
pub peer_certificates: Option<Vec<CertificateDer<'static>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TlsStreamInfo {
|
impl TlsStreamInfo {
|
||||||
@@ -98,7 +101,13 @@ impl<T> MaybeTlsStream<T> {
|
|||||||
|
|
||||||
let sni_hostname = conn.server_name().map(ToOwned::to_owned);
|
let sni_hostname = conn.server_name().map(ToOwned::to_owned);
|
||||||
let alpn_protocol = conn.alpn_protocol().map(ToOwned::to_owned);
|
let alpn_protocol = conn.alpn_protocol().map(ToOwned::to_owned);
|
||||||
let peer_certificates = conn.peer_certificates().map(ToOwned::to_owned);
|
let peer_certificates = conn.peer_certificates().map(|certs| {
|
||||||
|
certs
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(CertificateDer::into_owned)
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
Some(TlsStreamInfo {
|
Some(TlsStreamInfo {
|
||||||
protocol_version,
|
protocol_version,
|
||||||
negotiated_cipher_suite,
|
negotiated_cipher_suite,
|
||||||
|
@@ -32,6 +32,10 @@ static MAS_USER_AGENT: HeaderValue = HeaderValue::from_static("mas-oidc-client/0
|
|||||||
|
|
||||||
/// Constructs a [`HttpService`] using [hyper] as a backend.
|
/// Constructs a [`HttpService`] using [hyper] as a backend.
|
||||||
///
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If the native TLS root certificates fail to load
|
||||||
|
///
|
||||||
/// [hyper]: https://crates.io/crates/hyper
|
/// [hyper]: https://crates.io/crates/hyper
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hyper_service() -> HttpService {
|
pub fn hyper_service() -> HttpService {
|
||||||
@@ -41,8 +45,8 @@ pub fn hyper_service() -> HttpService {
|
|||||||
http.enforce_http(false);
|
http.enforce_http(false);
|
||||||
|
|
||||||
let tls_config = rustls::ClientConfig::builder()
|
let tls_config = rustls::ClientConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_native_roots()
|
.with_native_roots()
|
||||||
|
.expect("Failed to load native TLS")
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
let https = HttpsConnectorBuilder::new()
|
let https = HttpsConnectorBuilder::new()
|
||||||
|
@@ -13,8 +13,8 @@ workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
apalis-core = { version = "0.4.7", features = ["extensions", "tokio-comp", "storage"] }
|
apalis-core = { version = "=0.4.7", features = ["extensions", "tokio-comp", "storage"] }
|
||||||
apalis-cron = "0.4.7"
|
apalis-cron = "=0.4.7"
|
||||||
async-stream = "0.3.5"
|
async-stream = "0.3.5"
|
||||||
async-trait = "0.1.74"
|
async-trait = "0.1.74"
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
|
Reference in New Issue
Block a user