Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions attestation-gateway/src/nonces/nonce_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,21 @@ pub enum NonceDbError {

#[derive(Clone)]
pub struct NonceDb {
// redis: ConnectionManager,
redis: ConnectionManager,
}

impl NonceDb {
// #[must_use]
// #[expect(clippy::missing_const_for_fn)] // `ConnectionManager` is not usable in `const`
// pub fn new(redis: ConnectionManager) -> Self {
// Self { redis }
// }

pub fn new() -> Self {
Self {}
#[must_use]
#[expect(clippy::missing_const_for_fn)] // `ConnectionManager` is not usable in `const`
pub fn new(redis: ConnectionManager) -> Self {
Self { redis }
}

/// # Errors
///
/// When `token_details` cannot be serialized to JSON, or Redis rejects `SET`.
pub async fn generate_nonce(
&mut self,
redis: &mut ConnectionManager,
token_details: &TokenDetails,
) -> Result<String, NonceDbError> {
let mut nonce = [0; 16];
Expand All @@ -56,7 +51,7 @@ impl NonceDb {
))
.conditional_set(ExistenceCheck::NX);

redis
self.redis
.set_options::<String, String>(key, value, options)
.await
.map_err(NonceDbError::RedisError)?;
Expand All @@ -67,13 +62,10 @@ impl NonceDb {
/// # Errors
///
/// When Redis `GETDEL` fails, the value is missing, or JSON does not decode to [`TokenDetails`].
pub async fn consume_nonce(
&mut self,
redis: &mut ConnectionManager,
nonce: &str,
) -> Result<TokenDetails, NonceDbError> {
pub async fn consume_nonce(&mut self, nonce: &str) -> Result<TokenDetails, NonceDbError> {
let key = format!("nonce:{nonce}");
let value = redis
let value = self
.redis
.get_del::<String>(key)
.await
.map_err(NonceDbError::RedisError)?
Expand Down
29 changes: 13 additions & 16 deletions attestation-gateway/src/routes/a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,24 +122,21 @@ pub async fn handler(
});
}

let token_details = nonce_db
.consume_nonce(&mut redis, &request.nonce)
.await
.map_err(|e| {
if matches!(e, NonceDbError::NonceNotFound) {
RequestError {
code: ErrorCode::BadRequest,
details: Some("Nonce not found".to_string()),
}
} else {
tracing::error!(error = ?e, "Error consuming token nonce");
let token_details = nonce_db.consume_nonce(&request.nonce).await.map_err(|e| {
if matches!(e, NonceDbError::NonceNotFound) {
RequestError {
code: ErrorCode::BadRequest,
details: Some("Nonce not found".to_string()),
}
} else {
tracing::error!(error = ?e, "Error consuming token nonce");

RequestError {
code: ErrorCode::InternalServerError,
details: Some("Error consuming token nonce".to_string()),
}
RequestError {
code: ErrorCode::InternalServerError,
details: Some("Error consuming token nonce".to_string()),
}
})?;
}
})?;

let challenge = format!("n={},av={}", request.nonce, request.app_version);
let platform = request.bundle_identifier.platform();
Expand Down
19 changes: 7 additions & 12 deletions attestation-gateway/src/routes/c.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use axum::{Extension, Json};
use chrono::{DateTime, Utc};
use redis::aio::ConnectionManager;
use schemars::JsonSchema;

use crate::nonces::{NonceDb, TokenDetails};
Expand Down Expand Up @@ -40,7 +39,6 @@ pub struct Response {
/// ```
pub async fn handler(
Extension(mut nonce_db): Extension<NonceDb>,
Extension(mut redis): Extension<ConnectionManager>,
Extension(global_config): Extension<GlobalConfig>,
Json(request): Json<Request>,
) -> Result<Json<Response>, RequestError> {
Expand All @@ -56,17 +54,14 @@ pub async fn handler(
}

let token_details = TokenDetails::from_aud(request.aud.clone());
let nonce = nonce_db
.generate_nonce(&mut redis, &token_details)
.await
.map_err(|e| {
tracing::error!(error = ?e, "Failed to generate nonce.");
let nonce = nonce_db.generate_nonce(&token_details).await.map_err(|e| {
tracing::error!(error = ?e, "Failed to generate nonce.");

RequestError {
code: ErrorCode::InternalServerError,
details: Some("Failed to generate nonce.".to_string()),
}
})?;
RequestError {
code: ErrorCode::InternalServerError,
details: Some("Failed to generate nonce.".to_string()),
}
})?;

let device_key_expires_at =
DateTime::<Utc>::from_timestamp(token_details.exp_max, 0).ok_or(RequestError {
Expand Down
2 changes: 1 addition & 1 deletion attestation-gateway/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub async fn start(
..Default::default()
};

let nonce_db = NonceDb::new();
let nonce_db = NonceDb::new(redis.clone());

let android_rate_limit_per_day = env::var("ANDROID_RATE_LIMIT_PER_DAY").ok().map(|v| {
v.parse()
Expand Down
12 changes: 7 additions & 5 deletions attestation-gateway/tests/generate_token_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ fn get_global_config_extension_with_pem(
Extension(config)
}

fn extension_nonce_db() -> Extension<attestation_gateway::nonces::NonceDb> {
Extension(attestation_gateway::nonces::NonceDb::new())
fn extension_nonce_db(
redis: &redis::aio::ConnectionManager,
) -> Extension<attestation_gateway::nonces::NonceDb> {
Extension(attestation_gateway::nonces::NonceDb::new(redis.clone()))
}

async fn extension_android_attestation(
Expand Down Expand Up @@ -164,7 +166,7 @@ async fn get_api_router() -> aide::axum::ApiRouter {
.layer(get_aws_config_extension().await)
.layer(get_global_config_extension())
.layer(extension_android_attestation(&redis_ext.0).await)
.layer(extension_nonce_db())
.layer(extension_nonce_db(&redis_ext.0))
.layer(redis_ext)
.layer(get_kinesis_extension().await)
}
Expand Down Expand Up @@ -662,7 +664,7 @@ async fn test_server_error_is_properly_logged() {
.layer(get_aws_config_extension().await)
.layer(get_local_config_extension())
.layer(extension_android_attestation(&redis_ext.0).await)
.layer(extension_nonce_db())
.layer(extension_nonce_db(&redis_ext.0))
.layer(redis_ext)
.layer(get_kinesis_extension().await)
}
Expand Down Expand Up @@ -730,7 +732,7 @@ async fn test_apple_initial_attestation_e2e_success() {
.layer(get_aws_config_extension().await)
.layer(get_global_config_extension_with_pem(test_data.root_ca_pem))
.layer(extension_android_attestation(&redis_ext.0).await)
.layer(extension_nonce_db())
.layer(extension_nonce_db(&redis_ext.0))
.layer(redis_ext)
.layer(get_kinesis_extension().await);

Expand Down
Loading