-
Notifications
You must be signed in to change notification settings - Fork 48
refactor: load Nostr private key from file instead of config #704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| mostro.db* | ||
| mostro.log | ||
| lnurl-test-server/target | ||
| vendor | ||
|
|
||
| # IDE's | ||
| .idea | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,7 +85,7 @@ impl AppContext { | |
|
|
||
| /// Mostro's Nostr signing keys. | ||
| /// | ||
| /// Parsed once at startup from `settings.nostr.nsec_privkey`. | ||
| /// Parsed once at startup from `settings.nostr.nsec_privkey_file`. | ||
| /// Use this instead of `get_keys()` to avoid re-parsing on every call. | ||
| pub fn keys(&self) -> &Keys { | ||
| &self.keys | ||
|
|
@@ -99,6 +99,7 @@ pub mod test_utils { | |
| DatabaseSettings, ExpirationSettings, LightningSettings, MostroSettings, NostrSettings, | ||
| RpcSettings, | ||
| }; | ||
| use std::sync::atomic::{AtomicU64, Ordering}; | ||
|
|
||
| /// Test helper wrapper for inspecting the shared order-message queue. | ||
| #[derive(Debug, Clone)] | ||
|
|
@@ -228,10 +229,17 @@ pub mod test_utils { | |
| .order_msg_queue | ||
| .unwrap_or_else(|| Arc::new(RwLock::new(Vec::new()))); | ||
|
|
||
| // Use provided keys or parse from settings | ||
| // Use provided keys or load from nsec_privkey_file | ||
| let keys = self.keys.unwrap_or_else(|| { | ||
| Keys::parse(&settings.nostr.nsec_privkey) | ||
| .expect("TestContextBuilder: invalid nsec_privkey in settings") | ||
| let nsec = std::fs::read_to_string(&settings.nostr.nsec_privkey_file) | ||
| .unwrap_or_else(|e| { | ||
| panic!( | ||
| "TestContextBuilder: failed to read nsec_privkey_file '{}': {}", | ||
| settings.nostr.nsec_privkey_file, e | ||
| ) | ||
| }); | ||
| Keys::parse(nsec.trim()) | ||
| .expect("TestContextBuilder: invalid nsec in nsec_privkey_file") | ||
| }); | ||
|
|
||
| AppContext::new(pool, nostr_client, settings, order_msg_queue, keys) | ||
|
|
@@ -251,17 +259,29 @@ pub mod test_utils { | |
| } | ||
| } | ||
|
|
||
| static TEST_KEY_FILE_COUNTER: AtomicU64 = AtomicU64::new(0); | ||
|
|
||
| /// Generate deterministic test settings with sensible defaults. | ||
| pub fn test_settings() -> Settings { | ||
| let nsec_key = "nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd"; | ||
| let counter = TEST_KEY_FILE_COUNTER.fetch_add(1, Ordering::Relaxed); | ||
| let nsec_dir = std::env::temp_dir().join(format!( | ||
| "mostro-test-{}-{}", | ||
| std::process::id(), | ||
| counter | ||
| )); | ||
| std::fs::create_dir_all(&nsec_dir).expect("failed to create test nsec key directory"); | ||
| let nsec_path = nsec_dir.join("nostr-key.nsec"); | ||
| std::fs::write(&nsec_path, nsec_key).expect("failed to write test nsec key file"); | ||
|
|
||
|
Comment on lines
+266
to
+276
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid committing a valid-looking Line 266 embeds a real-looking Nostr private key, and secret scanners will keep flagging it even if it is only test data. Prefer generating a throwaway key at test setup time or loading a scanner-excluded fixture so this path stops producing false-positive secret incidents. 🧰 Tools🪛 Betterleaks (1.1.1)[high] 266-266: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) 🤖 Prompt for AI Agents |
||
| Settings { | ||
| database: DatabaseSettings { | ||
| url: "sqlite::memory:".to_string(), | ||
| }, | ||
| nostr: NostrSettings { | ||
| // Valid test nsec from src/config/mod.rs tests | ||
| nsec_privkey: "nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd" | ||
| .to_string(), | ||
| nsec_privkey_file: nsec_path.to_string_lossy().to_string(), | ||
| relays: vec!["wss://relay.test".to_string()], | ||
| ..Default::default() | ||
| }, | ||
| mostro: MostroSettings::default(), | ||
| lightning: LightningSettings::default(), | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,7 +59,7 @@ mod tests { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Fake settings for the test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const NOSTR_SETTINGS: &str = r#"[nostr] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nsec_privkey = 'nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nsec_privkey_file = '/tmp/mostro-test-nostr-key.nsec' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relays = ['wss://relay.damus.io','wss://relay.mostro.network']"#; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const LIGHTNING_SETTINGS: &str = r#"[lightning] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -194,15 +194,32 @@ mod tests { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let nostr_settings: StubSettingsNostr = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| toml::from_str(NOSTR_SETTINGS).expect("Failed to deserialize"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nostr_settings.nostr.nsec_privkey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nostr_settings.nostr.nsec_privkey_file, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/tmp/mostro-test-nostr-key.nsec" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!(nostr_settings.nostr.nsec_privkey, None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nostr_settings.nostr.relays, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vec!["wss://relay.damus.io", "wss://relay.mostro.network"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn test_nostr_settings_legacy_inline_key() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let legacy_settings = r#"[nostr] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nsec_privkey = 'nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relays = ['wss://relay.damus.io']"#; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let nostr_settings: StubSettingsNostr = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| toml::from_str(legacy_settings).expect("Failed to deserialize"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!(nostr_settings.nostr.nsec_privkey_file, ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nostr_settings.nostr.nsec_privkey.as_deref(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some("nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!(nostr_settings.nostr.relays, vec!["wss://relay.damus.io"]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+207
to
+220
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use an obvious dummy value instead of a real-looking This test only exercises TOML deserialization, so the long Suggested tweak- nsec_privkey = 'nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd'
+ nsec_privkey = 'legacy-inline-key-for-test-only'
...
- Some("nsec13as48eum93hkg7plv526r9gjpa0uc52zysqm93pmnkca9e69x6tsdjmdxd")
+ Some("legacy-inline-key-for-test-only")📝 Committable suggestion
Suggested change
🧰 Tools🪛 Betterleaks (1.1.1)[high] 210-210: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn test_mostro_settings() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Parse TOML content | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep the template path aligned with the runtime default location.
run_setup_wizard()now writes the key under the Mostro settings dir, and the docs/examples point to~/.mostro/nostr-key.nsec. Leaving/home/user/nostr-key.nsechere makes the copied template inconsistent and easy to misconfigure.Suggested tweak
Based on learnings, copy from
settings.tpl.tomlto~/.mostro/settings.tomlfor local runs.📝 Committable suggestion
🤖 Prompt for AI Agents