Skip to content

Commit 4524712

Browse files
chore: move reqwest adapter to the new datadog-serverless-fips crate
1 parent 1715738 commit 4524712

9 files changed

Lines changed: 51 additions & 34 deletions

File tree

.github/workflows/cargo.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,14 @@ jobs:
5353
shell: bash
5454
run: chmod +x ./scripts/install-protoc.sh && ./scripts/install-protoc.sh $HOME
5555
- shell: bash
56-
run: cargo clippy --workspace --all-features
56+
run: |
57+
if [[ "${{ inputs.runner }}" == "windows-2022" ]]; then
58+
# we don't technially support the datadog-serverless-fips module on
59+
# windows right now anyway, so let's set this so that the windows
60+
# build doesn't fail.
61+
export AWS_LC_FIPS_SYS_NO_ASM=1
62+
fi
63+
cargo clippy --workspace --all-features
5764
5865
build:
5966
name: Build

Cargo.lock

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "datadog-serverless-fips"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
license.workspace = true
6+
homepage.workspace = true
7+
repository.workspace = true
8+
9+
[dependencies]
10+
reqwest = { version = "0.12.4", features = ["json", "http2"], default-features = false }
11+
rustls = { version = "0.23.18", default-features = false, features = ["fips"], optional = true }
12+
rustls-native-certs = { version = "0.8.1", optional = true }
13+
tracing = { version = "0.1.40", default-features = false }
14+
15+
[features]
16+
default = [ "reqwest/rustls-tls" ]
17+
fips = [ "reqwest/rustls-tls-no-provider", "rustls", "rustls-native-certs" ]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Datadog Serverless FIPS
2+
3+
A package to support FIPS builds for serverless tools. Currently tested with the datadog-lambda-extension, but it may be useful in other environments.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
pub mod reqwest_adapter;

crates/dogstatsd/src/fips.rs renamed to crates/datadog-serverless-fips/src/reqwest_adapter.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ use std::error::Error;
33
#[cfg(feature = "fips")]
44
use tracing::debug;
55

6-
// TODO: once we confirm that this does what we think it does we'll move it to a separate crate.
7-
// for now going to copy the this code to bottlecap and make sure that all the clients we build do
8-
// in fact do the fips thing right.
9-
106
/// Creates a reqwest client builder with TLS configuration.
117
/// When the "fips" feature is enabled, it uses a FIPS-compliant TLS configuration.
128
/// Otherwise, it uses reqwest's default rustls TLS implementation.
@@ -20,60 +16,44 @@ pub fn create_reqwest_client_builder() -> Result<ClientBuilder, Box<dyn Error>>
2016
/// This version loads native root certificates and verifies FIPS compliance.
2117
#[cfg(feature = "fips")]
2218
pub fn create_reqwest_client_builder() -> Result<ClientBuilder, Box<dyn Error>> {
23-
// Get the runtime crypto provider that should have been configured elsewhere in the application
19+
// Get the runtime crypto provider that should have been configured at the start of the
20+
// application using something like rustls::crypto::default_fips_provider().install_default()
2421
let provider =
2522
rustls::crypto::CryptoProvider::get_default().ok_or("No crypto provider configured")?;
2623

27-
// Verify the provider is FIPS-compliant
2824
if !provider.fips() {
2925
return Err("Crypto provider is not FIPS-compliant".into());
3026
}
3127

32-
// Create an empty root cert store
3328
let mut root_cert_store = rustls::RootCertStore::empty();
34-
35-
// Load native certificates
3629
let native_certs = rustls_native_certs::load_native_certs();
37-
38-
// Add the certificates to the store
3930
let mut valid_count = 0;
40-
4131
for cert in native_certs.certs {
4232
match root_cert_store.add(cert) {
4333
Ok(()) => valid_count += 1,
4434
Err(err) => {
45-
// Optionally log errors
4635
debug!("Failed to parse certificate: {:?}", err);
4736
}
4837
}
4938
}
50-
51-
// Verify we have at least some valid certificates
5239
if valid_count == 0 {
5340
return Err("No valid certificates found in native root store".into());
5441
}
5542

56-
// Configure TLS versions (FIPS typically requires TLS 1.2 or higher)
43+
// FIPS typically requires TLS 1.2 or higher
5744
let versions = rustls::ALL_VERSIONS.to_vec();
58-
59-
// Build the client config
6045
let config_builder = rustls::ClientConfig::builder_with_provider(provider.clone())
6146
.with_protocol_versions(&versions)
6247
.map_err(|_| "Failed to set protocol versions")?;
6348

64-
// Complete the configuration without client authentication
6549
let config = config_builder
6650
.with_root_certificates(root_cert_store)
6751
.with_no_client_auth();
6852

69-
// Verify the final config is FIPS-compliant
7053
if !config.fips() {
7154
return Err("The final TLS configuration is not FIPS-compliant".into());
7255
}
73-
debug!("Client Builder is in FIPS mode");
74-
75-
// Create the reqwest client builder with our FIPS-compliant TLS configuration
76-
let client_builder = reqwest::Client::builder().use_preconfigured_tls(config);
56+
debug!("Client builder is configured with FIPS.");
7757

78-
Ok(client_builder)
58+
Ok(reqwest::Client::builder().use_preconfigured_tls(config))
7959
}

crates/dogstatsd/Cargo.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ tokio-util = { version = "0.7.11", default-features = false }
2424
tracing = { version = "0.1.40", default-features = false }
2525
regex = { version = "1.10.6", default-features = false }
2626
zstd = { version = "0.13.3", default-features = false }
27-
rustls = { version = "0.23.18", default-features = false, features = ["fips"], optional = true }
28-
rustls-native-certs = { version = "0.8.1", optional = true }
29-
27+
datadog-serverless-fips = { path = "../datadog-serverless-fips", default-features = false }
3028

3129
[dev-dependencies]
3230
mockito = { version = "1.5.0", default-features = false }
@@ -35,4 +33,4 @@ tracing-test = { version = "0.2.5", default-features = false }
3533

3634
[features]
3735
default = [ "reqwest/rustls-tls" ]
38-
fips = [ "reqwest/rustls-tls-no-provider", "rustls", "rustls-native-certs" ]
36+
fips = [ "reqwest/rustls-tls-no-provider", "datadog-serverless-fips/fips" ]

crates/dogstatsd/src/datadog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
//!Types to serialize data into the Datadog API
55
6-
use crate::fips::create_reqwest_client_builder;
76
use crate::flusher::ShippingError;
87
use datadog_protos::metrics::SketchPayload;
8+
use datadog_serverless_fips::reqwest_adapter::create_reqwest_client_builder;
99
use derive_more::{Display, Into};
1010
use protobuf::Message;
1111
use regex::Regex;

crates/dogstatsd/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ pub mod constants;
1212
pub mod datadog;
1313
pub mod dogstatsd;
1414
pub mod errors;
15-
pub mod fips;
1615
pub mod flusher;
1716
pub mod metric;

0 commit comments

Comments
 (0)