Skip to content

Commit 197fcc0

Browse files
authored
Do not override existing keys when using stellar keys add without --overwrite. (#2253)
1 parent fd2f9a3 commit 197fcc0

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

FULL_HELP_DOCS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ Add a new identity (keypair, ledger, OS specific secure store)
10021002
- `--global` — ⚠️ Deprecated: global config is always on
10031003
- `--config-dir <CONFIG_DIR>` — Location of config directory. By default, it uses `$XDG_CONFIG_HOME/stellar` if set, falling back to `~/.config/stellar` otherwise. Contains configuration files, aliases, and other persistent settings
10041004
- `--public-key <PUBLIC_KEY>` — Add a public key, ed25519, or muxed account, e.g. G1.., M2..
1005+
- `--overwrite` — Overwrite existing identity if it already exists
10051006

10061007
## `stellar keys public-key`
10071008

cmd/crates/soroban-test/tests/it/integration/keys.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,56 @@ async fn overwrite_identity() {
9090

9191
assert_ne!(initial_pubkey, pubkey_for_identity(sandbox, "test2"));
9292
}
93+
94+
#[tokio::test]
95+
#[allow(clippy::too_many_lines)]
96+
async fn overwrite_identity_with_add() {
97+
let sandbox = &TestEnv::new();
98+
sandbox
99+
.new_assert_cmd("keys")
100+
.arg("generate")
101+
.arg("test3")
102+
.assert()
103+
.success();
104+
105+
let initial_pubkey = sandbox
106+
.new_assert_cmd("keys")
107+
.arg("address")
108+
.arg("test3")
109+
.assert()
110+
.stdout_as_str();
111+
112+
// Try to add a key with the same name, should fail
113+
sandbox
114+
.new_assert_cmd("keys")
115+
.arg("add")
116+
.arg("test3")
117+
.arg("--public-key")
118+
.arg("GAKSH6AD2IPJQELTHIOWDAPYX74YELUOWJLI2L4RIPIPZH6YQIFNUSDC")
119+
.assert()
120+
.stderr(predicate::str::contains(
121+
"error: An identity with the name 'test3' already exists",
122+
));
123+
124+
// Verify the key wasn't changed
125+
assert_eq!(initial_pubkey, pubkey_for_identity(sandbox, "test3"));
126+
127+
// Try again with --overwrite flag, should succeed
128+
sandbox
129+
.new_assert_cmd("keys")
130+
.arg("add")
131+
.arg("test3")
132+
.arg("--public-key")
133+
.arg("GAKSH6AD2IPJQELTHIOWDAPYX74YELUOWJLI2L4RIPIPZH6YQIFNUSDC")
134+
.arg("--overwrite")
135+
.assert()
136+
.stderr(predicate::str::contains("Overwriting identity 'test3'"))
137+
.success();
138+
139+
// Verify the key was changed
140+
assert_ne!(initial_pubkey, pubkey_for_identity(sandbox, "test3"));
141+
assert_eq!(
142+
"GAKSH6AD2IPJQELTHIOWDAPYX74YELUOWJLI2L4RIPIPZH6YQIFNUSDC",
143+
pubkey_for_identity(sandbox, "test3").trim()
144+
);
145+
}

cmd/soroban-cli/src/commands/keys/add.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pub enum Error {
3131

3232
#[error("secret input error")]
3333
PasswordRead,
34+
35+
#[error("An identity with the name '{0}' already exists")]
36+
IdentityAlreadyExists(String),
3437
}
3538

3639
#[derive(Debug, clap::Parser, Clone)]
@@ -48,11 +51,24 @@ pub struct Cmd {
4851
/// Add a public key, ed25519, or muxed account, e.g. G1.., M2..
4952
#[arg(long, conflicts_with = "seed_phrase", conflicts_with = "secret_key")]
5053
pub public_key: Option<String>,
54+
55+
/// Overwrite existing identity if it already exists.
56+
#[arg(long)]
57+
pub overwrite: bool,
5158
}
5259

5360
impl Cmd {
5461
pub fn run(&self, global_args: &global::Args) -> Result<(), Error> {
5562
let print = Print::new(global_args.quiet);
63+
64+
if self.config_locator.read_identity(&self.name).is_ok() {
65+
if !self.overwrite {
66+
return Err(Error::IdentityAlreadyExists(self.name.to_string()));
67+
}
68+
69+
print.exclaimln(format!("Overwriting identity '{}'", &self.name.to_string()));
70+
}
71+
5672
let key = if let Some(key) = self.public_key.as_ref() {
5773
key.parse()?
5874
} else {

0 commit comments

Comments
 (0)