diff --git a/cmd/kops/create_secret_publickey.go b/cmd/kops/create_secret_sshpublickey.go similarity index 90% rename from cmd/kops/create_secret_publickey.go rename to cmd/kops/create_secret_sshpublickey.go index 35624cdff2..5c9fd67a2f 100644 --- a/cmd/kops/create_secret_publickey.go +++ b/cmd/kops/create_secret_sshpublickey.go @@ -15,7 +15,7 @@ type CreateSecretPublickeyCommand struct { var createSecretPublickeyCommand = CreateSecretPublickeyCommand{ cobraCommand: &cobra.Command{ - Use: "publickey", + Use: "sshpublickey", Short: "Create SSH publickey", Long: `Create SSH publickey.`, }, @@ -38,10 +38,10 @@ func init() { func (cmd *CreateSecretPublickeyCommand) Run(args []string) error { if len(args) == 0 { - return fmt.Errorf("syntax: NAME -i ") + return fmt.Errorf("syntax: NAME -i ") } if len(args) != 1 { - return fmt.Errorf("syntax: NAME -i ") + return fmt.Errorf("syntax: NAME -i ") } name := args[0] diff --git a/cmd/kops/delete_secret.go b/cmd/kops/delete_secret.go index 06bc5cea25..047b389bdb 100644 --- a/cmd/kops/delete_secret.go +++ b/cmd/kops/delete_secret.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "k8s.io/kops/upup/pkg/fi" ) type DeleteSecretCmd struct { @@ -28,24 +29,40 @@ func init() { } func (c *DeleteSecretCmd) Run(args []string) error { - if len(args) != 2 { - return fmt.Errorf("Syntax: ") + if len(args) != 2 && len(args) != 3 { + return fmt.Errorf("Syntax: []") } secretType := args[0] secretName := args[1] + secretID := "" + if len(args) == 3 { + secretID = args[2] + } + secrets, err := listSecrets(secretType, []string{secretName}) if err != nil { return err } + if secretID != "" { + var matches []*fi.KeystoreItem + for _, s := range secrets { + if s.Id == secretID { + matches = append(matches, s) + } + } + secrets = matches + } + if len(secrets) == 0 { return fmt.Errorf("secret %q not found") } if len(secrets) != 1 { - return fmt.Errorf("found multiple matching secrets") + // TODO: it would be friendly to print the matching keys + return fmt.Errorf("found multiple matching secrets; specify the id of the key") } keyStore, err := rootCommand.KeyStore() diff --git a/docs/secrets.md b/docs/secrets.md new file mode 100644 index 0000000000..0049679e33 --- /dev/null +++ b/docs/secrets.md @@ -0,0 +1,26 @@ +## Managing secrets + +### get secrets + +### get secret -oplaintext + +-oplaintext exposes the raw secret value. + +### describe secret + +`kops describe secret` + +### create secret + +`kops create secret publickey admin -i ~/.ssh/id_rsa.pub` + +### delete secret + +Syntax: `kops delete secret ` +or `kops delete secret ` + +The ID form can be used when there are multiple matching keys. + +example: +`kops delete secret sshpublickey admin` + diff --git a/upup/pkg/fi/vfs_castore.go b/upup/pkg/fi/vfs_castore.go index 7f2edef772..9f9dd6fb4a 100644 --- a/upup/pkg/fi/vfs_castore.go +++ b/upup/pkg/fi/vfs_castore.go @@ -370,7 +370,7 @@ func (c *VFSCAStore) List() ([]*KeystoreItem, error) { item := &KeystoreItem{ Name: tokens[0], - Id: tokens[1], + Id: insertFingerprintColons(tokens[1]), Type: SecretTypeSSHPublicKey, } items = append(items, item) @@ -621,6 +621,39 @@ func buildSerial(timestamp int64) *big.Int { return serial } +func formatFingerprint(data []byte) string { + var buf bytes.Buffer + + for i, b := range data { + s := fmt.Sprintf("%0.2x", b) + if i != 0 { + buf.WriteString(":") + } + buf.WriteString(s) + } + return buf.String() +} + +func insertFingerprintColons(id string) string { + var buf bytes.Buffer + + for { + if id == "" { + break + } + if buf.Len() != 0 { + buf.WriteString(":") + } + if len(id) < 2 { + buf.WriteString(id) + } else { + buf.WriteString(id[0:2]) + id = id[2:] + } + } + return buf.String() +} + // AddSSHPublicKey stores an SSH public key func (c *VFSCAStore) AddSSHPublicKey(name string, pubkey []byte) error { var id string @@ -636,7 +669,7 @@ func (c *VFSCAStore) AddSSHPublicKey(name string, pubkey []byte) error { if err != nil { return err } - id = fmt.Sprintf("%x", h.Sum(nil)) + id = formatFingerprint(h.Sum(nil)) } p := c.buildSSHPublicKeyPath(name, id) @@ -644,6 +677,8 @@ func (c *VFSCAStore) AddSSHPublicKey(name string, pubkey []byte) error { } func (c *VFSCAStore) buildSSHPublicKeyPath(name string, id string) vfs.Path { + // id is fingerprint with colons, but we store without colons + id = strings.Replace(id, ":", "", -1) return c.basedir.Join("ssh", "public", name, id) } @@ -659,8 +694,11 @@ func (c *VFSCAStore) FindSSHPublicKeys(name string) ([]*KeystoreItem, error) { return nil, err } for _, item := range items { + // Fill in the missing fields item.Type = SecretTypeSSHPublicKey item.Name = name + + item.Id = insertFingerprintColons(item.Id) } return items, nil }