-
Notifications
You must be signed in to change notification settings - Fork 14
poc: App & API Protection #695
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
Changes from 19 commits
bb7d9f0
7ee6fb7
a667b2e
241fcec
6151c67
2d10b46
c7fb357
cbcc2c6
ba7a1da
d229800
e0902ba
1d0b374
cd8e2cf
da3d640
87837d1
40c0e81
68c055f
8989366
4eaa311
26cd814
910f542
a323f47
19addc1
2582d39
c4854bd
d17cc48
383fe8e
4e54160
5d370b7
c184b42
fbd9022
3b236e7
097dbe5
64f3913
d276d88
28a8832
c580a90
cec9428
1671086
3eddce0
a2a1ccc
e80a5f0
9b922a9
abfc396
86c699b
6183ea2
09b67f8
598cdeb
61eff51
b32ac72
8f9e0d6
9f4016e
63a67cc
8c3de95
b349d91
23d8fb0
f4cea50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use std::env; | ||
|
||
use crate::config::Config; | ||
|
||
mod payload; | ||
pub mod processor; | ||
|
||
#[must_use] | ||
pub const fn is_enabled(config: &Config) -> bool { | ||
config.serverless_appsec_enabled | ||
} | ||
|
||
/// Reads the `DD_APM_TRACING_ENABLED` environment variable to determine whether ASM runs in | ||
/// standalone mode. | ||
/// | ||
/// This is a direct port of the Go logic and that is why we are not using the | ||
/// `config` crate. | ||
#[must_use] | ||
pub fn is_standalone() -> bool { | ||
let apm_tracing_enabled = env::var("DD_APM_TRACING_ENABLED"); | ||
let is_set = apm_tracing_enabled.is_ok(); | ||
|
||
let enabled = apm_tracing_enabled | ||
.unwrap_or("false".to_string()) | ||
.to_lowercase() | ||
== "true"; | ||
|
||
is_set && enabled | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
use base64::Engine; | ||
use bytes::Buf; | ||
use libddwaf::object::{WafMap, WafObject, WafString}; | ||
use mime::Mime; | ||
use tracing::{debug, warn}; | ||
|
||
pub(super) async fn parse_body( | ||
body: impl AsRef<[u8]>, | ||
is_base64_encoded: bool, | ||
content_type: Option<&str>, | ||
) -> Result<Option<WafObject>, Box<dyn std::error::Error>> { | ||
if is_base64_encoded { | ||
let body = base64::engine::general_purpose::STANDARD.decode(body)?; | ||
return Box::pin(parse_body(body, false, content_type)).await; | ||
} | ||
|
||
let body = body.as_ref(); | ||
let mime_type = match content_type | ||
.unwrap_or("application/json") | ||
.parse::<mime::Mime>() | ||
{ | ||
Ok(mime) => mime, | ||
Err(e) => return Err(e.into()), | ||
}; | ||
Comment on lines
+17
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this actually error at any moment since we're always setting the default as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can't assume the body is even valid JSON -- it comes from the client-side of the chain... Folks make mistakes! |
||
|
||
Ok(match (mime_type.type_(), mime_type.subtype()) { | ||
// text/json | application/json | application/vnd.api+json | ||
(mime::APPLICATION, sub) if sub == mime::JSON || sub == "vnd.api+json" => { | ||
Some(serde_json::from_slice(body)?) | ||
} | ||
(mime::APPLICATION, mime::WWW_FORM_URLENCODED) => Some(serde_html_form::from_bytes(body)?), | ||
(mime::APPLICATION | mime::TEXT, mime::XML) => { | ||
Some(serde_xml_rs::from_reader(body.reader())?) | ||
} | ||
(mime::MULTIPART, mime::FORM_DATA) => { | ||
let Some(boundary) = mime_type.get_param("boundary") else { | ||
warn!("appsec: cannot attempt parsing multipart/form-data without boundary"); | ||
return Ok(None); | ||
}; | ||
// We have to go through this dance because [`multer::Multipart`] requires an async stream. | ||
let body = body.to_vec(); | ||
let reader = futures::stream::iter([Result::<Vec<u8>, std::io::Error>::Ok(body)]); | ||
let mut multipart = multer::Multipart::new(reader, boundary.as_str()); | ||
|
||
let mut fields = Vec::new(); | ||
while let Some(field) = multipart.next_field().await? { | ||
let Some(name) = field.name().map(str::to_string) else { | ||
continue; | ||
}; | ||
let Some(content_type) = field.content_type().map(Mime::to_string) else { | ||
continue; | ||
}; | ||
let Some(value) = Box::pin(parse_body( | ||
field.bytes().await?, | ||
false, | ||
Some(content_type.as_ref()), | ||
)) | ||
.await? | ||
else { | ||
continue; | ||
}; | ||
fields.push((name, value)); | ||
} | ||
let mut res = WafMap::new(fields.len() as u64); | ||
for (i, (name, value)) in fields.into_iter().enumerate() { | ||
res[i] = (name.as_str(), value).into(); | ||
} | ||
Some(res.into()) | ||
} | ||
(mime::TEXT, mime::PLAIN) => Some(WafString::new(body).into()), | ||
_ => { | ||
debug!("appsec: unsupported content type: {mime_type}"); | ||
None | ||
} | ||
}) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.