diff --git a/src/cli.rs b/src/cli.rs index 89c61596..85efeb51 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -194,26 +194,6 @@ pub(crate) fn build_cli() -> Command { .env("KUBEWARDEN_CONTINUE_ON_ERRORS") .action(ArgAction::SetTrue) .hide(true), - - Arg::new("otlp-endpoint") - .long("otlp-endpoint") - .env("OTEL_EXPORTER_OTLP_ENDPOINT") - .help("The OTLP gRPC endpoint for exporting traces and metrics."), - - Arg::new("otlp-certificate") - .long("otlp-certificate") - .env("OTEL_EXPORTER_OTLP_CERTIFICATE") - .help("Path to the trusted certificate in PEM format used for verifying the TLS credentials of the OTLP gRPC endpoint."), - - Arg::new("otlp-client-certificate") - .long("otlp-client-certificate") - .env("OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE") - .help("Path to the certificate in PEM format to use in mTLS communication."), - - Arg::new("otlp-client-key") - .long("otlp-client-key") - .env("OTEL_EXPORTER_OTLP_CLIENT_KEY") - .help("Path to the client private key in PEM format to use in mTLS communication."), ]; args.sort_by(|a, b| a.get_id().cmp(b.get_id())); diff --git a/src/config.rs b/src/config.rs index 97a6aee7..fd2962f9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -12,10 +12,11 @@ use serde::Deserialize; use std::{ collections::{BTreeSet, HashMap}, env, - fs::File, + fs::{self, File}, net::SocketAddr, path::{Path, PathBuf}, }; +use tonic::transport::{Certificate, ClientTlsConfig, Identity}; pub static SERVICE_NAME: &str = "kubewarden-policy-server"; const DOCKER_CONFIG_ENV_VAR: &str = "DOCKER_CONFIG"; @@ -41,8 +42,6 @@ pub struct Config { pub log_level: String, pub log_fmt: String, pub log_no_color: bool, - pub otlp_endpoint: Option, - pub otlp_tls_config: OtlpTlsConfig, pub daemon: bool, pub enable_pprof: bool, pub daemon_pid_file: String, @@ -56,44 +55,6 @@ pub struct TlsConfig { pub key_file: String, } -#[derive(Clone, Default)] -pub struct OtlpTlsConfig { - pub ca_file: Option, - pub cert_file: Option, - pub key_file: Option, -} - -impl TryFrom for tonic::transport::ClientTlsConfig { - type Error = anyhow::Error; - - fn try_from(value: OtlpTlsConfig) -> Result { - use std::fs; - use tonic::transport::{Certificate, ClientTlsConfig, Identity}; - - let mut tls = ClientTlsConfig::new(); - - if let Some(ca) = value.ca_file { - let ca_cert = fs::read(ca)?; - tls = tls.ca_certificate(Certificate::from_pem(ca_cert)) - } - - if let Some(cert) = value.cert_file { - let cert = fs::read(cert)?; - - let key = value - .key_file - .map(fs::read) - .transpose()? - .unwrap_or_default(); - - let identity = Identity::from_pem(cert, key); - tls = tls.identity(identity); - } - - Ok(tls) - } -} - impl Config { pub fn from_args(matches: &ArgMatches) -> Result { // init some variables based on the cli parameters @@ -166,19 +127,6 @@ impl Config { .expect("clap should have assigned a default value") .to_owned(); - let otlp_endpoint = matches.get_one::("otlp-endpoint").cloned(); - let otlp_ca_file = matches.get_one::("otlp-certificate").cloned(); - let otlp_cert_file = matches - .get_one::("otlp-client-certificate") - .cloned(); - let otlp_key_file = matches.get_one::("otlp-client-key").cloned(); - - let otlp_tls_config = OtlpTlsConfig { - ca_file: otlp_ca_file, - cert_file: otlp_cert_file, - key_file: otlp_key_file, - }; - let (cert_file, key_file) = tls_files(matches)?; let tls_config = if cert_file.is_empty() { None @@ -214,8 +162,6 @@ impl Config { log_level, log_fmt, log_no_color, - otlp_endpoint, - otlp_tls_config, daemon, daemon_pid_file, daemon_stdout_file, @@ -482,6 +428,49 @@ fn read_policies_file(path: &Path) -> Result Result { + let mut client_tls_config = ClientTlsConfig::new(); + + let ca_env = format!("OTEL_EXPORTER_OTLP_{}CERTIFICATE", prefix); + let fallback_ca_env = "OTEL_EXPORTER_OTLP_CERTIFICATE"; + + let ca_file = env::var(&ca_env) + .or_else(|_| env::var(fallback_ca_env)) + .ok(); + + if let Some(ca_path) = ca_file { + let ca_cert = std::fs::read(ca_path)?; + client_tls_config = client_tls_config.ca_certificate(Certificate::from_pem(ca_cert)); + } + + let client_cert_env = format!("OTEL_EXPORTER_OTLP_{}CLIENT_CERTIFICATE", prefix); + let fallback_client_cert_env = "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE"; + + let client_cert_file = std::env::var(&client_cert_env) + .or_else(|_| std::env::var(fallback_client_cert_env)) + .ok(); + + let client_key_env = format!("OTEL_EXPORTER_OTLP_{}CLIENT_KEY", prefix); + let fallback_client_key_env = "OTEL_EXPORTER_OTLP_CLIENT_KEY"; + + let client_key_file = std::env::var(&client_key_env) + .or_else(|_| std::env::var(fallback_client_key_env)) + .ok(); + + if let (Some(cert_path), Some(key_path)) = (client_cert_file, client_key_file) { + let cert = fs::read(cert_path)?; + let key = fs::read(key_path)?; + + let identity = Identity::from_pem(cert, key); + client_tls_config = client_tls_config.identity(identity); + } + + Ok(client_tls_config) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/main.rs b/src/main.rs index 505d806b..045985c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,19 +21,10 @@ async fn main() -> Result<()> { let matches = cli::build_cli().get_matches(); let config = policy_server::config::Config::from_args(&matches)?; - setup_tracing( - &config.log_level, - &config.log_fmt, - config.log_no_color, - config.otlp_endpoint.as_deref(), - config.otlp_tls_config.clone(), - )?; + setup_tracing(&config.log_level, &config.log_fmt, config.log_no_color)?; if config.metrics_enabled { - setup_metrics( - config.otlp_endpoint.as_deref(), - config.otlp_tls_config.clone(), - )?; + setup_metrics()?; }; if config.daemon { diff --git a/src/metrics.rs b/src/metrics.rs index 38b38669..d9e1a2bd 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -8,21 +8,20 @@ pub use policy_evaluations_total::add_policy_evaluation; mod policy_evaluations_latency; pub use policy_evaluations_latency::record_policy_latency; -use crate::config::OtlpTlsConfig; +use crate::config::build_client_tls_config_from_env; const METER_NAME: &str = "kubewarden"; -pub fn setup_metrics(otlp_endpoint: Option<&str>, otlp_tls_config: OtlpTlsConfig) -> Result<()> { - let mut metric_exporter_builder = opentelemetry_otlp::MetricExporter::builder() +pub fn setup_metrics() -> Result<()> { + let metric_exporter = opentelemetry_otlp::MetricExporter::builder() .with_tonic() - .with_tls_config(otlp_tls_config.try_into()?) - .with_export_config(ExportConfig::default()); - if let Some(endpoint) = otlp_endpoint { - metric_exporter_builder = metric_exporter_builder.with_endpoint(endpoint); - } - let meter_reader = metric_exporter_builder.build()?; + .with_tls_config(build_client_tls_config_from_env("METRICS")?) + .with_export_config(ExportConfig::default()) + .build()?; + let periodic_reader = - opentelemetry_sdk::metrics::PeriodicReader::builder(meter_reader, runtime::Tokio).build(); + opentelemetry_sdk::metrics::PeriodicReader::builder(metric_exporter, runtime::Tokio) + .build(); let meter_provider = opentelemetry_sdk::metrics::SdkMeterProvider::builder() .with_reader(periodic_reader) .build(); diff --git a/src/tracing.rs b/src/tracing.rs index e0068159..44d7338e 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -1,23 +1,15 @@ -use std::convert::TryInto; - use anyhow::{anyhow, Result}; use opentelemetry::trace::TracerProvider; -use opentelemetry_otlp::{WithExportConfig, WithTonicConfig}; +use opentelemetry_otlp::WithTonicConfig; use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; -use crate::config::{self, OtlpTlsConfig}; +use crate::config::{self, build_client_tls_config_from_env}; // Setup the tracing system. This MUST be done inside of a tokio Runtime // because some collectors rely on it and would panic otherwise. -pub fn setup_tracing( - log_level: &str, - log_fmt: &str, - log_no_color: bool, - otlp_endpoint: Option<&str>, - otlp_tls_config: OtlpTlsConfig, -) -> Result<()> { +pub fn setup_tracing(log_level: &str, log_fmt: &str, log_no_color: bool) -> Result<()> { // setup logging let filter_layer = EnvFilter::new(log_level) // some of our dependencies generate trace events too, but we don't care about them -> @@ -50,15 +42,10 @@ pub fn setup_tracing( // If no endpoint is provided, the default one is used. // The default endpoint is "http://localhost:4317". // - let mut otlp_exporter_builder = opentelemetry_otlp::SpanExporter::builder() + let otlp_exporter = opentelemetry_otlp::SpanExporter::builder() .with_tonic() - .with_tls_config(otlp_tls_config.try_into()?); - - if let Some(endpoint) = otlp_endpoint { - otlp_exporter_builder = otlp_exporter_builder.with_endpoint(endpoint); - } - - let otlp_exporter = otlp_exporter_builder.build()?; + .with_tls_config(build_client_tls_config_from_env("OTLP")?) + .build()?; let tracer_provider = opentelemetry_sdk::trace::TracerProvider::builder() .with_resource(opentelemetry_sdk::Resource::new(vec![ diff --git a/tests/common/mod.rs b/tests/common/mod.rs index bba7c034..7b32c9d2 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -120,8 +120,6 @@ pub(crate) fn default_test_config() -> Config { log_level: "info".to_owned(), log_fmt: "json".to_owned(), log_no_color: false, - otlp_endpoint: None, - otlp_tls_config: Default::default(), daemon: false, daemon_pid_file: "policy_server.pid".to_owned(), daemon_stdout_file: None, diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 6d53a67c..07116614 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -23,7 +23,6 @@ use policy_evaluator::{ admission_response::AdmissionResponseStatus, policy_fetcher::verify::config::VerificationConfigV1, }; -use policy_server::config::OtlpTlsConfig; use policy_server::{ api::admission_review::AdmissionReviewResponse, config::{PolicyMode, PolicyOrPolicyGroup}, @@ -832,29 +831,26 @@ async fn test_otel() { .await .unwrap(); + std::env::set_var("OTEL_EXPORTER_OTLP_ENDPOINT", "https://localhost:1337"); + std::env::set_var( + "OTEL_EXPORTER_OTLP_CERTIFICATE", + server_ca_file.path().to_str().unwrap(), + ); + std::env::set_var( + "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE", + client_cert_file.path().to_str().unwrap(), + ); + std::env::set_var( + "OTEL_EXPORTER_OTLP_CLIENT_KEY", + client_key_file.path().to_str().unwrap(), + ); + let mut config = default_test_config(); config.metrics_enabled = true; config.log_fmt = "otlp".to_string(); - config.otlp_endpoint = Some("https://localhost:1337".to_string()); - config.otlp_tls_config = OtlpTlsConfig { - ca_file: Some(server_ca_file.path().to_owned()), - cert_file: Some(client_cert_file.path().to_owned()), - key_file: Some(client_key_file.path().to_owned()), - }; - - setup_metrics( - config.otlp_endpoint.as_deref(), - config.otlp_tls_config.clone(), - ) - .unwrap(); - setup_tracing( - &config.log_level, - &config.log_fmt, - config.log_no_color, - config.otlp_endpoint.as_deref(), - config.otlp_tls_config.clone(), - ) - .unwrap(); + + setup_metrics().unwrap(); + setup_tracing(&config.log_level, &config.log_fmt, config.log_no_color).unwrap(); let app = app(config).await;