Skip to content

Commit 6464638

Browse files
committed
Added a rate limit test and cleaned up a bit
1 parent 6c3d967 commit 6464638

1 file changed

Lines changed: 82 additions & 63 deletions

File tree

tests/tests/signer_jwt_auth.rs

Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ use std::{collections::HashMap, time::Duration};
33
use alloy::{hex, primitives::FixedBytes};
44
use cb_common::{
55
commit::{constants::GET_PUBKEYS_PATH, request::GetPubkeysResponse},
6+
config::StartSignerConfig,
67
signer::{SignerLoader, ValidatorKeysFormat},
78
types::{Chain, ModuleId},
89
utils::create_jwt,
910
};
1011
use cb_signer::service::SigningService;
1112
use cb_tests::utils::{get_signer_config, get_start_signer_config, setup_test_env};
1213
use eyre::Result;
14+
use reqwest::{Response, StatusCode};
1315
use tracing::info;
1416

1517
const JWT_MODULE: &str = "test-module";
@@ -18,66 +20,75 @@ const JWT_SECRET: &str = "test-jwt-secret";
1820
#[tokio::test]
1921
async fn test_signer_jwt_auth_success() -> Result<()> {
2022
setup_test_env();
21-
let chain = Chain::Hoodi;
23+
let module_id = ModuleId(JWT_MODULE.to_string());
24+
let start_config = start_server().await?;
2225

23-
// Mock JWT secrets
26+
// Run a pubkeys request
27+
let jwt = create_jwt(&module_id, JWT_SECRET)?;
28+
let client = reqwest::Client::new();
29+
let url = format!("http://{}{}", start_config.endpoint, GET_PUBKEYS_PATH);
30+
let response = client.get(&url).bearer_auth(&jwt).send().await?;
31+
32+
// Verify the expected pubkeys are returned
33+
verify_pubkeys(response).await?;
34+
35+
Ok(())
36+
}
37+
38+
#[tokio::test]
39+
async fn test_signer_jwt_auth_fail() -> Result<()> {
40+
setup_test_env();
2441
let module_id = ModuleId(JWT_MODULE.to_string());
25-
let mut jwts = HashMap::new();
26-
jwts.insert(module_id.clone(), JWT_SECRET.to_string());
42+
let start_config = start_server().await?;
2743

28-
// Create a signer config
29-
let loader = SignerLoader::ValidatorsDir {
30-
keys_path: "data/keystores/keys".into(),
31-
secrets_path: "data/keystores/secrets".into(),
32-
format: ValidatorKeysFormat::Lighthouse,
33-
};
34-
let config = get_signer_config(loader);
35-
let host = config.host;
36-
let port = config.port;
37-
let start_config = get_start_signer_config(config, chain, jwts);
44+
// Run a pubkeys request - this should fail due to invalid JWT
45+
let jwt = create_jwt(&module_id, "incorrect secret")?;
46+
let client = reqwest::Client::new();
47+
let url = format!("http://{}{}", start_config.endpoint, GET_PUBKEYS_PATH);
48+
let response = client.get(&url).bearer_auth(&jwt).send().await?;
49+
assert!(response.status() == StatusCode::UNAUTHORIZED);
50+
info!(
51+
"Server returned expected error code {} for invalid JWT: {}",
52+
response.status(),
53+
response.text().await.unwrap_or_else(|_| "No response body".to_string())
54+
);
55+
Ok(())
56+
}
3857

39-
// Run the Signer
40-
let server_handle = tokio::spawn(SigningService::run(start_config));
58+
#[tokio::test]
59+
async fn test_signer_jwt_rate_limit() -> Result<()> {
60+
setup_test_env();
61+
let module_id = ModuleId(JWT_MODULE.to_string());
62+
let start_config = start_server().await?;
4163

42-
// Make sure the server is running
43-
tokio::time::sleep(Duration::from_millis(100)).await;
44-
if server_handle.is_finished() {
45-
return Err(eyre::eyre!(
46-
"Signer service failed to start: {}",
47-
server_handle.await.unwrap_err()
48-
));
64+
// Run as many pubkeys requests as the fail limit
65+
let jwt = create_jwt(&module_id, "incorrect secret")?;
66+
let client = reqwest::Client::new();
67+
let url = format!("http://{}{}", start_config.endpoint, GET_PUBKEYS_PATH);
68+
for _ in 0..start_config.jwt_auth_fail_limit {
69+
let response = client.get(&url).bearer_auth(&jwt).send().await?;
70+
assert!(response.status() == StatusCode::UNAUTHORIZED);
4971
}
5072

51-
// Create a JWT header
73+
// Run another request - this should fail due to rate limiting now
5274
let jwt = create_jwt(&module_id, JWT_SECRET)?;
75+
let response = client.get(&url).bearer_auth(&jwt).send().await?;
76+
assert!(response.status() == StatusCode::TOO_MANY_REQUESTS);
5377

54-
// Run a pubkeys request
55-
let client = reqwest::Client::new();
56-
let url = format!("http://{}:{}{}", host, port, GET_PUBKEYS_PATH);
57-
let response = client.get(&url).bearer_auth(jwt).send().await?;
58-
assert!(response.status().is_success(), "Failed to authenticate with JWT");
59-
let pubkey_json = response.json::<GetPubkeysResponse>().await?;
78+
// Wait for the rate limit timeout
79+
tokio::time::sleep(Duration::from_secs(start_config.jwt_auth_fail_timeout_seconds as u64))
80+
.await;
6081

61-
// Verify the expected pubkeys are returned
62-
assert_eq!(pubkey_json.keys.len(), 2);
63-
let expected_pubkeys = vec![
64-
FixedBytes::new(hex!("883827193f7627cd04e621e1e8d56498362a52b2a30c9a1c72036eb935c4278dee23d38a24d2f7dda62689886f0c39f4")),
65-
FixedBytes::new(hex!("b3a22e4a673ac7a153ab5b3c17a4dbef55f7e47210b20c0cbb0e66df5b36bb49ef808577610b034172e955d2312a61b9")),
66-
];
67-
for expected in expected_pubkeys {
68-
assert!(
69-
pubkey_json.keys.iter().any(|k| k.consensus == expected),
70-
"Expected pubkey not found: {:?}",
71-
expected
72-
);
73-
info!("Server returned expected pubkey: {:?}", expected);
74-
}
82+
// Now the next request should succeed
83+
let response = client.get(&url).bearer_auth(&jwt).send().await?;
84+
verify_pubkeys(response).await?;
7585

7686
Ok(())
7787
}
7888

79-
#[tokio::test]
80-
async fn test_signer_jwt_auth_fail() -> Result<()> {
89+
// Starts the signer moduler server on a separate task and returns its
90+
// configuration
91+
async fn start_server() -> Result<StartSignerConfig> {
8192
setup_test_env();
8293
let chain = Chain::Hoodi;
8394

@@ -92,13 +103,13 @@ async fn test_signer_jwt_auth_fail() -> Result<()> {
92103
secrets_path: "data/keystores/secrets".into(),
93104
format: ValidatorKeysFormat::Lighthouse,
94105
};
95-
let config = get_signer_config(loader);
96-
let host = config.host;
97-
let port = config.port;
106+
let mut config = get_signer_config(loader);
107+
config.jwt_auth_fail_limit = 3; // Set a low fail limit for testing
108+
config.jwt_auth_fail_timeout_seconds = 3; // Set a short timeout for testing
98109
let start_config = get_start_signer_config(config, chain, jwts);
99110

100111
// Run the Signer
101-
let server_handle = tokio::spawn(SigningService::run(start_config));
112+
let server_handle = tokio::spawn(SigningService::run(start_config.clone()));
102113

103114
// Make sure the server is running
104115
tokio::time::sleep(Duration::from_millis(100)).await;
@@ -108,19 +119,27 @@ async fn test_signer_jwt_auth_fail() -> Result<()> {
108119
server_handle.await.unwrap_err()
109120
));
110121
}
122+
Ok(start_config)
123+
}
111124

112-
// Create a JWT header
113-
let jwt = create_jwt(&module_id, "incorrect secret")?;
114-
115-
// Run a pubkeys request
116-
let client = reqwest::Client::new();
117-
let url = format!("http://{}:{}{}", host, port, GET_PUBKEYS_PATH);
118-
let response = client.get(&url).bearer_auth(jwt).send().await?;
119-
assert!(response.status().is_client_error(), "Failed to authenticate with JWT");
120-
info!(
121-
"Server returned expected error code {} for invalid JWT: {}",
122-
response.status(),
123-
response.text().await.unwrap_or_else(|_| "No response body".to_string())
124-
);
125+
// Verifies that the pubkeys returned by the server match the pubkeys in the
126+
// test data
127+
async fn verify_pubkeys(response: Response) -> Result<()> {
128+
// Verify the expected pubkeys are returned
129+
assert!(response.status() == StatusCode::OK);
130+
let pubkey_json = response.json::<GetPubkeysResponse>().await?;
131+
assert_eq!(pubkey_json.keys.len(), 2);
132+
let expected_pubkeys = vec![
133+
FixedBytes::new(hex!("883827193f7627cd04e621e1e8d56498362a52b2a30c9a1c72036eb935c4278dee23d38a24d2f7dda62689886f0c39f4")),
134+
FixedBytes::new(hex!("b3a22e4a673ac7a153ab5b3c17a4dbef55f7e47210b20c0cbb0e66df5b36bb49ef808577610b034172e955d2312a61b9")),
135+
];
136+
for expected in expected_pubkeys {
137+
assert!(
138+
pubkey_json.keys.iter().any(|k| k.consensus == expected),
139+
"Expected pubkey not found: {:?}",
140+
expected
141+
);
142+
info!("Server returned expected pubkey: {:?}", expected);
143+
}
125144
Ok(())
126145
}

0 commit comments

Comments
 (0)