mirror of https://github.com/docker/docs.git
Added root key creation if non-existing to notary
Signed-off-by: Diogo Monica <diogo@docker.com>
This commit is contained in:
parent
682e7ea00b
commit
06a28c89ee
|
@ -618,7 +618,7 @@ func (r *NotaryRepository) ListRootKeys() []string {
|
||||||
func (r *NotaryRepository) GenRootKey(passphrase string) (string, error) {
|
func (r *NotaryRepository) GenRootKey(passphrase string) (string, error) {
|
||||||
privKey, err := trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize)
|
privKey, err := trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to convert private key: ", err)
|
return "", fmt.Errorf("failed to convert private key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase)
|
r.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase)
|
||||||
|
|
|
@ -2,14 +2,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
notaryclient "github.com/docker/notary/client"
|
notaryclient "github.com/docker/notary/client"
|
||||||
"github.com/endophage/gotuf/data"
|
|
||||||
"github.com/endophage/gotuf/keys"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -107,13 +106,30 @@ func tufInit(cmd *cobra.Command, args []string) {
|
||||||
fatalf(err.Error())
|
fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(diogo): We don't want to generate a new root every time. Ask the user
|
keysList := nRepo.ListRootKeys()
|
||||||
// which key she wants to use if there > 0 root keys available.
|
var passphrase string
|
||||||
rootKeyID, err := nRepo.GenRootKey("passphrase")
|
var rootKeyID string
|
||||||
|
if len(keysList) < 1 {
|
||||||
|
fmt.Println("No root keys found. Generating a new root key...")
|
||||||
|
passphrase, err = passphraseRetriever()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf(err.Error())
|
fatalf(err.Error())
|
||||||
}
|
}
|
||||||
rootSigner, err := nRepo.GetRootSigner(rootKeyID, "passphrase")
|
rootKeyID, err = nRepo.GenRootKey(passphrase)
|
||||||
|
if err != nil {
|
||||||
|
fatalf(err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rootKeyID = keysList[0]
|
||||||
|
fmt.Println("Root key found.")
|
||||||
|
fmt.Printf("Enter passphrase for: %s (%d)\n", rootKeyID, len(rootKeyID))
|
||||||
|
passphrase, err = passphraseRetriever()
|
||||||
|
if err != nil {
|
||||||
|
fatalf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootSigner, err := nRepo.GetRootSigner(rootKeyID, passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf(err.Error())
|
fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -185,7 +201,7 @@ func tufPublish(cmd *cobra.Command, args []string) {
|
||||||
fatalf(err.Error())
|
fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.Publish(passwordRetriever)
|
err = repo.Publish(passphraseRetriever)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf(err.Error())
|
fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -249,76 +265,16 @@ func verify(cmd *cobra.Command, args []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//func generateKeys(kdb *keys.KeyDB, signer *signed.Signer, remote store.RemoteStore) (string, string, string, string, error) {
|
func passphraseRetriever() (string, error) {
|
||||||
// rawTSKey, err := remote.GetKey("timestamp")
|
fmt.Println("Please provide a passphrase for this root key: ")
|
||||||
// if err != nil {
|
var passphrase string
|
||||||
// return "", "", "", "", err
|
_, err := fmt.Scanln(&passphrase)
|
||||||
// }
|
|
||||||
// fmt.Println("RawKey: ", string(rawTSKey))
|
|
||||||
// parsedKey := &data.TUFKey{}
|
|
||||||
// err = json.Unmarshal(rawTSKey, parsedKey)
|
|
||||||
// if err != nil {
|
|
||||||
// return "", "", "", "", err
|
|
||||||
// }
|
|
||||||
// timestampKey := data.NewPublicKey(parsedKey.Cipher(), parsedKey.Public())
|
|
||||||
//
|
|
||||||
// rootKey, err := signer.Create("root")
|
|
||||||
// if err != nil {
|
|
||||||
// return "", "", "", "", err
|
|
||||||
// }
|
|
||||||
// targetsKey, err := signer.Create("targets")
|
|
||||||
// if err != nil {
|
|
||||||
// return "", "", "", "", err
|
|
||||||
// }
|
|
||||||
// snapshotKey, err := signer.Create("snapshot")
|
|
||||||
// if err != nil {
|
|
||||||
// return "", "", "", "", err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// kdb.AddKey(rootKey)
|
|
||||||
// kdb.AddKey(targetsKey)
|
|
||||||
// kdb.AddKey(snapshotKey)
|
|
||||||
// kdb.AddKey(timestampKey)
|
|
||||||
// return rootKey.ID(), targetsKey.ID(), snapshotKey.ID(), timestampKey.ID(), nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
func generateRoles(kdb *keys.KeyDB, rootKeyID, targetsKeyID, snapshotKeyID, timestampKeyID string) error {
|
|
||||||
rootRole, err := data.NewRole("root", 1, []string{rootKeyID}, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
targetsRole, err := data.NewRole("targets", 1, []string{targetsKeyID}, nil, nil)
|
if len(passphrase) < 8 {
|
||||||
if err != nil {
|
fmt.Println("Please use a password manager to generate and store a good random passphrase.")
|
||||||
return err
|
return "", errors.New("Passphrase too short")
|
||||||
}
|
}
|
||||||
snapshotRole, err := data.NewRole("snapshot", 1, []string{snapshotKeyID}, nil, nil)
|
return passphrase, nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
timestampRole, err := data.NewRole("timestamp", 1, []string{timestampKeyID}, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = kdb.AddRole(rootRole)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = kdb.AddRole(targetsRole)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = kdb.AddRole(snapshotRole)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = kdb.AddRole(timestampRole)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func passwordRetriever() (string, error) {
|
|
||||||
return "passphrase", nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
[1mdiff --git a/client/client.go b/client/client.go[m
|
||||||
|
[1mindex 6916daf..8029996 100644[m
|
||||||
|
[1m--- a/client/client.go[m
|
||||||
|
[1m+++ b/client/client.go[m
|
||||||
|
[36m@@ -618,7 +618,7 @@[m [mfunc (r *NotaryRepository) ListRootKeys() []string {[m
|
||||||
|
func (r *NotaryRepository) GenRootKey(passphrase string) (string, error) {[m
|
||||||
|
privKey, err := trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize)[m
|
||||||
|
if err != nil {[m
|
||||||
|
[31m- return "", fmt.Errorf("failed to convert private key: ", err)[m
|
||||||
|
[32m+[m [32mreturn "", fmt.Errorf("failed to convert private key: %v", err)[m
|
||||||
|
}[m
|
||||||
|
[m
|
||||||
|
r.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase)[m
|
||||||
|
[1mdiff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go[m
|
||||||
|
[1mindex af21933..7825170 100644[m
|
||||||
|
[1m--- a/cmd/notary/tuf.go[m
|
||||||
|
[1m+++ b/cmd/notary/tuf.go[m
|
||||||
|
[36m@@ -2,14 +2,13 @@[m [mpackage main[m
|
||||||
|
[m
|
||||||
|
import ([m
|
||||||
|
"crypto/sha256"[m
|
||||||
|
[32m+[m [32m"errors"[m
|
||||||
|
"fmt"[m
|
||||||
|
"io/ioutil"[m
|
||||||
|
"os"[m
|
||||||
|
[m
|
||||||
|
"github.com/Sirupsen/logrus"[m
|
||||||
|
notaryclient "github.com/docker/notary/client"[m
|
||||||
|
[31m- "github.com/endophage/gotuf/data"[m
|
||||||
|
[31m- "github.com/endophage/gotuf/keys"[m
|
||||||
|
"github.com/spf13/cobra"[m
|
||||||
|
"github.com/spf13/viper"[m
|
||||||
|
)[m
|
||||||
|
[36m@@ -107,13 +106,30 @@[m [mfunc tufInit(cmd *cobra.Command, args []string) {[m
|
||||||
|
fatalf(err.Error())[m
|
||||||
|
}[m
|
||||||
|
[m
|
||||||
|
[31m- // TODO(diogo): We don't want to generate a new root every time. Ask the user[m
|
||||||
|
[31m- // which key she wants to use if there > 0 root keys available.[m
|
||||||
|
[31m- rootKeyID, err := nRepo.GenRootKey("passphrase")[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- fatalf(err.Error())[m
|
||||||
|
[32m+[m [32mkeysList := nRepo.ListRootKeys()[m
|
||||||
|
[32m+[m [32mvar passphrase string[m
|
||||||
|
[32m+[m [32mvar rootKeyID string[m
|
||||||
|
[32m+[m [32mif len(keysList) < 1 {[m
|
||||||
|
[32m+[m [32mfmt.Println("No root keys found. Generating a new root key...")[m
|
||||||
|
[32m+[m [32mpassphrase, err = passphraseRetriever()[m
|
||||||
|
[32m+[m [32mif err != nil {[m
|
||||||
|
[32m+[m [32mfatalf(err.Error())[m
|
||||||
|
[32m+[m [32m}[m
|
||||||
|
[32m+[m [32mrootKeyID, err = nRepo.GenRootKey(passphrase)[m
|
||||||
|
[32m+[m [32mif err != nil {[m
|
||||||
|
[32m+[m [32mfatalf(err.Error())[m
|
||||||
|
[32m+[m [32m}[m
|
||||||
|
[32m+[m [32m} else {[m
|
||||||
|
[32m+[m [32mrootKeyID = keysList[0][m
|
||||||
|
[32m+[m [32mfmt.Println("Root key found.")[m
|
||||||
|
[32m+[m [32mfmt.Printf("Enter passphrase for: %s (%d)\n", rootKeyID, len(rootKeyID))[m
|
||||||
|
[32m+[m [32mpassphrase, err = passphraseRetriever()[m
|
||||||
|
[32m+[m [32mif err != nil {[m
|
||||||
|
[32m+[m [32mfatalf(err.Error())[m
|
||||||
|
[32m+[m [32m}[m
|
||||||
|
}[m
|
||||||
|
[31m- rootSigner, err := nRepo.GetRootSigner(rootKeyID, "passphrase")[m
|
||||||
|
[32m+[m
|
||||||
|
[32m+[m [32mrootSigner, err := nRepo.GetRootSigner(rootKeyID, passphrase)[m
|
||||||
|
if err != nil {[m
|
||||||
|
fatalf(err.Error())[m
|
||||||
|
}[m
|
||||||
|
[36m@@ -185,7 +201,7 @@[m [mfunc tufPublish(cmd *cobra.Command, args []string) {[m
|
||||||
|
fatalf(err.Error())[m
|
||||||
|
}[m
|
||||||
|
[m
|
||||||
|
[31m- err = repo.Publish(passwordRetriever)[m
|
||||||
|
[32m+[m [32merr = repo.Publish(passphraseRetriever)[m
|
||||||
|
if err != nil {[m
|
||||||
|
fatalf(err.Error())[m
|
||||||
|
}[m
|
||||||
|
[36m@@ -249,76 +265,20 @@[m [mfunc verify(cmd *cobra.Command, args []string) {[m
|
||||||
|
return[m
|
||||||
|
}[m
|
||||||
|
[m
|
||||||
|
[31m-//func generateKeys(kdb *keys.KeyDB, signer *signed.Signer, remote store.RemoteStore) (string, string, string, string, error) {[m
|
||||||
|
[31m-// rawTSKey, err := remote.GetKey("timestamp")[m
|
||||||
|
[31m-// if err != nil {[m
|
||||||
|
[31m-// return "", "", "", "", err[m
|
||||||
|
[31m-// }[m
|
||||||
|
[31m-// fmt.Println("RawKey: ", string(rawTSKey))[m
|
||||||
|
[31m-// parsedKey := &data.TUFKey{}[m
|
||||||
|
[31m-// err = json.Unmarshal(rawTSKey, parsedKey)[m
|
||||||
|
[31m-// if err != nil {[m
|
||||||
|
[31m-// return "", "", "", "", err[m
|
||||||
|
[31m-// }[m
|
||||||
|
[31m-// timestampKey := data.NewPublicKey(parsedKey.Cipher(), parsedKey.Public())[m
|
||||||
|
[31m-//[m
|
||||||
|
[31m-// rootKey, err := signer.Create("root")[m
|
||||||
|
[31m-// if err != nil {[m
|
||||||
|
[31m-// return "", "", "", "", err[m
|
||||||
|
[31m-// }[m
|
||||||
|
[31m-// targetsKey, err := signer.Create("targets")[m
|
||||||
|
[31m-// if err != nil {[m
|
||||||
|
[31m-// return "", "", "", "", err[m
|
||||||
|
[31m-// }[m
|
||||||
|
[31m-// snapshotKey, err := signer.Create("snapshot")[m
|
||||||
|
[31m-// if err != nil {[m
|
||||||
|
[31m-// return "", "", "", "", err[m
|
||||||
|
[31m-// }[m
|
||||||
|
[31m-//[m
|
||||||
|
[31m-// kdb.AddKey(rootKey)[m
|
||||||
|
[31m-// kdb.AddKey(targetsKey)[m
|
||||||
|
[31m-// kdb.AddKey(snapshotKey)[m
|
||||||
|
[31m-// kdb.AddKey(timestampKey)[m
|
||||||
|
[31m-// return rootKey.ID(), targetsKey.ID(), snapshotKey.ID(), timestampKey.ID(), nil[m
|
||||||
|
[31m-//}[m
|
||||||
|
[31m-[m
|
||||||
|
[31m-func generateRoles(kdb *keys.KeyDB, rootKeyID, targetsKeyID, snapshotKeyID, timestampKeyID string) error {[m
|
||||||
|
[31m- rootRole, err := data.NewRole("root", 1, []string{rootKeyID}, nil, nil)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[31m- targetsRole, err := data.NewRole("targets", 1, []string{targetsKeyID}, nil, nil)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[31m- snapshotRole, err := data.NewRole("snapshot", 1, []string{snapshotKeyID}, nil, nil)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[31m- timestampRole, err := data.NewRole("timestamp", 1, []string{timestampKeyID}, nil, nil)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[32m+[m[32m// func passwordRetriever() (string, error) {[m
|
||||||
|
[32m+[m[32m// return "passphrase", nil[m
|
||||||
|
[32m+[m[32m// }[m
|
||||||
|
[m
|
||||||
|
[31m- err = kdb.AddRole(rootRole)[m
|
||||||
|
[32m+[m[32mfunc passphraseRetriever() (string, error) {[m
|
||||||
|
[32m+[m [32mfmt.Println("Please provide a passphrase for this root key: ")[m
|
||||||
|
[32m+[m [32mvar passphrase string[m
|
||||||
|
[32m+[m [32m_, err := fmt.Scanln(&passphrase)[m
|
||||||
|
if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[32m+[m [32mreturn "", err[m
|
||||||
|
}[m
|
||||||
|
[31m- err = kdb.AddRole(targetsRole)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[31m- err = kdb.AddRole(snapshotRole)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[32m+[m [32mif len(passphrase) < 8 {[m
|
||||||
|
[32m+[m [32mfmt.Println("Please use a password manager to generate and store a good random passphrase.")[m
|
||||||
|
[32m+[m [32mreturn "", errors.New("Passphrase too short")[m
|
||||||
|
}[m
|
||||||
|
[31m- err = kdb.AddRole(timestampRole)[m
|
||||||
|
[31m- if err != nil {[m
|
||||||
|
[31m- return err[m
|
||||||
|
[31m- }[m
|
||||||
|
[31m- return nil[m
|
||||||
|
[31m-}[m
|
||||||
|
[31m-[m
|
||||||
|
[31m-func passwordRetriever() (string, error) {[m
|
||||||
|
[31m- return "passphrase", nil[m
|
||||||
|
[32m+[m [32mreturn passphrase, nil[m
|
||||||
|
}[m
|
||||||
|
[1mdiff --git a/trustmanager/keyfilestore.go b/trustmanager/keyfilestore.go[m
|
||||||
|
[1mindex 6418139..f076c79 100644[m
|
||||||
|
[1m--- a/trustmanager/keyfilestore.go[m
|
||||||
|
[1m+++ b/trustmanager/keyfilestore.go[m
|
||||||
|
[36m@@ -1,6 +1,11 @@[m
|
||||||
|
package trustmanager[m
|
||||||
|
[m
|
||||||
|
[31m-import "github.com/endophage/gotuf/data"[m
|
||||||
|
[32m+[m[32mimport ([m
|
||||||
|
[32m+[m [32m"path/filepath"[m
|
||||||
|
[32m+[m [32m"strings"[m
|
||||||
|
[32m+[m
|
||||||
|
[32m+[m [32m"github.com/endophage/gotuf/data"[m
|
||||||
|
[32m+[m[32m)[m
|
||||||
|
[m
|
||||||
|
const ([m
|
||||||
|
keyExtension = "key"[m
|
||||||
|
[36m@@ -79,5 +84,10 @@[m [mfunc (s *KeyFileStore) GetDecryptedKey(name string, passphrase string) (*data.Pr[m
|
||||||
|
// There might be symlinks associating Certificate IDs to Public Keys, so this[m
|
||||||
|
// method only returns the IDs that aren't symlinks[m
|
||||||
|
func (s *KeyFileStore) ListKeys() []string {[m
|
||||||
|
[31m- return s.ListFiles(false)[m
|
||||||
|
[32m+[m [32mvar keyIDList []string[m
|
||||||
|
[32m+[m [32mfor _, f := range s.ListFiles(false) {[m
|
||||||
|
[32m+[m [32mkeyID := strings.TrimSpace(strings.TrimSuffix(filepath.Base(f), filepath.Ext(f)))[m
|
||||||
|
[32m+[m [32mkeyIDList = append(keyIDList, keyID)[m
|
||||||
|
[32m+[m [32m}[m
|
||||||
|
[32m+[m [32mreturn keyIDList[m
|
||||||
|
}[m
|
|
@ -1,6 +1,11 @@
|
||||||
package trustmanager
|
package trustmanager
|
||||||
|
|
||||||
import "github.com/endophage/gotuf/data"
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/endophage/gotuf/data"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
keyExtension = "key"
|
keyExtension = "key"
|
||||||
|
@ -79,5 +84,10 @@ func (s *KeyFileStore) GetDecryptedKey(name string, passphrase string) (*data.Pr
|
||||||
// There might be symlinks associating Certificate IDs to Public Keys, so this
|
// There might be symlinks associating Certificate IDs to Public Keys, so this
|
||||||
// method only returns the IDs that aren't symlinks
|
// method only returns the IDs that aren't symlinks
|
||||||
func (s *KeyFileStore) ListKeys() []string {
|
func (s *KeyFileStore) ListKeys() []string {
|
||||||
return s.ListFiles(false)
|
var keyIDList []string
|
||||||
|
for _, f := range s.ListFiles(false) {
|
||||||
|
keyID := strings.TrimSpace(strings.TrimSuffix(filepath.Base(f), filepath.Ext(f)))
|
||||||
|
keyIDList = append(keyIDList, keyID)
|
||||||
|
}
|
||||||
|
return keyIDList
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue