diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rwxr-xr-x | genkeys.sh | 35 | ||||
-rw-r--r-- | src/rpc_client.rs | 3 | ||||
-rw-r--r-- | src/tls_util.rs | 58 |
4 files changed, 37 insertions, 61 deletions
@@ -31,7 +31,7 @@ reduce = "0.1.2" serde_json = "1.0" rustls = "0.17" -tokio-rustls = { version = "0.13", features = ["dangerous_configuration"] } +tokio-rustls = "0.13" hyper-rustls = { version = "0.20", default-features = false } webpki = "0.21" @@ -7,6 +7,8 @@ cd $(dirname $0) mkdir -p pki cd pki +# Create a certificate authority that both the client side and the server side of +# the RPC protocol will use to authenticate the other side. if [ ! -f garage-ca.key ]; then echo "Generating Garage CA keys..." openssl genrsa -out garage-ca.key 4096 @@ -14,6 +16,9 @@ if [ ! -f garage-ca.key ]; then fi +# Generate a certificate that can be used either as a server certificate +# or a client certificate. This is what the RPC client and server will use +# to prove that they are authenticated by the CA. if [ ! -f garage.crt ]; then echo "Generating Garage agent keys..." if [ ! -f garage.key ]; then @@ -46,3 +51,33 @@ EOF -CA garage-ca.crt -CAkey garage-ca.key -CAcreateserial \ -out garage.crt -days 365 fi + +# Client-only certificate used for the CLI +if [ ! -f garage-client.crt ]; then + echo "Generating Garage client keys..." + if [ ! -f garage-client.key ]; then + openssl genrsa -out garage-client.key 4096 + fi + openssl req -new -sha256 -key garage-client.key -subj "/C=FR/O=Garage" \ + -out garage-client.csr + openssl req -in garage-client.csr -noout -text + openssl x509 -req -in garage-client.csr \ + -extensions v3_req \ + -extfile <(cat <<EOF +[req] +distinguished_name = req_distinguished_name +req_extensions = v3_req +prompt = no + +[req_distinguished_name] +C = FR +O = Garage + +[v3_req] +keyUsage = keyEncipherment, dataEncipherment +extendedKeyUsage = clientAuth +EOF +) \ + -CA garage-ca.crt -CAkey garage-ca.key -CAcreateserial \ + -out garage-client.crt -days 365 +fi diff --git a/src/rpc_client.rs b/src/rpc_client.rs index 255eb958..6f897a90 100644 --- a/src/rpc_client.rs +++ b/src/rpc_client.rs @@ -109,7 +109,6 @@ impl RpcClient { } config.set_single_client_cert([&node_certs[..], &ca_certs[..]].concat(), node_key)?; - // config.dangerous().set_certificate_verifier(Arc::new(tls_util::NoHostnameCertVerifier)); let connector = tls_util::HttpsConnectorFixedDnsname::<HttpConnector>::new(config, "garage"); @@ -143,7 +142,7 @@ impl RpcClient { let resp = tokio::time::timeout(timeout, resp_fut) .await? .map_err(|e| { - eprintln!("RPC client error: {}", e); + eprintln!("RPC HTTP client error when connecting to {}: {}", to_addr, e); e })?; diff --git a/src/tls_util.rs b/src/tls_util.rs index 5a17d380..dfc4e716 100644 --- a/src/tls_util.rs +++ b/src/tls_util.rs @@ -7,7 +7,6 @@ use core::future::Future; use futures_util::future::*; use tokio::io::{AsyncRead, AsyncWrite}; use rustls::internal::pemfile; -use rustls::*; use hyper::client::HttpConnector; use hyper::client::connect::Connection; use hyper::service::Service; @@ -60,63 +59,6 @@ pub fn load_private_key(filename: &str) -> Result<rustls::PrivateKey, Error> { } -// ---- AWFUL COPYPASTA FROM rustls/verifier.rs -// ---- USED TO ALLOW TO VERIFY SERVER CERTIFICATE VALIDITY IN CHAIN -// ---- BUT DISREGARD HOSTNAME PARAMETER - -pub struct NoHostnameCertVerifier; - -type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; -static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ - &webpki::ECDSA_P256_SHA256, - &webpki::ECDSA_P256_SHA384, - &webpki::ECDSA_P384_SHA256, - &webpki::ECDSA_P384_SHA384, - &webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, - &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, - &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, - &webpki::RSA_PKCS1_2048_8192_SHA256, - &webpki::RSA_PKCS1_2048_8192_SHA384, - &webpki::RSA_PKCS1_2048_8192_SHA512, - &webpki::RSA_PKCS1_3072_8192_SHA384 -]; - -impl rustls::ServerCertVerifier for NoHostnameCertVerifier { - fn verify_server_cert(&self, - roots: &RootCertStore, - presented_certs: &[Certificate], - _dns_name: webpki::DNSNameRef, - _ocsp_response: &[u8]) -> Result<rustls::ServerCertVerified, TLSError> { - - if presented_certs.is_empty() { - return Err(TLSError::NoCertificatesPresented); - } - - let cert = webpki::EndEntityCert::from(&presented_certs[0].0) - .map_err(TLSError::WebPKIError)?; - - let chain = presented_certs.iter() - .skip(1) - .map(|cert| cert.0.as_ref()) - .collect::<Vec<_>>(); - - let trustroots: Vec<webpki::TrustAnchor> = roots.roots - .iter() - .map(|x| x.to_trust_anchor()) - .collect(); - - let now = webpki::Time::try_from(std::time::SystemTime::now()) - .map_err( |_ | TLSError::FailedToGetCurrentTime)?; - - cert.verify_is_valid_tls_server_cert(SUPPORTED_SIG_ALGS, - &webpki::TLSServerTrustAnchors(&trustroots), &chain, now) - .map_err(TLSError::WebPKIError)?; - - Ok(rustls::ServerCertVerified::assertion()) - } -} - - // ---- AWFUL COPYPASTA FROM HYPER-RUSTLS connector.rs // ---- ALWAYS USE `garage` AS HOSTNAME FOR TLS VERIFICATION |