Skip to content

Commit 9f6c682

Browse files
committed
chore: Merge branch 'main' into feat/crd-versioning
2 parents 2586e77 + 0e4076b commit 9f6c682

File tree

14 files changed

+1125
-37
lines changed

14 files changed

+1125
-37
lines changed

Cargo.toml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,20 @@ kube = { version = "0.89.0", default-features = false, features = ["client", "js
3333
lazy_static = "1.4.0"
3434
opentelemetry = "0.22.0"
3535
opentelemetry_sdk = { version = "0.22.1", features = ["rt-tokio"] }
36+
opentelemetry-appender-tracing = "0.3.0"
3637
opentelemetry-jaeger = { version = "0.21.0", features = ["rt-tokio"] }
38+
opentelemetry-otlp = "0.15.0"
39+
opentelemetry-semantic-conventions = "0.14.0"
3740
p256 = { version = "0.13.2", features = ["ecdsa"] }
41+
pin-project = "1.1.5"
3842
proc-macro2 = "1.0.79"
3943
quote = "1.0.35"
4044
rand = "0.8.5"
4145
rand_core = "0.6.4"
4246
regex = "1.10.4"
4347
rsa = { version = "0.9.6", features = ["sha2"] }
4448
rstest = "0.18.2"
45-
schemars = "0.8.16"
49+
schemars = { version = "0.8.16", features = ["url"] }
4650
semver = "1.0.22"
4751
serde = { version = "1.0.197", features = ["derive"] }
4852
serde_json = "1.0.115"
@@ -63,6 +67,12 @@ tower-http = { version = "0.5.2", features = ["trace"] }
6367
tracing = "0.1.40"
6468
tracing-opentelemetry = "0.23.0"
6569
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
66-
url = "2.5.0"
70+
url = { version = "2.5.0", features = ["serde"] }
6771
x509-cert = { version = "0.2.5", features = ["builder"] }
6872
zeroize = "1.7.0"
73+
74+
# Use O3 in tests to improve the RSA key generation speed in the stackable-certs crate
75+
[profile.test.package.stackable-certs]
76+
opt-level = 3
77+
[profile.test.package."rsa"]
78+
opt-level = 3

crates/stackable-certs/src/ca/mod.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ where
270270
/// It is also possible to directly greate RSA or ECDSA-based leaf
271271
/// certificates using [`CertificateAuthority::generate_rsa_leaf_certificate`]
272272
/// and [`CertificateAuthority::generate_ecdsa_leaf_certificate`].
273-
#[instrument(skip(key_pair))]
273+
#[instrument(skip(self, key_pair))]
274274
pub fn generate_leaf_certificate<T>(
275275
&mut self,
276276
key_pair: T,
@@ -304,8 +304,6 @@ where
304304
// The leaf certificate can be used for WWW client and server
305305
// authentication. This is a base requirement for TLS certs.
306306
let eku = ExtendedKeyUsage(vec![ID_KP_CLIENT_AUTH, ID_KP_SERVER_AUTH]);
307-
let aki = AuthorityKeyIdentifier::try_from(spki.owned_to_ref())
308-
.context(ParseAuthorityKeyIdentifierSnafu)?;
309307

310308
let signer = self.certificate_pair.key_pair.signing_key();
311309
let mut builder = CertificateBuilder::new(
@@ -331,9 +329,6 @@ where
331329
builder
332330
.add_extension(&eku)
333331
.context(AddCertificateExtensionSnafu)?;
334-
builder
335-
.add_extension(&aki)
336-
.context(AddCertificateExtensionSnafu)?;
337332

338333
debug!("create and sign leaf certificate");
339334
let certificate = builder.build().context(BuildCertificateSnafu)?;
@@ -348,7 +343,7 @@ where
348343
///
349344
/// See [`CertificateAuthority::generate_leaf_certificate`] for more
350345
/// information.
351-
#[instrument]
346+
#[instrument(skip(self))]
352347
pub fn generate_rsa_leaf_certificate(
353348
&mut self,
354349
name: &str,
@@ -363,7 +358,7 @@ where
363358
///
364359
/// See [`CertificateAuthority::generate_leaf_certificate`] for more
365360
/// information.
366-
#[instrument]
361+
#[instrument(skip(self))]
367362
pub fn generate_ecdsa_leaf_certificate(
368363
&mut self,
369364
name: &str,
@@ -477,14 +472,16 @@ mod test {
477472
use super::*;
478473

479474
#[tokio::test]
480-
async fn test() {
475+
async fn test_rsa_key_generation() {
481476
let mut ca = CertificateAuthority::new_rsa().unwrap();
482-
ca.generate_leaf_certificate(
483-
rsa::SigningKey::new().unwrap(),
484-
"Airflow",
485-
"pod",
486-
Duration::from_secs(3600),
487-
)
488-
.unwrap();
477+
ca.generate_rsa_leaf_certificate("Airflow", "pod", Duration::from_secs(3600))
478+
.unwrap();
479+
}
480+
481+
#[tokio::test]
482+
async fn test_ecdsa_key_generation() {
483+
let mut ca = CertificateAuthority::new_ecdsa().unwrap();
484+
ca.generate_ecdsa_leaf_certificate("Airflow", "pod", Duration::from_secs(3600))
485+
.unwrap();
489486
}
490487
}

crates/stackable-certs/src/keys/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! [`ecdsa`], which provides primitives and traits, and [`p256`] which
1010
//! implements the NIST P-256 elliptic curve and supports ECDSA.
1111
//!
12-
//! ```
12+
//! ```ignore
1313
//! use stackable_certs::keys::ecdsa::SigningKey;
1414
//! let key = SigningKey::new().unwrap();
1515
//! ```
@@ -18,7 +18,7 @@
1818
//!
1919
//! In order to work with RSA keys, this crate requires the [`rsa`] dependency.
2020
//!
21-
//! ```
21+
//! ```ignore
2222
//! use stackable_certs::keys::rsa::SigningKey;
2323
//! let key = SigningKey::new().unwrap();
2424
//! ```

crates/stackable-certs/src/keys/rsa.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ use tracing::instrument;
99

1010
use crate::keys::CertificateKeypair;
1111

12+
#[cfg(not(test))]
1213
const KEY_SIZE: usize = 4096;
1314

15+
#[cfg(test)]
16+
const KEY_SIZE: usize = 512;
17+
1418
pub type Result<T, E = Error> = std::result::Result<T, E>;
1519

1620
#[derive(Debug, PartialEq, Snafu)]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "stackable-telemetry"
3+
version = "0.1.0"
4+
authors.workspace = true
5+
license.workspace = true
6+
edition.workspace = true
7+
repository.workspace = true
8+
9+
[dependencies]
10+
axum.workspace = true
11+
futures-util.workspace = true
12+
opentelemetry = { workspace = true, features = ["logs"] }
13+
opentelemetry-appender-tracing.workspace = true
14+
opentelemetry-otlp = { workspace = true, features = ["gzip-tonic", "logs"] }
15+
opentelemetry-semantic-conventions.workspace = true
16+
opentelemetry_sdk = { workspace = true, features = ["logs", "rt-tokio"] }
17+
pin-project.workspace = true
18+
snafu.workspace = true
19+
tokio.workspace = true
20+
tower.workspace = true
21+
tracing.workspace = true
22+
tracing-opentelemetry.workspace = true
23+
tracing-subscriber = { workspace = true, features = ["env-filter"] }
24+
25+
[dev-dependencies]
26+
tokio.workspace = true
27+
tracing-opentelemetry.workspace = true
28+
stackable-webhook = { path = "../stackable-webhook" }
29+
30+
[package.metadata.cargo-udeps.ignore]
31+
# Required for doc tests in stackable-telemetry
32+
development = ["stackable-webhook"]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use axum::http::{HeaderMap, HeaderName};
2+
use opentelemetry::{propagation::Extractor, Context};
3+
4+
/// Extracts the [`TextMapPropagator`][1] to access trace parent information in
5+
/// HTTP headers.
6+
///
7+
/// This propagation is useful when an HTTP request already has a trace parent
8+
/// which can be picked up by the Tower [`Layer`][2] to link both spans together.
9+
/// A concrete usage example is available in [`SpanExt::from_request`][3].
10+
///
11+
/// This is pretty much a copy-pasted version of the [`HeaderExtractor`][4] from
12+
/// the `opentelemetry_http` crate. However, we cannot use this crate, as it
13+
/// uses an outdated version of the underlying `http` crate.
14+
///
15+
/// [1]: opentelemetry::propagation::TextMapPropagator
16+
/// [2]: tower::Layer
17+
/// [3]: crate::instrumentation::axum::SpanExt::from_request
18+
/// [4]: https://docs.rs/opentelemetry-http/latest/opentelemetry_http/struct.HeaderExtractor.html
19+
pub struct HeaderExtractor<'a>(pub(crate) &'a HeaderMap);
20+
21+
impl<'a> Extractor for HeaderExtractor<'a> {
22+
fn get(&self, key: &str) -> Option<&str> {
23+
self.0
24+
.get(key)
25+
.and_then(|header_value| header_value.to_str().ok())
26+
}
27+
28+
fn keys(&self) -> Vec<&str> {
29+
self.0.keys().map(HeaderName::as_str).collect()
30+
}
31+
}
32+
33+
impl<'a> HeaderExtractor<'a> {
34+
/// Create a new header extractor from a reference to a [`HeaderMap`].
35+
pub fn new(headers: &'a HeaderMap) -> Self {
36+
Self(headers)
37+
}
38+
39+
/// Extracts the [`TextMapPropagator`][1] from the HTTP headers.
40+
///
41+
/// [1]: opentelemetry::propagation::TextMapPropagator
42+
pub fn extract_context(&self) -> Context {
43+
opentelemetry::global::get_text_map_propagator(|propagator| propagator.extract(self))
44+
}
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use axum::http::{HeaderMap, HeaderName, HeaderValue};
2+
use opentelemetry::{propagation::Injector, Context};
3+
4+
/// Injects the [`TextMapPropagator`][1] to propagate trace parent information
5+
/// in HTTP headers.
6+
///
7+
/// This propagation is useful when consumers of the HTTP response want to link
8+
/// up their span data with the data produced in the Tower [`Layer`][2].
9+
/// A concrete usage example is available in the [`TraceService::call`][3]
10+
/// implementation for [`TraceService`][4].
11+
///
12+
/// This is pretty much a copy-pasted version of the [`HeaderInjector`][5] from
13+
/// the `opentelemetry_http` crate. However, we cannot use this crate, as it
14+
/// uses an outdated version of the underlying `http` crate.
15+
///
16+
/// [1]: opentelemetry::propagation::TextMapPropagator
17+
/// [2]: tower::Layer
18+
/// [3]: tower::Service::call
19+
/// [4]: crate::instrumentation::axum::TraceService
20+
/// [5]: https://docs.rs/opentelemetry-http/latest/opentelemetry_http/struct.HeaderInjector.html
21+
pub struct HeaderInjector<'a>(pub(crate) &'a mut HeaderMap);
22+
23+
impl<'a> Injector for HeaderInjector<'a> {
24+
fn set(&mut self, key: &str, value: String) {
25+
if let Ok(header_name) = HeaderName::from_bytes(key.as_bytes()) {
26+
if let Ok(header_value) = HeaderValue::from_str(&value) {
27+
self.0.insert(header_name, header_value);
28+
}
29+
}
30+
}
31+
}
32+
33+
impl<'a> HeaderInjector<'a> {
34+
/// Create a new header injecttor from a mutable reference to [`HeaderMap`].
35+
pub fn new(headers: &'a mut HeaderMap) -> Self {
36+
Self(headers)
37+
}
38+
39+
/// Inject the [`TextMapPropagator`][1] into the HTTP headers.
40+
///
41+
/// [1]: opentelemetry::propagation::TextMapPropagator
42+
pub fn inject_context(&mut self, cx: &Context) {
43+
opentelemetry::global::get_text_map_propagator(|propagator| {
44+
propagator.inject_context(cx, self)
45+
})
46+
}
47+
}

0 commit comments

Comments
 (0)