diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e12ad37..a3432e25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,9 @@ jobs: matrix: args: - build --release + - build --release --features=native-tls - clippy -- -D warnings + - clippy --features=native-tls -- -D warnings - test arch: - amd64 diff --git a/Cargo.lock b/Cargo.lock index ddcb3959..070a5175 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.8.4" @@ -263,10 +285,13 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.30" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -336,6 +361,15 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -361,6 +395,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -382,6 +426,12 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.15.0" @@ -445,6 +495,7 @@ dependencies = [ "fact-ebpf", "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", "hyper-util", "libc", @@ -454,6 +505,7 @@ dependencies = [ "prometheus-client", "prost", "prost-types", + "rustls", "serde", "serde_json", "tempfile", @@ -495,6 +547,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -528,6 +586,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.31" @@ -567,6 +631,17 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.3.3" @@ -703,6 +778,24 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "log", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-timeout" version = "0.5.2" @@ -819,6 +912,16 @@ dependencies = [ "syn", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -929,7 +1032,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -1273,6 +1376,20 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -1298,6 +1415,54 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -1332,7 +1497,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -1433,6 +1611,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.104" @@ -1457,7 +1641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.59.0", @@ -1523,6 +1707,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -1696,6 +1890,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1708,7 +1908,7 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom", + "getrandom 0.3.3", "js-sys", "wasm-bindgen", ] @@ -1923,3 +2123,9 @@ dependencies = [ "encoding_rs", "hashlink", ] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/Cargo.toml b/Cargo.toml index a7938bb6..bafe7ee3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ clap = { version = "4.5.41", features = ["derive", "env"] } env_logger = { version = "0.11.5", default-features = false, features = ["humantime"] } http-body-util = "0.1.3" hyper = { version = "1.6.0", default-features = false } +hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-tls = "0.6.0" hyper-util = { version = "0.1.16", default-features = false } libc = { version = "0.2.159", default-features = false } @@ -27,6 +28,7 @@ openssl = "0.10.75" prometheus-client = { version = "0.24.0", default-features = false } prost = "0.14.0" prost-types = "0.14.0" +rustls = "0.23.35" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.142" tokio = { version = "1.40.0", default-features = false, features = [ diff --git a/Containerfile b/Containerfile index ef52906d..5e57fa56 100644 --- a/Containerfile +++ b/Containerfile @@ -23,14 +23,7 @@ RUN --mount=type=cache,target=/root/.cargo/registry \ cargo build --release && \ cp target/release/fact fact -FROM registry.access.redhat.com/ubi9/ubi-minimal:latest - -RUN microdnf install -y openssl-libs && \ - microdnf clean all && \ - rpm --verbose -e --nodeps $( \ - rpm -qa 'curl' '*rpm*' '*dnf*' '*libsolv*' '*hawkey*' 'yum*' 'libyaml*' 'libarchive*' \ - ) && \ - rm -rf /var/cache/yum +FROM registry.access.redhat.com/ubi9/ubi-micro:latest COPY --from=build /app/fact /usr/local/bin diff --git a/fact/Cargo.toml b/fact/Cargo.toml index 8bbc97a2..0612723b 100644 --- a/fact/Cargo.toml +++ b/fact/Cargo.toml @@ -12,15 +12,17 @@ clap = { workspace = true } env_logger = { workspace = true } http-body-util = { workspace = true } hyper = { workspace = true } -hyper-tls = { workspace = true } +hyper-rustls = { workspace = true } +hyper-tls = { workspace = true, optional = true } hyper-util = { workspace = true } libc = { workspace = true } log = { workspace = true } -native-tls = { workspace = true } -openssl = { workspace = true } +native-tls = { workspace = true, optional = true } +openssl = { workspace = true, optional = true } +rustls = { workspace = true } tonic = { workspace = true } tokio = { workspace = true } -tokio-native-tls = { workspace = true } +tokio-native-tls = { workspace = true, optional = true } tokio-stream = { workspace = true } prometheus-client = { workspace = true } prost = { workspace = true } @@ -45,3 +47,9 @@ path = "src/main.rs" [features] bpf-test = [] +native-tls = [ + "dep:hyper-tls", + "dep:native-tls", + "dep:openssl", + "dep:tokio-native-tls", +] diff --git a/fact/src/output/grpc.rs b/fact/src/output/grpc.rs index 9ed220f4..b3aee973 100644 --- a/fact/src/output/grpc.rs +++ b/fact/src/output/grpc.rs @@ -1,14 +1,14 @@ use std::{sync::Arc, time::Duration}; -use anyhow::{bail, Context}; +use anyhow::bail; use fact_api::file_activity_service_client::FileActivityServiceClient; +#[cfg(not(feature = "native-tls"))] +use hyper_rustls::HttpsConnector; +#[cfg(feature = "native-tls")] use hyper_tls::HttpsConnector; use hyper_util::client::legacy::connect::HttpConnector; use log::{debug, info, warn}; -use native_tls::{Certificate, Identity}; -use openssl::{ec::EcKey, pkey::PKey}; use tokio::{ - fs, sync::{broadcast, watch}, time::sleep, }; @@ -63,7 +63,13 @@ impl Client { }); } - async fn get_tls_connector(&self) -> anyhow::Result> { + #[cfg(feature = "native-tls")] + async fn get_connector(&self) -> anyhow::Result>> { + use anyhow::Context; + use native_tls::{Certificate, Identity}; + use openssl::{ec::EcKey, pkey::PKey}; + use tokio::fs; + let certs = { let config = self.config.borrow(); let Some(certs) = config.certs() else { @@ -91,20 +97,46 @@ impl Client { .identity(id) .request_alpns(&["h2"]) .build()?; - Ok(Some(connector.into())) + let connector = tokio_native_tls::TlsConnector::from(connector); + + let mut http = HttpConnector::new(); + http.enforce_http(false); + let mut connector = HttpsConnector::from((http, connector)); + connector.https_only(true); + Ok(Some(connector)) } - fn get_https_connector( - &self, - connector: Option, - ) -> Option> { - connector.map(|c| { - let mut http = HttpConnector::new(); - http.enforce_http(false); - let mut connector = HttpsConnector::from((http, c)); - connector.https_only(true); - connector - }) + #[cfg(not(feature = "native-tls"))] + async fn get_connector(&self) -> anyhow::Result>> { + use hyper_rustls::HttpsConnectorBuilder; + use rustls::{ + pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer}, + ClientConfig, RootCertStore, + }; + + let config = self.config.borrow(); + let Some(certs) = config.certs() else { + return Ok(None); + }; + let mut cert_store = RootCertStore::empty(); + for cert in CertificateDer::pem_file_iter(certs.join("ca.pem"))? { + cert_store.add(cert?)?; + } + let client_certs = + CertificateDer::pem_file_iter(certs.join("cert.pem"))?.collect::>()?; + let client_key = PrivateKeyDer::from_pem_file(certs.join("key.pem"))?; + + let config = ClientConfig::builder() + .with_root_certificates(cert_store) + .with_client_auth_cert(client_certs, client_key)?; + + let https = HttpsConnectorBuilder::new() + .with_tls_config(config) + .https_only() + .enable_http2() + .build(); + + Ok(Some(https)) } async fn create_channel( @@ -124,8 +156,7 @@ impl Client { } async fn run(&mut self) -> anyhow::Result { - let tls_connector = self.get_tls_connector().await?; - let connector = self.get_https_connector(tls_connector); + let connector = self.get_connector().await?; loop { info!("Attempting to connect to gRPC server..."); let channel = match self.create_channel(connector.clone()).await { diff --git a/konflux.Containerfile b/konflux.Containerfile index e84dc327..b41f5d1f 100644 --- a/konflux.Containerfile +++ b/konflux.Containerfile @@ -16,7 +16,7 @@ WORKDIR /app COPY . . -RUN cargo build --release +RUN cargo build --release --features=native-tls FROM registry.access.redhat.com/ubi9/ubi-minimal@sha256:6fc28bcb6776e387d7a35a2056d9d2b985dc4e26031e98a2bd35a7137cd6fd71