Skip to content

Commit

Permalink
Support loading appsec helper in sidecar
Browse files Browse the repository at this point in the history
  • Loading branch information
cataphract committed Aug 1, 2024
1 parent 9895dd2 commit cc67ce5
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 7 deletions.
79 changes: 73 additions & 6 deletions sidecar/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ const DEFAULT_IDLE_LINGER_TIME: Duration = Duration::from_secs(60);

const ENV_SIDECAR_SELF_TELEMETRY: &str = "_DD_SIDECAR_SELF_TELEMETRY";

const ENV_SIDECAR_APPSEC_SHARED_LIB_PATH: &str = "_DD_SIDECAR_APPSEC_SHARED_LIB_PATH";
const ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_SOCKET_FILE_PATH";
const ENV_SIDECAR_APPSEC_LOCK_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_LOCK_FILE_PATH";
const ENV_SIDECAR_APPSEC_LOG_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_LOG_FILE_PATH";
const ENV_SIDECAR_APPSEC_LOG_LEVEL: &str = "_DD_SIDECAR_APPSEC_LOG_LEVEL";

#[derive(Debug, Copy, Clone)]
pub enum IpcMode {
Shared,
Expand Down Expand Up @@ -78,22 +84,66 @@ pub struct Config {
pub self_telemetry: bool,
pub library_dependencies: Vec<LibDependency>,
pub child_env: HashMap<std::ffi::OsString, std::ffi::OsString>,
pub appsec_config: Option<AppSecConfig>,
}

#[derive(Debug, Clone)]
pub struct AppSecConfig {
pub shared_lib_path: std::ffi::OsString,
pub socket_file_path: std::ffi::OsString,
pub lock_file_path: std::ffi::OsString,
pub log_file_path: std::ffi::OsString,
pub log_level: String,
}

impl Config {
pub fn get() -> Self {
FromEnv::config()
}

pub fn to_env(&self) -> HashMap<&'static str, String> {
HashMap::from([
(ENV_SIDECAR_IPC_MODE, self.ipc_mode.to_string()),
(ENV_SIDECAR_LOG_METHOD, self.log_method.to_string()),
pub fn to_env(&self) -> HashMap<&'static str, std::ffi::OsString> {
let mut res = HashMap::from([
(ENV_SIDECAR_IPC_MODE, self.ipc_mode.to_string().into()),
(ENV_SIDECAR_LOG_METHOD, self.log_method.to_string().into()),
(
ENV_IDLE_LINGER_TIME_SECS,
self.idle_linger_time.as_secs().to_string(),
self.idle_linger_time.as_secs().to_string().into(),
),
(
ENV_SIDECAR_SELF_TELEMETRY,
self.self_telemetry.to_string().into(),
),
]);
if self.appsec_config.is_some() {
res.extend(self.appsec_config.as_ref().unwrap().to_env());
}
res
}
}

impl AppSecConfig {
pub fn to_env(&self) -> HashMap<&'static str, std::ffi::OsString> {
HashMap::from([
(
ENV_SIDECAR_APPSEC_SHARED_LIB_PATH,
self.shared_lib_path.to_owned(),
),
(
ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH,
self.socket_file_path.to_owned(),
),
(
ENV_SIDECAR_APPSEC_LOCK_FILE_PATH,
self.lock_file_path.to_owned(),
),
(
ENV_SIDECAR_APPSEC_LOG_FILE_PATH,
self.log_file_path.to_owned(),
),
(
ENV_SIDECAR_APPSEC_LOG_LEVEL,
self.log_level.to_owned().into(),
),
(ENV_SIDECAR_SELF_TELEMETRY, self.self_telemetry.to_string()),
])
}
}
Expand Down Expand Up @@ -159,8 +209,25 @@ impl FromEnv {
self_telemetry: Self::self_telemetry(),
library_dependencies: vec![],
child_env: std::env::vars_os().collect(),
appsec_config: Self::appsec_config(),
}
}

pub fn appsec_config() -> Option<AppSecConfig> {
let shared_lib_path = std::env::var_os(ENV_SIDECAR_APPSEC_SHARED_LIB_PATH)?;
let socket_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH)?;
let lock_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_LOCK_FILE_PATH)?;
let log_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_LOG_FILE_PATH)?;
let log_level = std::env::var(ENV_SIDECAR_APPSEC_LOG_LEVEL).ok()?;

Some(AppSecConfig {
shared_lib_path,
socket_file_path,
lock_file_path,
log_file_path,
log_level,
})
}
}

pub fn get_product_endpoint(subdomain: &str, endpoint: &Endpoint) -> Endpoint {
Expand Down
9 changes: 8 additions & 1 deletion sidecar/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,15 @@ pub fn daemonize(listener: IpcServer, cfg: Config) -> anyhow::Result<()> {

setup_daemon_process(listener, &mut spawn_cfg)?;

let mut lib_deps = cfg.library_dependencies;
if cfg.appsec_config.is_some() {
lib_deps.push(spawn_worker::LibDependency::Path(
cfg.appsec_config.unwrap().shared_lib_path.into(),
));
}

spawn_cfg
.shared_lib_dependencies(cfg.library_dependencies)
.shared_lib_dependencies(lib_deps)
.wait_spawn()
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
.context("Could not spawn the sidecar daemon")?;
Expand Down
56 changes: 56 additions & 0 deletions sidecar/src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

use spawn_worker::{getpid, SpawnWorker, Stdio};

use std::ffi::CString;
use std::os::unix::net::UnixListener as StdUnixListener;

use crate::config::FromEnv;
use crate::enter_listener_loop;
use nix::fcntl::{fcntl, OFlag, F_GETFL, F_SETFL};
use nix::sys::socket::{shutdown, Shutdown};
Expand All @@ -28,6 +30,8 @@ pub extern "C" fn ddog_daemon_entry_point() {

let now = Instant::now();

let appsec_started = maybe_start_appsec();

if let Some(fd) = spawn_worker::recv_passed_fd() {
let listener: StdUnixListener = fd.into();
info!("Starting sidecar, pid: {}", getpid());
Expand Down Expand Up @@ -56,6 +60,10 @@ pub extern "C" fn ddog_daemon_entry_point() {
}
}

if appsec_started {
shutdown_appsec();
}

info!(
"shutting down sidecar, pid: {}, total runtime: {:.3}s",
getpid(),
Expand Down Expand Up @@ -89,3 +97,51 @@ pub fn setup_daemon_process(
pub fn primary_sidecar_identifier() -> u32 {
unsafe { libc::geteuid() }
}

fn maybe_start_appsec() -> bool {
let cfg = FromEnv::appsec_config();
if cfg.is_none() {
return false;
}

info!("Starting appsec helper");

let entrypoint_sym_name = CString::new("appsec_helper_main").unwrap();

let func_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, entrypoint_sym_name.as_ptr()) };
if func_ptr.is_null() {
error!("Failed to load appsec helper: can't find the symbol 'appsec_helper_main'");
return false;
}

let appsec_entry_fn: extern "C" fn() -> i32 = unsafe { std::mem::transmute(func_ptr) };
let res = appsec_entry_fn();
if res != 0 {
error!("Appsec helper failed to start");
return false;
}

info!("Appsec helper started");
true
}

fn shutdown_appsec() -> bool {
info!("Shutting down appsec helper");

let shutdown_sym_name = CString::new("appsec_helper_shutdown").unwrap();

let func_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, shutdown_sym_name.as_ptr()) };
if func_ptr.is_null() {
error!("Failed to load appsec helper: can't find the symbol 'appsec_helper_shutdown'");
return false;
}
let appsec_shutdown_fn: extern "C" fn() -> i32 = unsafe { std::mem::transmute(func_ptr) };
let res = appsec_shutdown_fn();
if res != 0 {
error!("Appsec helper failed to shutdown");
return false;
}

info!("Appsec helper shutdown");
true
}

0 comments on commit cc67ce5

Please sign in to comment.