mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-21 08:56:37 +08:00
117 lines
3.3 KiB
Go
117 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
cmds "github.com/ipfs/go-ipfs-cmds"
|
|
config "github.com/ipfs/go-ipfs-config"
|
|
oldcmds "github.com/ipfs/go-ipfs/commands"
|
|
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
|
|
"github.com/ipfs/interface-go-ipfs-core/options"
|
|
)
|
|
|
|
const (
|
|
oldKeyOptionName = "oldkey"
|
|
)
|
|
|
|
var rotateCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Rotates the ipfs identity.",
|
|
ShortDescription: `
|
|
Generates a new ipfs identity and saves it to the ipfs config file.
|
|
The daemon must not be running when calling this command.
|
|
|
|
ipfs uses a repository in the local file system. By default, the repo is
|
|
located at ~/.ipfs. To change the repo location, set the $IPFS_PATH
|
|
environment variable:
|
|
|
|
export IPFS_PATH=/path/to/ipfsrepo
|
|
`,
|
|
},
|
|
Arguments: []cmds.Argument{},
|
|
Options: []cmds.Option{
|
|
cmds.StringOption(oldKeyOptionName, "o", "Keystore name for the old/rotated-out key."),
|
|
cmds.StringOption(algorithmOptionName, "a", "Cryptographic algorithm to use for key generation.").WithDefault(algorithmDefault),
|
|
cmds.IntOption(bitsOptionName, "b", "Number of bits to use in the generated RSA private key."),
|
|
},
|
|
NoRemote: true,
|
|
PreRun: func(req *cmds.Request, env cmds.Environment) error {
|
|
cctx := env.(*oldcmds.Context)
|
|
daemonLocked, err := fsrepo.LockedByOtherProcess(cctx.ConfigRoot)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info("checking if daemon is running...")
|
|
if daemonLocked {
|
|
log.Debug("ipfs daemon is running")
|
|
e := "ipfs daemon is running. please stop it to run this command"
|
|
return cmds.ClientError(e)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
cctx := env.(*oldcmds.Context)
|
|
nBitsForKeypair, nBitsGiven := req.Options[bitsOptionName].(int)
|
|
algorithm, _ := req.Options[algorithmOptionName].(string)
|
|
oldKey, ok := req.Options[oldKeyOptionName].(string)
|
|
if !ok {
|
|
return fmt.Errorf("keystore name for backing up old key must be provided")
|
|
}
|
|
return doRotate(os.Stdout, cctx.ConfigRoot, oldKey, algorithm, nBitsForKeypair, nBitsGiven)
|
|
},
|
|
}
|
|
|
|
func doRotate(out io.Writer, repoRoot string, oldKey string, algorithm string, nBitsForKeypair int, nBitsGiven bool) error {
|
|
// Open repo
|
|
repo, err := fsrepo.Open(repoRoot)
|
|
if err != nil {
|
|
return fmt.Errorf("opening repo (%v)", err)
|
|
}
|
|
defer repo.Close()
|
|
|
|
// Read config file from repo
|
|
cfg, err := repo.Config()
|
|
if err != nil {
|
|
return fmt.Errorf("reading config from repo (%v)", err)
|
|
}
|
|
|
|
// Generate new identity
|
|
var identity config.Identity
|
|
if nBitsGiven {
|
|
identity, err = config.CreateIdentity(out, []options.KeyGenerateOption{
|
|
options.Key.Size(nBitsForKeypair),
|
|
options.Key.Type(algorithm),
|
|
})
|
|
} else {
|
|
identity, err = config.CreateIdentity(out, []options.KeyGenerateOption{
|
|
options.Key.Type(algorithm),
|
|
})
|
|
}
|
|
if err != nil {
|
|
return fmt.Errorf("creating identity (%v)", err)
|
|
}
|
|
|
|
// Save old identity to keystore
|
|
oldPrivKey, err := cfg.Identity.DecodePrivateKey("")
|
|
if err != nil {
|
|
return fmt.Errorf("decoding old private key (%v)", err)
|
|
}
|
|
keystore := repo.Keystore()
|
|
if err := keystore.Put(oldKey, oldPrivKey); err != nil {
|
|
return fmt.Errorf("saving old key in keystore (%v)", err)
|
|
}
|
|
|
|
// Update identity
|
|
cfg.Identity = identity
|
|
|
|
// Write config file to repo
|
|
if err = repo.SetConfig(cfg); err != nil {
|
|
return fmt.Errorf("saving new key to config (%v)", err)
|
|
}
|
|
return nil
|
|
}
|