Skip to content

Commit

Permalink
alter tests
Browse files Browse the repository at this point in the history
Signed-off-by: Zahari Dichev <[email protected]>
  • Loading branch information
zaharidichev committed Dec 21, 2023
1 parent c156aa2 commit 189c777
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,7 @@ dependencies = [
"simple_asn1",
"spiffe-proto",
"tokio",
"tokio-test",
"tonic",
"tower",
"tracing",
Expand Down
1 change: 1 addition & 0 deletions linkerd/proxy/spire-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ asn1 = { version = "0.6", package = "simple_asn1" }

[dev-dependencies]
rcgen = "0.11.3"
tokio-test = "0.4"
1 change: 0 additions & 1 deletion linkerd/proxy/spire-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ impl tower::Service<()> for Client {
let socket = self.socket.clone();
let backoff = self.backoff;
Box::pin(async move {

Check warning on line 41 in linkerd/proxy/spire-client/src/client.rs

View check run for this annotation

Codecov / codecov/patch

linkerd/proxy/spire-client/src/client.rs#L38-L41

Added lines #L38 - L41 were not covered by tests
//spiffe::workload_api::client::WorkloadApiClient
// Strip the 'unix:' prefix for tonic compatibility.
let stripped_path = socket

Check warning on line 43 in linkerd/proxy/spire-client/src/client.rs

View check run for this annotation

Codecov / codecov/patch

linkerd/proxy/spire-client/src/client.rs#L43

Added line #L43 was not covered by tests
.strip_prefix(UNIX_PREFIX)
Expand Down
137 changes: 107 additions & 30 deletions linkerd/proxy/spire-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,61 @@ mod tests {
use std::collections::HashMap;
use tokio::sync::watch;

fn gen_cert(subject_alt_names: Vec<SanType>, serial: SerialNumber) -> DerX509 {
fn gen_svid(id: Id, subject_alt_names: Vec<SanType>, serial: SerialNumber) -> Svid {
let mut params = CertificateParams::default();
params.subject_alt_names = subject_alt_names;
params.serial_number = Some(serial);

DerX509(
Certificate::from_params(params)
.expect("should generate cert")
.serialize_der()
.expect("should serialize"),
)
Svid {
spiffe_id: id,
leaf: DerX509(
Certificate::from_params(params)
.expect("should generate cert")
.serialize_der()
.expect("should serialize"),
),
private_key: Vec::default(),
intermediates: Vec::default(),
}
}

fn svid_update(svids: Vec<Svid>) -> SvidUpdate {
let mut svids_map = HashMap::default();
for svid in svids.into_iter() {
svids_map.insert(svid.spiffe_id.clone(), svid);
}

SvidUpdate { svids: svids_map }
}

// TODO: use a service_fn for this mock
struct MockNewClient {
rx: watch::Receiver<SvidUpdate>,
}

impl MockNewClient {
fn new(init: SvidUpdate) -> (Self, watch::Sender<SvidUpdate>) {
let (tx, rx) = watch::channel(init);
(Self { rx }, tx)
}
}

impl tower::Service<()> for MockNewClient {
type Response = watch::Receiver<SvidUpdate>;
type Error = Error;
// type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>;

fn poll_ready(
&mut self,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
std::task::Poll::Ready(Ok(()))
}

fn call(&mut self, _req: ()) -> Self::Future {
Box::pin(futures::future::ready(Ok(self.rx.clone())))
}
}

struct MockCredentials {
Expand All @@ -125,43 +169,76 @@ mod tests {
}

#[tokio::test(flavor = "current_thread")]
async fn valid_update() {
let serial = SerialNumber::from_slice("some-serial".as_bytes());
async fn valid_updates() {
let spiffe_san = "spiffe://some-domain/some-workload";
let leaf = gen_cert(vec![SanType::URI(spiffe_san.into())], serial.clone());
let spiffe_id = Id::parse_uri("spiffe://some-domain/some-workload").expect("should parse");

let (mut creds, mut rx) = MockCredentials::new();
let svid = Svid {
spiffe_id: spiffe_id.clone(),
leaf,
private_key: Vec::default(),
intermediates: Vec::default(),
};
let mut svids = HashMap::default();
svids.insert(svid.spiffe_id.clone(), svid);
let update = SvidUpdate { svids };
let (creds, mut creds_rx) = MockCredentials::new();

let spire = Spire::new(spiffe_id.clone(), Metrics::default());

let serial_1 = SerialNumber::from_slice("some-serial-1".as_bytes());
let update_1 = svid_update(vec![gen_svid(
spiffe_id.clone(),
vec![SanType::URI(spiffe_san.into())],
serial_1.clone(),
)]);

let (client, svid_tx) = MockNewClient::new(update_1);
tokio::spawn(spire.run(creds, client));

creds_rx.changed().await.unwrap();
assert!(*creds_rx.borrow_and_update() == Some(serial_1));

let serial_2 = SerialNumber::from_slice("some-serial-2".as_bytes());
let update_2 = svid_update(vec![gen_svid(
spiffe_id.clone(),
vec![SanType::URI(spiffe_san.into())],
serial_2.clone(),
)]);

svid_tx.send(update_2).expect("should send");

assert!(process_svid(&mut creds, update, &spiffe_id).is_ok());
rx.changed().await.unwrap();
assert!(*rx.borrow_and_update() == Some(serial));
creds_rx.changed().await.unwrap();
assert!(*creds_rx.borrow_and_update() == Some(serial_2));
}

#[tokio::test(flavor = "current_thread")]
async fn invalid_update() {
let spiffe_san = "spiffe://some-domain/some-workload";
let spiffe_id = Id::parse_uri("spiffe://some-domain/some-workload").expect("should parse");
let (mut creds, mut rx) = MockCredentials::new();
let svid = Svid {

let (creds, mut creds_rx) = MockCredentials::new();

let spire = Spire::new(spiffe_id.clone(), Metrics::default());

let serial_1 = SerialNumber::from_slice("some-serial-1".as_bytes());
let update_1 = svid_update(vec![gen_svid(
spiffe_id.clone(),
vec![SanType::URI(spiffe_san.into())],
serial_1.clone(),
)]);

let (client, svid_tx) = MockNewClient::new(update_1);
tokio::spawn(spire.run(creds, client));

creds_rx.changed().await.unwrap();
assert!(*creds_rx.borrow_and_update() == Some(serial_1.clone()));

let invalid_svid = Svid {
spiffe_id: spiffe_id.clone(),
leaf: DerX509(Vec::default()),
private_key: Vec::default(),
intermediates: Vec::default(),
};
let mut svids = HashMap::default();
svids.insert(svid.spiffe_id.clone(), svid);
let update = SvidUpdate { svids };

assert!(process_svid(&mut creds, update, &spiffe_id).is_err());
assert!(rx.borrow_and_update().is_none());
let mut update_sent = svid_tx.subscribe();
let update_2 = svid_update(vec![invalid_svid]);
svid_tx.send(update_2).expect("should send");

update_sent.changed().await.unwrap();

assert!(!creds_rx.has_changed().unwrap());
assert!(*creds_rx.borrow_and_update() == Some(serial_1));
}
}

0 comments on commit 189c777

Please sign in to comment.