Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support loading appsec helper in sidecar #565

Merged
merged 1 commit into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading