Skip to content

Commit e5ef5a4

Browse files
temp(datasect): fix code after rebase
1 parent 9abba93 commit e5ef5a4

8 files changed

Lines changed: 104 additions & 120 deletions

File tree

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,52 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_library")
12
load("@rules_rust//rust:defs.bzl", "rust_shared_library", "rust_test")
23

34
# Rust shared-library checks are Linux-only.
45
_LINUX = ["@platforms//os:linux"]
56

6-
# Backend engines to compile in.
77
_FEATURES = ["engine-postgres"]
88

9-
# cdylib loaded by the shared-library check loader.
9+
# proto deps pull in C++; link libstdc++ explicitly.
10+
cc_library(
11+
name = "cpp_stdlib",
12+
linkopts = ["-lstdc++"],
13+
target_compatible_with = _LINUX,
14+
)
15+
1016
rust_shared_library(
1117
name = "datasecurity",
1218
srcs = glob(["src/**/*.rs"]),
13-
# Cargo renames `dd-sensitive-data-scanner` to `dd_sds`
1419
aliases = {
20+
"//pkg/collector/sharedlibrary/rustchecks/core": "shlib_core",
1521
"@crates//:dd-sensitive-data-scanner": "dd_sds",
1622
},
1723
crate_features = _FEATURES,
1824
crate_name = "datasecurity",
1925
edition = "2024",
26+
link_deps = [":cpp_stdlib"],
27+
# Use the Bazel proto crate instead of the cargo build-script path (src/proto.rs).
28+
rustc_flags = ["--cfg=bazel"],
2029
target_compatible_with = _LINUX,
2130
visibility = ["//visibility:public"],
2231
deps = [
2332
"//pkg/collector/sharedlibrary/rustchecks/core",
33+
"//pkg/proto/datadog/sds:sds_rust_proto",
34+
"//pkg/proto/datadog/sds:timestamp_rust_proto",
2435
"@crates//:anyhow",
2536
"@crates//:dd-sensitive-data-scanner",
2637
"@crates//:libc",
2738
"@crates//:postgres",
39+
"@crates//:prost",
2840
"@crates//:serde",
2941
"@crates//:serde_json",
3042
],
3143
)
3244

33-
# Unit tests embedded in the crate sources (run with `bazel test`).
3445
rust_test(
3546
name = "datasecurity_test",
3647
crate = ":datasecurity",
3748
crate_features = _FEATURES,
3849
edition = "2024",
50+
rustc_flags = ["--cfg=bazel"],
3951
target_compatible_with = _LINUX,
4052
)

pkg/collector/sharedlibrary/rustchecks/checks/datasecurity/build.rs

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,14 @@
33
// This product includes software developed at Datadog (https://www.datadoghq.com/).
44
// Copyright 2026-present Datadog, Inc.
55

6-
// Compiles the canonical SDS result proto with prost-build so the check can
7-
// serialize `SdsResultPayload` messages. The crate is built with cargo.
8-
//
9-
// Canonical source: pkg/proto/datadog/sds/sds_result.proto
10-
// Requires `protoc` on PATH (e.g. `brew install protobuf`).
6+
// cargo-only proto codegen into OUT_DIR; Bazel uses the sds_proto crate (see src/proto.rs).
7+
// Requires `protoc` on PATH.
118

129
fn main() -> Result<(), Box<dyn std::error::Error>> {
13-
let proto_root = "../../../../../proto";
14-
let proto_file = "../../../../../proto/datadog/sds/sds_result.proto";
15-
16-
println!("cargo:rerun-if-changed={proto_file}");
17-
18-
let mut config = prost_build::Config::new();
19-
20-
// TODO(DSEC): remove this serde derive once debugging ends — it only exists to
21-
// emit the SDS result payload as JSON (see `send_sds_result_json`), which we do
22-
// not need in production. `google.protobuf.Timestamp` (prost-types) has no serde
23-
// support, so its fields use a local `serialize_with` helper.
24-
config.type_attribute(".", "#[derive(serde::Serialize)]");
25-
for field in [
26-
".datadog.sds.SdsResultPayload.ScanMetadata.ScanTaskMetadata.started_at",
27-
".datadog.sds.SdsResultPayload.ScanMetadata.ScanTaskMetadata.ended_at",
28-
] {
29-
config.field_attribute(
30-
field,
31-
"#[serde(serialize_with = \"crate::proto::serialize_timestamp\")]",
32-
);
33-
}
34-
35-
config.compile_protos(&[proto_file], &[proto_root])?;
36-
10+
println!("cargo::rustc-check-cfg=cfg(bazel)");
11+
prost_build::compile_protos(
12+
&["../../../../../proto/datadog/sds/sds_result.proto"],
13+
&["../../../../../proto"],
14+
)?;
3715
Ok(())
3816
}

pkg/collector/sharedlibrary/rustchecks/checks/datasecurity/src/check.rs

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::time::{SystemTime, UNIX_EPOCH};
22

33
use anyhow::{Context, Result, anyhow};
4-
use shlib_core::*;
54
use serde_json::Value;
5+
use shlib_core::*;
66

77
use crate::backend;
88
use crate::config::{CheckConfig, SubTask};
@@ -61,9 +61,14 @@ fn run_sub_task(
6161
Ok(out) => {
6262
println!(
6363
"datasecurity: sub task succeeded ({} match(es))",
64-
matches.len()
64+
out.matches.len()
6565
);
66-
(ScanStatus::Success, String::new(), out.matches, out.scanned_row_count)
66+
(
67+
ScanStatus::Success,
68+
String::new(),
69+
out.matches,
70+
out.scanned_row_count,
71+
)
6772
}
6873
Err(err) => {
6974
let reason = format!("{err:#}");
@@ -93,26 +98,6 @@ fn run_sub_task(
9398
check.event_platform_event_bytes(&proto::encode(&payload), SDS_RESULT_EVENT_TYPE)?;
9499
}
95100

96-
// TODO(DSEC): remove this JSON event once the protobuf is validated end to
97-
// end — we do not need to send SDS results as JSON. It is serialized from the
98-
// same protobuf so the two representations cannot drift.
99-
if config.send_sds_result_json {
100-
let payload_json =
101-
proto::to_json(&payload).context("failed to serialize sds result payload to json")?;
102-
check.event(
103-
"datasecurity scan result",
104-
&payload_json,
105-
0,
106-
"normal",
107-
"",
108-
&[],
109-
"info",
110-
"",
111-
"datasecurity",
112-
"",
113-
)?;
114-
}
115-
116101
Ok(())
117102
}
118103

@@ -182,7 +167,11 @@ fn build_sds_result(
182167
r#type: "postgres_table".to_string(),
183168
name: resource_name(sub_task),
184169
}),
185-
rule_ids: config.scanning_rules.iter().map(|rule| rule.id.clone()).collect(),
170+
rule_ids: config
171+
.scanning_rules
172+
.iter()
173+
.map(|rule| rule.id.clone())
174+
.collect(),
186175
// The scanning source is the Agent. TODO(DSEC): populate hostname and
187176
// agent version once the check receives them (not provided via config yet).
188177
scanning_source: Some(proto::ScanningSource {

pkg/collector/sharedlibrary/rustchecks/checks/datasecurity/src/config.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::{Context, Result};
2-
use shlib_core::AgentCheck;
32
use serde::Deserialize;
3+
use shlib_core::AgentCheck;
44

55
use crate::scanning::ScanningRule;
66

@@ -21,9 +21,6 @@ impl CheckConfig {
2121
.context("failed to read scan_data from instance config")?,
2222
// Emit the SDS result protobuf on the `sds-result` track (default on).
2323
send_sds_result: check.instance.get("send_sds_result").unwrap_or(true),
24-
// TODO(DSEC): debug only, off by default. Remove once the protobuf is
25-
// validated end to end.
26-
send_sds_result_json: check.instance.get("send_sds_result_json").unwrap_or(false),
2724
})
2825
}
2926
}
@@ -37,13 +34,6 @@ pub struct CheckConfig {
3734
/// Emit the SDS result protobuf on the `sds-result` event platform track.
3835
#[serde(default)]
3936
pub send_sds_result: bool,
40-
/// Emit the SDS result payload as JSON (serialized from the same protobuf) as
41-
/// a regular event.
42-
///
43-
/// TODO(DSEC): debug only, remove once the protobuf is validated end to end —
44-
/// we do not need to send SDS results as JSON.
45-
#[serde(default)]
46-
pub send_sds_result_json: bool,
4737
}
4838

4939
/// A single scan sub task: a query to run against one data source.
Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,41 @@
11
//! Protobuf construction for SDS results.
22
//!
3-
//! The crate is built with cargo: `build.rs` compiles
4-
//! `pkg/proto/datadog/sds/sds_result.proto` with prost-build and this module
5-
//! includes the generated code from `OUT_DIR`. The check builds these
6-
//! prost-generated types directly (no intermediate structs).
3+
//! The `datadog.sds` types are prost-generated: from `OUT_DIR` under cargo, from
4+
//! the `sds_proto` crate under Bazel.
75
8-
use std::time::SystemTime;
6+
use std::time::{SystemTime, UNIX_EPOCH};
97

108
use prost::Message;
11-
use prost_types::Timestamp;
12-
use serde::Serialize;
139

1410
use crate::payload::Match;
1511

12+
// cargo maps well-known types to `prost-types`; the Bazel toolchain to a `timestamp_proto` crate.
13+
#[cfg(not(bazel))]
14+
use prost_types::Timestamp;
15+
#[cfg(bazel)]
16+
use timestamp_proto::google::protobuf::Timestamp;
17+
18+
#[cfg(not(bazel))]
1619
pub mod datadog {
1720
pub mod sds {
1821
include!(concat!(env!("OUT_DIR"), "/datadog.sds.rs"));
1922
}
2023
}
2124

25+
#[cfg(bazel)]
26+
pub mod datadog {
27+
pub mod sds {
28+
pub use sds_proto::datadog::sds::*;
29+
}
30+
}
31+
2232
// Proto types the check assembles directly.
2333
pub use datadog::sds::{
24-
scanning_source,
34+
ScanningSource, SdsResultPayload, scanning_source,
2535
sds_result_payload::{
26-
scan_location,
27-
scan_metadata::{scan_task_metadata::Status, ScanTaskMetadata},
28-
PostgresTable, Resource, ScanLocation, ScanMetadata, ScanResult, TableMatch,
36+
PostgresTable, Resource, ScanLocation, ScanMetadata, ScanResult, TableMatch, scan_location,
37+
scan_metadata::{ScanTaskMetadata, scan_task_metadata::Status},
2938
},
30-
ScanningSource, SdsResultPayload,
3139
};
3240

3341
/// Convert aggregated scanner matches into proto `TableMatch` entries.
@@ -45,42 +53,17 @@ pub fn table_matches(matches: &[Match]) -> Vec<TableMatch> {
4553

4654
/// Convert a wall-clock time into a proto `Timestamp`.
4755
pub fn to_timestamp(time: SystemTime) -> Timestamp {
48-
Timestamp::from(time)
56+
let (seconds, nanos) = match time.duration_since(UNIX_EPOCH) {
57+
Ok(d) => (d.as_secs() as i64, d.subsec_nanos() as i32),
58+
Err(e) => {
59+
let d = e.duration();
60+
(-(d.as_secs() as i64), -(d.subsec_nanos() as i32))
61+
}
62+
};
63+
Timestamp { seconds, nanos }
4964
}
5065

5166
/// Marshal `payload` to protobuf bytes for the `sds-result` event platform track.
5267
pub fn encode(payload: &SdsResultPayload) -> Vec<u8> {
5368
payload.encode_to_vec()
5469
}
55-
56-
/// Serialize `payload` to JSON, from the same protobuf sent on the wire.
57-
///
58-
/// TODO(DSEC): debug only, remove once the protobuf is validated end to end.
59-
pub fn to_json(payload: &SdsResultPayload) -> serde_json::Result<String> {
60-
serde_json::to_string(payload)
61-
}
62-
63-
/// Serde helper for the prost-types `Timestamp` fields, which have no serde
64-
/// support of their own. Serializes `Some` as `{ "seconds", "nanos" }` and
65-
/// `None` as null. Referenced by generated code via `build.rs`.
66-
///
67-
/// TODO(DSEC): remove alongside the JSON debug event.
68-
pub fn serialize_timestamp<S>(ts: &Option<Timestamp>, serializer: S) -> Result<S::Ok, S::Error>
69-
where
70-
S: serde::Serializer,
71-
{
72-
#[derive(serde::Serialize)]
73-
struct SerdeTimestamp {
74-
seconds: i64,
75-
nanos: i32,
76-
}
77-
78-
match ts {
79-
Some(ts) => SerdeTimestamp {
80-
seconds: ts.seconds,
81-
nanos: ts.nanos,
82-
}
83-
.serialize(serializer),
84-
None => serializer.serialize_none(),
85-
}
86-
}

pkg/collector/sharedlibrary/rustchecks/checks/datasecurity/src/scanning/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use shlib_core::Config;
21
use dd_sds::{
32
Labels, ProximityKeywordsConfig, RegexRuleConfig, RootRuleConfig, SecondaryValidator,
43
Suppressions,
54
};
65
use serde_json::json;
6+
use shlib_core::Config;
77

88
use crate::payload::Match;
99

pkg/collector/sharedlibrary/rustchecks/core/src/agent_check.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,10 @@ impl AgentCheck {
254254
raw_event: &[u8],
255255
event_track_type: &str,
256256
) -> Result<()> {
257-
self.aggregator
258-
.submit_event_platform_event_bytes(&self.check_id, raw_event, event_track_type)
257+
self.aggregator.submit_event_platform_event_bytes(
258+
&self.check_id,
259+
raw_event,
260+
event_track_type,
261+
)
259262
}
260263
}

pkg/proto/datadog/sds/BUILD.bazel

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
1-
# Compiled with prost-build (cargo) by the datasecurity Rust check; not built or
2-
# consumed by Bazel. Disable proto generation inherited from ../BUILD.bazel.
3-
# gazelle:proto disable
1+
load("@protobuf//bazel:proto_library.bzl", "proto_library")
2+
load("@rules_go//proto:def.bzl", "go_proto_library")
3+
load("@rules_rust_prost//:defs.bzl", "rust_prost_library")
44

5-
exports_files(["sds_result.proto"])
5+
proto_library(
6+
name = "sds_proto",
7+
srcs = ["sds_result.proto"],
8+
strip_import_prefix = "/pkg/proto",
9+
visibility = ["//visibility:public"],
10+
deps = ["@protobuf//:timestamp_proto"],
11+
)
12+
13+
go_proto_library(
14+
name = "sds_go_proto",
15+
importpath = "pkg/proto/pbgo/sds",
16+
proto = ":sds_proto",
17+
visibility = ["//visibility:public"],
18+
)
19+
20+
# Rust bindings for the datasecurity check (Linux-only).
21+
rust_prost_library(
22+
name = "sds_rust_proto",
23+
proto = ":sds_proto",
24+
target_compatible_with = ["@platforms//os:linux"],
25+
visibility = ["//visibility:public"],
26+
)
27+
28+
# Well-known types get their own `timestamp_proto` crate; expose it for Timestamp construction.
29+
rust_prost_library(
30+
name = "timestamp_rust_proto",
31+
proto = "@protobuf//:timestamp_proto",
32+
target_compatible_with = ["@platforms//os:linux"],
33+
visibility = ["//visibility:public"],
34+
)

0 commit comments

Comments
 (0)