fix(notary): make TLS keys and authorization whitelist configs optional (#589)

* feat: Add optional fields for TLS private key and certificate paths

* Add optional field for whitelist_csv_path

* fix test cases for whitelist_csv_path

* fix issues pointed out by yuroitaki

* Add error handling for missing PEM paths when TLS is enabled

* Fix formatting and linting

* throw error if pem files do not exist

---------

Co-authored-by: funkyenough <14842981+funkyenough@users.noreply.github.com>
This commit is contained in:
yorozunouchu
2024-11-22 19:44:06 +09:00
committed by GitHub
parent c10c9155a7
commit 7d88d1c20b
3 changed files with 51 additions and 31 deletions

View File

@@ -21,7 +21,7 @@ pub struct AuthorizationProperties {
/// Switch to turn on or off auth middleware
pub enabled: bool,
/// File path of the whitelist API key csv
pub whitelist_csv_path: String,
pub whitelist_csv_path: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Default)]
@@ -53,8 +53,8 @@ pub struct TLSProperties {
/// turned on unless TLS is handled by external setup e.g. reverse proxy,
/// cloud)
pub enabled: bool,
pub private_key_pem_path: String,
pub certificate_pem_path: String,
pub private_key_pem_path: Option<String>,
pub certificate_pem_path: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Default)]

View File

@@ -61,11 +61,19 @@ pub async fn run_server(config: &NotaryServerProperties) -> Result<(), NotarySer
debug!("Skipping TLS setup as it is turned off.");
None
} else {
let (tls_private_key, tls_certificates) = load_tls_key_and_cert(
&config.tls.private_key_pem_path,
&config.tls.certificate_pem_path,
)
.await?;
let private_key_pem_path = config
.tls
.private_key_pem_path
.as_deref()
.ok_or_else(|| eyre!("TLS is enabled but private key PEM path is not set"))?;
let certificate_pem_path = config
.tls
.certificate_pem_path
.as_deref()
.ok_or_else(|| eyre!("TLS is enabled but certificate PEM path is not set"))?;
let (tls_private_key, tls_certificates) =
load_tls_key_and_cert(private_key_pem_path, certificate_pem_path).await?;
let mut server_config = ServerConfig::builder()
.with_safe_defaults()
@@ -293,11 +301,17 @@ fn load_authorization_whitelist(
debug!("Skipping authorization as it is turned off.");
None
} else {
// Check if whitelist_csv_path is Some and convert to &str
let whitelist_csv_path = config
.authorization
.whitelist_csv_path
.as_deref()
.ok_or_else(|| {
eyre!("Authorization whitelist csv path is not provided in the config")
})?;
// Load the csv
let whitelist_csv = parse_csv_file::<AuthorizationWhitelistRecord>(
&config.authorization.whitelist_csv_path,
)
.map_err(|err| eyre!("Failed to parse authorization whitelist csv: {:?}", err))?;
let whitelist_csv = parse_csv_file::<AuthorizationWhitelistRecord>(whitelist_csv_path)
.map_err(|err| eyre!("Failed to parse authorization whitelist csv: {:?}", err))?;
// Convert the whitelist record into hashmap for faster lookup
let whitelist_hashmap = authorization_whitelist_vec_into_hashmap(whitelist_csv);
Some(whitelist_hashmap)
@@ -347,12 +361,18 @@ fn watch_and_reload_authorization_whitelist(
)
.map_err(|err| eyre!("Error occured when setting up watcher for hot reload: {err}"))?;
// Check if whitelist_csv_path is Some and convert to &str
let whitelist_csv_path = config
.authorization
.whitelist_csv_path
.as_deref()
.ok_or_else(|| {
eyre!("Authorization whitelist csv path is not provided in the config")
})?;
// Start watcher to listen to any changes on the whitelist file
watcher
.watch(
Path::new(&config.authorization.whitelist_csv_path),
RecursiveMode::Recursive,
)
.watch(Path::new(whitelist_csv_path), RecursiveMode::Recursive)
.map_err(|err| eyre!("Error occured when starting up watcher for hot reload: {err}"))?;
Some(watcher)
@@ -404,7 +424,7 @@ mod test {
let config = NotaryServerProperties {
authorization: AuthorizationProperties {
enabled: true,
whitelist_csv_path,
whitelist_csv_path: Some(whitelist_csv_path.clone()),
},
..Default::default()
};
@@ -428,16 +448,16 @@ mod test {
api_key: "unit-test-api-key".to_string(),
created_at: "unit-test-created-at".to_string(),
};
let file = OpenOptions::new()
.append(true)
.open(&config.authorization.whitelist_csv_path)
.unwrap();
let mut wtr = WriterBuilder::new()
.has_headers(false) // Set to false to avoid writing header again
.from_writer(file);
wtr.serialize(new_record).unwrap();
wtr.flush().unwrap();
if let Some(ref path) = config.authorization.whitelist_csv_path {
let file = OpenOptions::new().append(true).open(path).unwrap();
let mut wtr = WriterBuilder::new()
.has_headers(false) // Set to false to avoid writing header again
.from_writer(file);
wtr.serialize(new_record).unwrap();
wtr.flush().unwrap();
} else {
panic!("Whitelist CSV path should be provided in the config");
}
// Sleep to buy a bit of time for updated whitelist to be hot reloaded
tokio::time::sleep(Duration::from_millis(50)).await;
@@ -448,6 +468,6 @@ mod test {
.contains_key("unit-test-api-key"));
// Delete the cloned whitelist
std::fs::remove_file(&config.authorization.whitelist_csv_path).unwrap();
std::fs::remove_file(&whitelist_csv_path).unwrap();
}
}

View File

@@ -52,8 +52,8 @@ fn get_server_config(port: u16, tls_enabled: bool, auth_enabled: bool) -> Notary
},
tls: TLSProperties {
enabled: tls_enabled,
private_key_pem_path: "../server/fixture/tls/notary.key".to_string(),
certificate_pem_path: "../server/fixture/tls/notary.crt".to_string(),
private_key_pem_path: Some("../server/fixture/tls/notary.key".to_string()),
certificate_pem_path: Some("../server/fixture/tls/notary.crt".to_string()),
},
notary_key: NotarySigningKeyProperties {
private_key_pem_path: "../server/fixture/notary/notary.key".to_string(),
@@ -65,7 +65,7 @@ fn get_server_config(port: u16, tls_enabled: bool, auth_enabled: bool) -> Notary
},
authorization: AuthorizationProperties {
enabled: auth_enabled,
whitelist_csv_path: "../server/fixture/auth/whitelist.csv".to_string(),
whitelist_csv_path: Some("../server/fixture/auth/whitelist.csv".to_string()),
},
}
}