Skip to content

Commit d7e8fee

Browse files
authored
Support loading appsec helper in sidecar (#565)
1 parent 9895dd2 commit d7e8fee

File tree

3 files changed

+137
-7
lines changed

3 files changed

+137
-7
lines changed

sidecar/src/config.rs

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ const DEFAULT_IDLE_LINGER_TIME: Duration = Duration::from_secs(60);
2424

2525
const ENV_SIDECAR_SELF_TELEMETRY: &str = "_DD_SIDECAR_SELF_TELEMETRY";
2626

27+
const ENV_SIDECAR_APPSEC_SHARED_LIB_PATH: &str = "_DD_SIDECAR_APPSEC_SHARED_LIB_PATH";
28+
const ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_SOCKET_FILE_PATH";
29+
const ENV_SIDECAR_APPSEC_LOCK_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_LOCK_FILE_PATH";
30+
const ENV_SIDECAR_APPSEC_LOG_FILE_PATH: &str = "_DD_SIDECAR_APPSEC_LOG_FILE_PATH";
31+
const ENV_SIDECAR_APPSEC_LOG_LEVEL: &str = "_DD_SIDECAR_APPSEC_LOG_LEVEL";
32+
2733
#[derive(Debug, Copy, Clone)]
2834
pub enum IpcMode {
2935
Shared,
@@ -78,22 +84,66 @@ pub struct Config {
7884
pub self_telemetry: bool,
7985
pub library_dependencies: Vec<LibDependency>,
8086
pub child_env: HashMap<std::ffi::OsString, std::ffi::OsString>,
87+
pub appsec_config: Option<AppSecConfig>,
88+
}
89+
90+
#[derive(Debug, Clone)]
91+
pub struct AppSecConfig {
92+
pub shared_lib_path: std::ffi::OsString,
93+
pub socket_file_path: std::ffi::OsString,
94+
pub lock_file_path: std::ffi::OsString,
95+
pub log_file_path: std::ffi::OsString,
96+
pub log_level: String,
8197
}
8298

8399
impl Config {
84100
pub fn get() -> Self {
85101
FromEnv::config()
86102
}
87103

88-
pub fn to_env(&self) -> HashMap<&'static str, String> {
89-
HashMap::from([
90-
(ENV_SIDECAR_IPC_MODE, self.ipc_mode.to_string()),
91-
(ENV_SIDECAR_LOG_METHOD, self.log_method.to_string()),
104+
pub fn to_env(&self) -> HashMap<&'static str, std::ffi::OsString> {
105+
let mut res = HashMap::from([
106+
(ENV_SIDECAR_IPC_MODE, self.ipc_mode.to_string().into()),
107+
(ENV_SIDECAR_LOG_METHOD, self.log_method.to_string().into()),
92108
(
93109
ENV_IDLE_LINGER_TIME_SECS,
94-
self.idle_linger_time.as_secs().to_string(),
110+
self.idle_linger_time.as_secs().to_string().into(),
111+
),
112+
(
113+
ENV_SIDECAR_SELF_TELEMETRY,
114+
self.self_telemetry.to_string().into(),
115+
),
116+
]);
117+
if self.appsec_config.is_some() {
118+
res.extend(self.appsec_config.as_ref().unwrap().to_env());
119+
}
120+
res
121+
}
122+
}
123+
124+
impl AppSecConfig {
125+
pub fn to_env(&self) -> HashMap<&'static str, std::ffi::OsString> {
126+
HashMap::from([
127+
(
128+
ENV_SIDECAR_APPSEC_SHARED_LIB_PATH,
129+
self.shared_lib_path.to_owned(),
130+
),
131+
(
132+
ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH,
133+
self.socket_file_path.to_owned(),
134+
),
135+
(
136+
ENV_SIDECAR_APPSEC_LOCK_FILE_PATH,
137+
self.lock_file_path.to_owned(),
138+
),
139+
(
140+
ENV_SIDECAR_APPSEC_LOG_FILE_PATH,
141+
self.log_file_path.to_owned(),
142+
),
143+
(
144+
ENV_SIDECAR_APPSEC_LOG_LEVEL,
145+
self.log_level.to_owned().into(),
95146
),
96-
(ENV_SIDECAR_SELF_TELEMETRY, self.self_telemetry.to_string()),
97147
])
98148
}
99149
}
@@ -159,8 +209,25 @@ impl FromEnv {
159209
self_telemetry: Self::self_telemetry(),
160210
library_dependencies: vec![],
161211
child_env: std::env::vars_os().collect(),
212+
appsec_config: Self::appsec_config(),
162213
}
163214
}
215+
216+
pub fn appsec_config() -> Option<AppSecConfig> {
217+
let shared_lib_path = std::env::var_os(ENV_SIDECAR_APPSEC_SHARED_LIB_PATH)?;
218+
let socket_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_SOCKET_FILE_PATH)?;
219+
let lock_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_LOCK_FILE_PATH)?;
220+
let log_file_path = std::env::var_os(ENV_SIDECAR_APPSEC_LOG_FILE_PATH)?;
221+
let log_level = std::env::var(ENV_SIDECAR_APPSEC_LOG_LEVEL).ok()?;
222+
223+
Some(AppSecConfig {
224+
shared_lib_path,
225+
socket_file_path,
226+
lock_file_path,
227+
log_file_path,
228+
log_level,
229+
})
230+
}
164231
}
165232

166233
pub fn get_product_endpoint(subdomain: &str, endpoint: &Endpoint) -> Endpoint {

sidecar/src/entry.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,15 @@ pub fn daemonize(listener: IpcServer, cfg: Config) -> anyhow::Result<()> {
166166

167167
setup_daemon_process(listener, &mut spawn_cfg)?;
168168

169+
let mut lib_deps = cfg.library_dependencies;
170+
if cfg.appsec_config.is_some() {
171+
lib_deps.push(spawn_worker::LibDependency::Path(
172+
cfg.appsec_config.unwrap().shared_lib_path.into(),
173+
));
174+
}
175+
169176
spawn_cfg
170-
.shared_lib_dependencies(cfg.library_dependencies)
177+
.shared_lib_dependencies(lib_deps)
171178
.wait_spawn()
172179
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
173180
.context("Could not spawn the sidecar daemon")?;

sidecar/src/unix.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

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

6+
use std::ffi::CString;
67
use std::os::unix::net::UnixListener as StdUnixListener;
78

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

2931
let now = Instant::now();
3032

33+
let appsec_started = maybe_start_appsec();
34+
3135
if let Some(fd) = spawn_worker::recv_passed_fd() {
3236
let listener: StdUnixListener = fd.into();
3337
info!("Starting sidecar, pid: {}", getpid());
@@ -56,6 +60,10 @@ pub extern "C" fn ddog_daemon_entry_point() {
5660
}
5761
}
5862

63+
if appsec_started {
64+
shutdown_appsec();
65+
}
66+
5967
info!(
6068
"shutting down sidecar, pid: {}, total runtime: {:.3}s",
6169
getpid(),
@@ -89,3 +97,51 @@ pub fn setup_daemon_process(
8997
pub fn primary_sidecar_identifier() -> u32 {
9098
unsafe { libc::geteuid() }
9199
}
100+
101+
fn maybe_start_appsec() -> bool {
102+
let cfg = FromEnv::appsec_config();
103+
if cfg.is_none() {
104+
return false;
105+
}
106+
107+
info!("Starting appsec helper");
108+
109+
let entrypoint_sym_name = CString::new("appsec_helper_main").unwrap();
110+
111+
let func_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, entrypoint_sym_name.as_ptr()) };
112+
if func_ptr.is_null() {
113+
error!("Failed to load appsec helper: can't find the symbol 'appsec_helper_main'");
114+
return false;
115+
}
116+
117+
let appsec_entry_fn: extern "C" fn() -> i32 = unsafe { std::mem::transmute(func_ptr) };
118+
let res = appsec_entry_fn();
119+
if res != 0 {
120+
error!("Appsec helper failed to start");
121+
return false;
122+
}
123+
124+
info!("Appsec helper started");
125+
true
126+
}
127+
128+
fn shutdown_appsec() -> bool {
129+
info!("Shutting down appsec helper");
130+
131+
let shutdown_sym_name = CString::new("appsec_helper_shutdown").unwrap();
132+
133+
let func_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, shutdown_sym_name.as_ptr()) };
134+
if func_ptr.is_null() {
135+
error!("Failed to load appsec helper: can't find the symbol 'appsec_helper_shutdown'");
136+
return false;
137+
}
138+
let appsec_shutdown_fn: extern "C" fn() -> i32 = unsafe { std::mem::transmute(func_ptr) };
139+
let res = appsec_shutdown_fn();
140+
if res != 0 {
141+
error!("Appsec helper failed to shutdown");
142+
return false;
143+
}
144+
145+
info!("Appsec helper shutdown");
146+
true
147+
}

0 commit comments

Comments
 (0)