-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
core/commands/config: do not show private key on local network #2957
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
011a546
ea9327d
2b682f9
2fded41
f7e6590
6b97588
921ae0e
c5318e8
7270556
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 |
---|---|---|
|
@@ -9,6 +9,7 @@ import ( | |
"io/ioutil" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
|
||
cmds "github.com/ipfs/go-ipfs/commands" | ||
repo "github.com/ipfs/go-ipfs/repo" | ||
|
@@ -58,6 +59,14 @@ Set the value of the 'datastore.path' key: | |
args := req.Arguments() | ||
key := args[0] | ||
|
||
// This is a temporary fix until we move the private key out of the config file | ||
switch strings.ToLower(key) { | ||
case "identity", "identity.privkey": | ||
res.SetError(fmt.Errorf("cannot show or change private key through API"), cmds.ErrNormal) | ||
return | ||
default: | ||
} | ||
|
||
r, err := fsrepo.Open(req.InvocContext().ConfigRoot) | ||
if err != nil { | ||
res.SetError(err, cmds.ErrNormal) | ||
|
@@ -134,18 +143,40 @@ included in the output of this command. | |
}, | ||
|
||
Run: func(req cmds.Request, res cmds.Response) { | ||
filename, err := config.Filename(req.InvocContext().ConfigRoot) | ||
fname, err := config.Filename(req.InvocContext().ConfigRoot) | ||
if err != nil { | ||
res.SetError(err, cmds.ErrNormal) | ||
return | ||
} | ||
|
||
output, err := showConfig(filename) | ||
data, err := ioutil.ReadFile(fname) | ||
if err != nil { | ||
res.SetError(err, cmds.ErrNormal) | ||
return | ||
} | ||
res.SetOutput(output) | ||
|
||
var cfg map[string]interface{} | ||
err = json.Unmarshal(data, &cfg) | ||
if err != nil { | ||
res.SetError(err, cmds.ErrNormal) | ||
return | ||
} | ||
|
||
idmap, ok := cfg["Identity"].(map[string]interface{}) | ||
if !ok { | ||
res.SetError(fmt.Errorf("config has no identity"), cmds.ErrNormal) | ||
return | ||
} | ||
|
||
delete(idmap, "PrivKey") | ||
|
||
output, err := config.HumanOutput(cfg) | ||
if err != nil { | ||
res.SetError(err, cmds.ErrNormal) | ||
return | ||
} | ||
|
||
res.SetOutput(bytes.NewReader(output)) | ||
}, | ||
} | ||
|
||
|
@@ -219,22 +250,20 @@ func getConfig(r repo.Repo, key string) (*ConfigField, error) { | |
} | ||
|
||
func setConfig(r repo.Repo, key string, value interface{}) (*ConfigField, error) { | ||
err := r.SetConfigKey(key, value) | ||
keyF, err := getConfig(r, "Identity.PrivKey") | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to set config value: %s (maybe use --json?)", err) | ||
return nil, errors.New("failed to get PrivKey") | ||
} | ||
return getConfig(r, key) | ||
} | ||
|
||
func showConfig(filename string) (io.Reader, error) { | ||
// TODO maybe we should omit privkey so we don't accidentally leak it? | ||
|
||
data, err := ioutil.ReadFile(filename) | ||
privkey := keyF.Value | ||
err = r.SetConfigKey(key, value) | ||
if err != nil { | ||
return nil, err | ||
return nil, fmt.Errorf("failed to set config value: %s (maybe use --json?)", err) | ||
} | ||
|
||
return bytes.NewReader(data), nil | ||
err = r.SetConfigKey("Identity.PrivKey", privkey) | ||
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.
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. it should probably also error similarly to 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. I think we should use this opportunity to remove the private key from the config file altogether. 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. Yeah. maybe we can do another migration (4-5) that moves the key to 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. I will address this issue here in case any other callers to |
||
if err != nil { | ||
return nil, errors.New("failed to set PrivKey") | ||
} | ||
return getConfig(r, key) | ||
} | ||
|
||
func editConfig(filename string) error { | ||
|
@@ -251,8 +280,23 @@ func editConfig(filename string) error { | |
func replaceConfig(r repo.Repo, file io.Reader) error { | ||
var cfg config.Config | ||
if err := json.NewDecoder(file).Decode(&cfg); err != nil { | ||
return errors.New("Failed to decode file as config") | ||
return errors.New("failed to decode file as config") | ||
} | ||
if len(cfg.Identity.PrivKey) != 0 { | ||
return errors.New("setting private key with API is not supported") | ||
} | ||
|
||
keyF, err := getConfig(r, "Identity.PrivKey") | ||
if err != nil { | ||
return fmt.Errorf("Failed to get PrivKey") | ||
} | ||
|
||
pkstr, ok := keyF.Value.(string) | ||
if !ok { | ||
return fmt.Errorf("private key in config was not a string") | ||
} | ||
|
||
cfg.Identity.PrivKey = pkstr | ||
|
||
return r.SetConfig(&cfg) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,59 @@ test_config_cmd() { | |
grep "\"beep2\": false," actual && | ||
grep "\"beep3\": false," actual | ||
' | ||
|
||
test_expect_success "'ipfs config Identity' fails" ' | ||
test_expect_code 1 ipfs config Identity 2> ident_out | ||
' | ||
|
||
test_expect_success "output looks good" ' | ||
echo "Error: cannot show or change private key through API" > ident_exp && | ||
test_cmp ident_exp ident_out | ||
' | ||
|
||
# SECURITY | ||
# Those tests are here to prevent exposing the PrivKey on the network | ||
test_expect_success "'ipfs config Identity.PrivKey' fails" ' | ||
test_expect_code 1 ipfs config Identity.PrivKey 2> ident_out | ||
' | ||
|
||
test_expect_success "output looks good" ' | ||
test_cmp ident_exp ident_out | ||
' | ||
|
||
test_expect_success "lower cased PrivKey" ' | ||
sed -i -e '\''s/PrivKey/privkey/'\'' "$IPFS_PATH/config" && | ||
test_expect_code 1 ipfs config Identity.privkey 2> ident_out | ||
' | ||
|
||
test_expect_success "output looks good" ' | ||
test_cmp ident_exp ident_out | ||
' | ||
|
||
test_expect_success "fix it back" ' | ||
sed -i -e '\''s/privkey/PrivKey/'\'' "$IPFS_PATH/config" | ||
' | ||
|
||
test_expect_success "'ipfs config show' doesn't include privkey" ' | ||
ipfs config show > show_config && | ||
test_expect_code 1 grep PrivKey show_config | ||
' | ||
|
||
test_expect_success "'ipfs config replace' injects privkey back" ' | ||
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. add a test where the keys are lowercased? 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. added 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. @Kubuxu where is it added? not seeing it 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. Ah, I added test case for lower case key in the config file, I will add test case for 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. Adding in: #3141 |
||
ipfs config replace show_config && | ||
grep "\"PrivKey\":" "$IPFS_PATH/config" | grep -e ": \".\+\"" >/dev/null | ||
' | ||
|
||
test_expect_success "'ipfs config replace' with privkey erors out" ' | ||
cp "$IPFS_PATH/config" real_config && | ||
test_expect_code 1 ipfs config replace - < real_config 2> replace_out | ||
' | ||
|
||
test_expect_success "output looks good" ' | ||
echo "Error: setting private key with API is not supported" > replace_expected | ||
test_cmp replace_out replace_expected | ||
' | ||
|
||
} | ||
|
||
test_init_ipfs | ||
|
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.
privkey
. this should be case insensitive.Privkey
there.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.
I can also loop the map, compare keys to
privkey
case insensitive and remove that. SGTY?