Skip to content

Commit 0cee20c

Browse files
committed
fixup! Keep API keys within one instance
This commit was created with assistance from Codex.
1 parent 72341f0 commit 0cee20c

3 files changed

Lines changed: 83 additions & 21 deletions

File tree

ldk-server-cli/src/main.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use clap_complete::{generate, Shell};
1515
use hex_conservative::{DisplayHex, FromHex};
1616
use ldk_server_client::client::LdkServerClient;
1717
use ldk_server_client::config::{
18-
get_default_config_path, load_config, read_tls_certificate, resolve_api_key, resolve_base_url,
19-
resolve_cert_path, Config, DEFAULT_GRPC_SERVICE_ADDRESS,
18+
get_default_config_path, load_config, read_tls_certificate, resolve_api_key,
19+
resolve_api_key_path, resolve_base_url, resolve_cert_path, Config,
20+
DEFAULT_GRPC_SERVICE_ADDRESS,
2021
};
2122
use ldk_server_client::error::LdkServerError;
2223
use ldk_server_client::error::LdkServerErrorCode::{
@@ -644,13 +645,22 @@ async fn main() {
644645
std::process::exit(1);
645646
});
646647

648+
let api_key_path = resolve_api_key_path(config.as_ref());
647649
let api_key = resolve_api_key(cli.api_key, config.as_ref())
648650
.unwrap_or_else(|e| {
649651
eprintln!("Failed to resolve API key: {e}");
650652
std::process::exit(1);
651653
})
652654
.unwrap_or_else(|| {
653-
eprintln!("API key not provided. Use --api-key or ensure the api_key file exists at {DEFAULT_DIR}/[network]/api_key");
655+
match api_key_path {
656+
Some(path) => eprintln!(
657+
"API key not provided. Use --api-key or ensure the api_key file exists at '{}'",
658+
path.display()
659+
),
660+
None => eprintln!(
661+
"API key not provided. Use --api-key; no API key file path could be resolved from the configuration"
662+
),
663+
}
654664
std::process::exit(1);
655665
});
656666

ldk-server-client/src/config.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ pub fn resolve_base_url(override_url: Option<String>, config: Option<&Config>) -
155155

156156
/// Resolves the API key used to authenticate against the `ldk-server` gRPC endpoint.
157157
///
158-
/// Prefers `override_key`, falls back to reading the API key file from the configured storage
159-
/// directory, and finally from the OS-specific default data directory. The raw bytes read from
160-
/// disk are lower-hex encoded before being returned.
158+
/// Prefers `override_key`. Otherwise, reads the API key file from the configured storage
159+
/// directory when one is set, or from the OS-specific default data directory when one is not.
160+
/// A failed read from a configured storage directory does not fall back to the default data
161+
/// directory. The raw bytes read from disk are lower-hex encoded before being returned.
161162
///
162163
/// Returns an error if a candidate API key file exists but cannot be read or does not contain
163164
/// exactly 32 bytes.
@@ -168,19 +169,24 @@ pub fn resolve_api_key(
168169
return Ok(override_key);
169170
}
170171

172+
match resolve_api_key_path(config) {
173+
Some(path) => read_api_key(&path),
174+
None => Ok(None),
175+
}
176+
}
177+
178+
/// Resolves the API key file path selected by [`resolve_api_key`] when no override is given.
179+
///
180+
/// Uses the configured storage directory when one is set. Uses the OS-specific default data
181+
/// directory only when no storage directory is configured.
182+
pub fn resolve_api_key_path(config: Option<&Config>) -> Option<PathBuf> {
171183
let network = match config {
172-
Some(config) => match config.network() {
173-
Ok(network) => network,
174-
Err(_) => return Ok(None),
175-
},
184+
Some(config) => config.network().ok()?,
176185
None => "bitcoin".to_string(),
177186
};
178187
match storage_dir(config) {
179-
Some(dir) => read_api_key(&api_key_path_for_storage_dir(dir, &network)),
180-
None => match get_default_api_key_path(&network) {
181-
Some(path) => read_api_key(&path),
182-
None => Ok(None),
183-
},
188+
Some(dir) => Some(api_key_path_for_storage_dir(dir, &network)),
189+
None => get_default_api_key_path(&network),
184190
}
185191
}
186192

@@ -254,7 +260,7 @@ mod tests {
254260

255261
use super::{
256262
get_default_api_key_path, load_config, read_tls_certificate, resolve_api_key,
257-
resolve_base_url, Config, API_KEY_FILE, CONFIG_FILE_SIZE_LIMIT,
263+
resolve_api_key_path, resolve_base_url, Config, API_KEY_FILE, CONFIG_FILE_SIZE_LIMIT,
258264
DEFAULT_GRPC_SERVICE_ADDRESS, TLS_CERT_FILE_SIZE_LIMIT,
259265
};
260266

@@ -426,6 +432,10 @@ mod tests {
426432
))
427433
.unwrap();
428434

435+
assert_eq!(
436+
resolve_api_key_path(Some(&config)),
437+
Some(configured_storage.join("regtest").join(API_KEY_FILE))
438+
);
429439
let resolved = resolve_api_key(None, Some(&config));
430440

431441
restore_env_var(&default_dir_env_var, old_default_dir);

ldk-server-mcp/src/config.rs

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
use std::path::PathBuf;
1111

1212
use ldk_server_client::config::{
13-
get_default_config_path, load_config, read_tls_certificate, resolve_api_key, resolve_base_url,
14-
resolve_cert_path,
13+
get_default_config_path, load_config, read_tls_certificate, resolve_api_key,
14+
resolve_api_key_path, resolve_base_url, resolve_cert_path,
1515
};
1616

1717
pub struct ResolvedConfig {
@@ -48,9 +48,14 @@ pub fn resolve_config(config_path: Option<String>) -> Result<ResolvedConfig, Str
4848

4949
let base_url = resolve_base_url(env_base_url, config.as_ref());
5050

51-
let api_key = resolve_api_key(env_api_key, config.as_ref())?.ok_or_else(
52-
|| "API key not provided. Set LDK_API_KEY or ensure the api_key file exists at ~/.ldk-server/[network]/api_key".to_string()
53-
)?;
51+
let api_key_path = resolve_api_key_path(config.as_ref());
52+
let api_key = resolve_api_key(env_api_key, config.as_ref())?.ok_or_else(|| match api_key_path {
53+
Some(path) => format!(
54+
"API key not provided. Set LDK_API_KEY or ensure the api_key file exists at '{}'",
55+
path.display()
56+
),
57+
None => "API key not provided. Set LDK_API_KEY; no API key file path could be resolved from the configuration".to_string(),
58+
})?;
5459

5560
let tls_cert_path = resolve_cert_path(env_tls_cert_path, config.as_ref()).ok_or_else(|| {
5661
"TLS cert path not provided. Set LDK_TLS_CERT_PATH or ensure config file exists at ~/.ldk-server/config.toml"
@@ -254,4 +259,41 @@ mod tests {
254259

255260
std::fs::remove_dir_all(temp_dir).unwrap();
256261
}
262+
263+
#[test]
264+
fn resolve_config_reports_missing_key_in_storage_dir() {
265+
let _lock = ENV_LOCK.lock().unwrap();
266+
267+
let temp_dir = std::env::temp_dir()
268+
.join(format!("ldk-server-mcp-missing-storage-key-{}", std::process::id()));
269+
let custom_storage = temp_dir.join("custom-storage");
270+
std::fs::create_dir_all(&custom_storage).unwrap();
271+
272+
let config_path = temp_dir.join("config.toml");
273+
std::fs::write(
274+
&config_path,
275+
format!(
276+
r#"
277+
[node]
278+
network = "regtest"
279+
280+
[storage.disk]
281+
dir_path = "{}"
282+
"#,
283+
custom_storage.display()
284+
),
285+
)
286+
.unwrap();
287+
288+
std::env::remove_var("LDK_API_KEY");
289+
std::env::remove_var("LDK_TLS_CERT_PATH");
290+
std::env::remove_var("LDK_BASE_URL");
291+
let error = resolve_config(Some(config_path.display().to_string())).err().unwrap();
292+
293+
assert!(
294+
error.contains(&custom_storage.join("regtest").join("api_key").display().to_string())
295+
);
296+
297+
std::fs::remove_dir_all(temp_dir).unwrap();
298+
}
257299
}

0 commit comments

Comments
 (0)