Skip to content

Commit

Permalink
Merge pull request #716 from kazk/refine-errors-native-tls
Browse files Browse the repository at this point in the history
  • Loading branch information
kazk authored Nov 18, 2021
2 parents 3f89ac0 + 7bf6e6c commit 6bd7e05
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 20 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ UNRELEASED
===================
* see https://github.com/kube-rs/kube-rs/compare/0.64.0...master

* BREAKING: Removed `kube::Error::OpenSslError`
* BREAKING: Added `kube::Error::NativeTls(kube::client::NativeTlsError)` for errors from native TLS

0.64.0 / 2021-11-16
===================

Expand Down
1 change: 1 addition & 0 deletions kube-client/src/client/config_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ impl ConfigExt for Config {
self.root_cert.as_ref(),
self.accept_invalid_certs,
)
.map_err(Error::NativeTls)
}

#[cfg(feature = "native-tls")]
Expand Down
1 change: 1 addition & 0 deletions kube-client/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub use config_ext::ConfigExt;
pub mod middleware;
#[cfg(any(feature = "native-tls", feature = "rustls-tls", feature = "openssl-tls"))]
mod tls;
#[cfg(feature = "native-tls")] pub use tls::native_tls::Error as NativeTlsError;
#[cfg(feature = "openssl-tls")]
pub use tls::openssl_tls::Error as OpensslTlsError;
#[cfg(feature = "ws")] mod upgrade;
Expand Down
59 changes: 43 additions & 16 deletions kube-client/src/client/tls.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,60 @@
#[cfg(feature = "native-tls")]
pub mod native_tls {
use thiserror::Error;
use tokio_native_tls::native_tls::{Certificate, Identity, TlsConnector};

use crate::{Error, Result};

const IDENTITY_PASSWORD: &str = " ";

/// Errors from native TLS
#[derive(Debug, Error)]
pub enum Error {
/// Failed to deserialize PEM-encoded X509 certificate
#[error("failed to deserialize PEM-encoded X509 certificate: {0}")]
DeserializeCertificate(#[source] openssl::error::ErrorStack),

/// Failed to deserialize PEM-encoded private key
#[error("failed to deserialize PEM-encoded private key: {0}")]
DeserializePrivateKey(#[source] openssl::error::ErrorStack),

/// Failed to create PKCS #12 archive
#[error("failed to create PKCS #12 archive: {0}")]
CreatePkcs12(#[source] openssl::error::ErrorStack),

/// Failed to serialize PKCS #12 archive to DER
#[error("failed to serialize PKCS #12 archive to DER encoding: {0}")]
SerializePkcs12(#[source] openssl::error::ErrorStack),

/// Failed to deserialize DER-encoded PKCS #12 archive
#[error("failed to deserialize DER-encoded PKCS #12 archive: {0}")]
DeserializePkcs12(#[source] tokio_native_tls::native_tls::Error),

/// Failed to deserialize DER-encoded X509 certificate
#[error("failed to deserialize DER-encoded X509 certificate: {0}")]
DeserializeRootCertificate(#[source] tokio_native_tls::native_tls::Error),

/// Failed to create `TlsConnector`
#[error("failed to create `TlsConnector`: {0}")]
CreateTlsConnector(#[source] tokio_native_tls::native_tls::Error),
}

/// Create `native_tls::TlsConnector`.
pub fn native_tls_connector(
identity_pem: Option<&Vec<u8>>,
root_cert: Option<&Vec<Vec<u8>>>,
accept_invalid: bool,
) -> Result<TlsConnector> {
) -> Result<TlsConnector, Error> {
let mut builder = TlsConnector::builder();
if let Some(pem) = identity_pem {
let identity = pkcs12_from_pem(pem, IDENTITY_PASSWORD)?;
builder.identity(
Identity::from_pkcs12(&identity, IDENTITY_PASSWORD)
.map_err(|e| Error::SslError(format!("{}", e)))?,
Identity::from_pkcs12(&identity, IDENTITY_PASSWORD).map_err(Error::DeserializePkcs12)?,
);
}

if let Some(ders) = root_cert {
for der in ders {
builder.add_root_certificate(
Certificate::from_der(der).map_err(|e| Error::SslError(format!("{}", e)))?,
Certificate::from_der(der).map_err(Error::DeserializeRootCertificate)?,
);
}
}
Expand All @@ -33,21 +63,18 @@ pub mod native_tls {
builder.danger_accept_invalid_certs(true);
}

let connector = builder.build().map_err(|e| Error::SslError(format!("{}", e)))?;
Ok(connector)
builder.build().map_err(Error::CreateTlsConnector)
}

// TODO Replace this with pure Rust implementation to avoid depending on openssl on macOS and Win
fn pkcs12_from_pem(pem: &[u8], password: &str) -> Result<Vec<u8>> {
// TODO Switch to PKCS8 support when https://github.com/sfackler/rust-native-tls/pull/209 is merged
fn pkcs12_from_pem(pem: &[u8], password: &str) -> Result<Vec<u8>, Error> {
use openssl::{pkcs12::Pkcs12, pkey::PKey, x509::X509};
// TODO These are all treated as the same error. Add specific errors.
let x509 = X509::from_pem(pem).map_err(Error::OpensslError)?;
let pkey = PKey::private_key_from_pem(pem).map_err(Error::OpensslError)?;
let x509 = X509::from_pem(pem).map_err(Error::DeserializeCertificate)?;
let pkey = PKey::private_key_from_pem(pem).map_err(Error::DeserializePrivateKey)?;
let p12 = Pkcs12::builder()
.build(password, "kubeconfig", &pkey, &x509)
.map_err(Error::OpensslError)?;
let der = p12.to_der().map_err(Error::OpensslError)?;
Ok(der)
.map_err(Error::CreatePkcs12)?;
p12.to_der().map_err(Error::SerializePkcs12)
}
}

Expand Down
8 changes: 4 additions & 4 deletions kube-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ pub enum Error {
#[error("SslError: {0}")]
SslError(String),

/// An error from openssl when handling configuration
/// Errors from Native TLS
#[cfg(feature = "native-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
#[error("OpensslError: {0}")]
OpensslError(#[source] openssl::error::ErrorStack),
#[cfg_attr(docsrs, doc(feature = "native-tls"))]
#[error("native tls error: {0}")]
NativeTls(#[source] crate::client::NativeTlsError),

/// Errors from OpenSSL TLS
#[cfg(feature = "openssl-tls")]
Expand Down

0 comments on commit 6bd7e05

Please sign in to comment.