Address comments from review.
This commit is contained in:
parent
0b580d0521
commit
cc232e6f79
|
@ -14,17 +14,8 @@ func (c *Sys) InitStatus() (bool, error) {
|
|||
}
|
||||
|
||||
func (c *Sys) Init(opts *InitRequest) (*InitResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"secret_shares": opts.SecretShares,
|
||||
"secret_threshold": opts.SecretThreshold,
|
||||
}
|
||||
|
||||
if len(opts.SecretPGPKeys) != 0 {
|
||||
body["secret_pgp_keys"] = opts.SecretPGPKeys
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/init")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -40,9 +31,9 @@ func (c *Sys) Init(opts *InitRequest) (*InitResponse, error) {
|
|||
}
|
||||
|
||||
type InitRequest struct {
|
||||
SecretShares int
|
||||
SecretThreshold int
|
||||
SecretPGPKeys []string
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
}
|
||||
|
||||
type InitStatusResponse struct {
|
||||
|
|
|
@ -57,7 +57,7 @@ func (c *Sys) RekeyUpdate(shard string) (*RekeyUpdateResponse, error) {
|
|||
type RekeyInitRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
SecretPGPKeys []string `json:"secret_pgp_keys"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
}
|
||||
|
||||
type RekeyStatusResponse struct {
|
||||
|
|
|
@ -18,7 +18,7 @@ func (c *InitCommand) Run(args []string) int {
|
|||
var pgpKeys pgpkeys.PubKeyFilesFlag
|
||||
flags := c.Meta.FlagSet("init", FlagSetDefault)
|
||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
flags.IntVar(&shares, "key-shares", 0, "")
|
||||
flags.IntVar(&shares, "key-shares", 5, "")
|
||||
flags.IntVar(&threshold, "key-threshold", 3, "")
|
||||
flags.Var(&pgpKeys, "pgp-keys", "")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
|
@ -32,18 +32,10 @@ func (c *InitCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
if shares == 0 {
|
||||
if pgpKeys == nil {
|
||||
shares = 5
|
||||
} else {
|
||||
shares = len(pgpKeys)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.Sys().Init(&api.InitRequest{
|
||||
SecretShares: shares,
|
||||
SecretThreshold: threshold,
|
||||
SecretPGPKeys: pgpKeys,
|
||||
PGPKeys: pgpKeys,
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
|
@ -104,8 +96,7 @@ Init Options:
|
|||
|
||||
-pgp-keys If provided, must be a comma-separated list of
|
||||
files on disk containing binary-format public PGP
|
||||
keys. The number of files must match 'key-shares',
|
||||
or you can omit 'key-shares' if using this option.
|
||||
keys. The number of files must match 'key-shares'.
|
||||
The output unseal keys will be hex-encoded and
|
||||
encrypted, in order, with the given public keys.
|
||||
If you want to use them with the 'vault unseal'
|
||||
|
|
|
@ -147,6 +147,7 @@ func TestInit_PGP(t *testing.T) {
|
|||
|
||||
args = []string{
|
||||
"-address", addr,
|
||||
"-key-shares", "3",
|
||||
"-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2],
|
||||
"-key-threshold", "2",
|
||||
}
|
||||
|
@ -177,7 +178,7 @@ func TestInit_PGP(t *testing.T) {
|
|||
if !reflect.DeepEqual(expected, sealConf) {
|
||||
t.Fatalf("bad:\nexpected: %#v\ngot: %#v", expected, sealConf)
|
||||
}
|
||||
|
||||
|
||||
re, err := regexp.Compile("\\s+Initial Root Token:\\s+(.*)")
|
||||
if err != nil {
|
||||
t.Fatalf("Error compiling regex: %s", err)
|
||||
|
|
|
@ -27,7 +27,7 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||
flags.BoolVar(&init, "init", false, "")
|
||||
flags.BoolVar(&cancel, "cancel", false, "")
|
||||
flags.BoolVar(&status, "status", false, "")
|
||||
flags.IntVar(&shares, "key-shares", 0, "")
|
||||
flags.IntVar(&shares, "key-shares", 5, "")
|
||||
flags.IntVar(&threshold, "key-threshold", 3, "")
|
||||
flags.Var(&pgpKeys, "pgp-keys", "")
|
||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
|
@ -42,14 +42,6 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||
return 2
|
||||
}
|
||||
|
||||
if shares == 0 {
|
||||
if pgpKeys == nil {
|
||||
shares = 5
|
||||
} else {
|
||||
shares = len(pgpKeys)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we are running doing any restricted variants
|
||||
if init {
|
||||
return c.initRekey(client, shares, threshold, pgpKeys)
|
||||
|
@ -71,7 +63,7 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||
err := client.Sys().RekeyInit(&api.RekeyInitRequest{
|
||||
SecretShares: shares,
|
||||
SecretThreshold: threshold,
|
||||
SecretPGPKeys: pgpKeys,
|
||||
PGPKeys: pgpKeys,
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing rekey: %s", err))
|
||||
|
@ -153,7 +145,7 @@ func (c *RekeyCommand) initRekey(client *api.Client, shares, threshold int, pgpK
|
|||
err := client.Sys().RekeyInit(&api.RekeyInitRequest{
|
||||
SecretShares: shares,
|
||||
SecretThreshold: threshold,
|
||||
SecretPGPKeys: pgpKeys,
|
||||
PGPKeys: pgpKeys,
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing rekey: %s", err))
|
||||
|
@ -241,8 +233,7 @@ Unseal Options:
|
|||
|
||||
-pgp-keys If provided, must be a comma-separated list of
|
||||
files on disk containing binary-format public PGP
|
||||
keys. The number of files must match 'key-shares',
|
||||
or you can omit 'key-shares' if using this option.
|
||||
keys. The number of files must match 'key-shares'.
|
||||
The output unseal keys will be hex-encoded and
|
||||
encrypted, in order, with the given public keys.
|
||||
If you want to use them with the 'vault unseal'
|
||||
|
|
|
@ -176,8 +176,9 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||
args := []string{
|
||||
"-address", addr,
|
||||
"-init",
|
||||
"-key-shares", "3",
|
||||
"-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2],
|
||||
"-key-threshold=2",
|
||||
"-key-threshold", "2",
|
||||
}
|
||||
|
||||
if code := c.Run(args); code != 0 {
|
||||
|
|
|
@ -15,30 +15,31 @@ import (
|
|||
//
|
||||
// Note: There is no corresponding test function; this functionality is
|
||||
// thoroughly tested in the init and rekey command unit tests
|
||||
func EncryptShares(secretShares *[][]byte, pgpKeys *[]string) error {
|
||||
if len(*secretShares) != len(*pgpKeys) {
|
||||
return fmt.Errorf("Mismatch between number of generated shares and number of PGP keys")
|
||||
func EncryptShares(secretShares [][]byte, pgpKeys []string) ([][]byte, error) {
|
||||
if len(secretShares) != len(pgpKeys) {
|
||||
return nil, fmt.Errorf("Mismatch between number of generated shares and number of PGP keys")
|
||||
}
|
||||
for i, keystring := range *pgpKeys {
|
||||
encryptedShares := [][]byte{}
|
||||
for i, keystring := range pgpKeys {
|
||||
data, err := base64.StdEncoding.DecodeString(keystring)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error decoding given PGP key: %s", err)
|
||||
return nil, fmt.Errorf("Error decoding given PGP key: %s", err)
|
||||
}
|
||||
entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error parsing given PGP key: %s", err)
|
||||
return nil, fmt.Errorf("Error parsing given PGP key: %s", err)
|
||||
}
|
||||
ctBuf := bytes.NewBuffer(nil)
|
||||
pt, err := openpgp.Encrypt(ctBuf, []*openpgp.Entity{entity}, nil, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting up encryption for PGP message: %s", err)
|
||||
return nil, fmt.Errorf("Error setting up encryption for PGP message: %s", err)
|
||||
}
|
||||
_, err = pt.Write((*secretShares)[i])
|
||||
_, err = pt.Write(secretShares[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error encrypting PGP message: %s", err)
|
||||
return nil, fmt.Errorf("Error encrypting PGP message: %s", err)
|
||||
}
|
||||
pt.Close()
|
||||
(*secretShares)[i] = ctBuf.Bytes()
|
||||
encryptedShares = append(encryptedShares, ctBuf.Bytes())
|
||||
}
|
||||
return nil
|
||||
return encryptedShares, nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package http
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/vault/vault"
|
||||
|
@ -41,19 +40,11 @@ func handleSysInitPut(core *vault.Core, w http.ResponseWriter, r *http.Request)
|
|||
return
|
||||
}
|
||||
|
||||
switch {
|
||||
case req.SecretShares > 0 && len(req.SecretPGPKeys) > 0 && len(req.SecretPGPKeys) != req.SecretShares:
|
||||
respondError(w, http.StatusBadRequest, fmt.Errorf("Mismatch between key-shares and length of pgp-keys (you can specify pgp-keys alone)"))
|
||||
return
|
||||
case req.SecretShares == 0 && len(req.SecretPGPKeys) > 0:
|
||||
req.SecretShares = len(req.SecretPGPKeys)
|
||||
}
|
||||
|
||||
// Initialize
|
||||
result, err := core.Initialize(&vault.SealConfig{
|
||||
SecretShares: req.SecretShares,
|
||||
SecretThreshold: req.SecretThreshold,
|
||||
SecretPGPKeys: req.SecretPGPKeys,
|
||||
PGPKeys: req.PGPKeys,
|
||||
})
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
|
@ -75,7 +66,7 @@ func handleSysInitPut(core *vault.Core, w http.ResponseWriter, r *http.Request)
|
|||
type InitRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
SecretPGPKeys []string `json:"secret_pgp_keys"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
}
|
||||
|
||||
type InitResponse struct {
|
||||
|
|
|
@ -79,7 +79,7 @@ func handleSysRekeyInitPut(core *vault.Core, w http.ResponseWriter, r *http.Requ
|
|||
err := core.RekeyInit(&vault.SealConfig{
|
||||
SecretShares: req.SecretShares,
|
||||
SecretThreshold: req.SecretThreshold,
|
||||
SecretPGPKeys: req.SecretPGPKeys,
|
||||
PGPKeys: req.PGPKeys,
|
||||
})
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
|
@ -152,7 +152,7 @@ func handleSysRekeyUpdate(core *vault.Core) http.Handler {
|
|||
type RekeyRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
SecretPGPKeys []string `json:"secret_pgp_keys"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
}
|
||||
|
||||
type RekeyStatusResponse struct {
|
||||
|
|
|
@ -86,11 +86,11 @@ type SealConfig struct {
|
|||
// split into. This is the N value of Shamir.
|
||||
SecretShares int `json:"secret_shares"`
|
||||
|
||||
// SecretPGPKeys is the array of public PGP keys used,
|
||||
// PGPKeys is the array of public PGP keys used,
|
||||
// if requested, to encrypt the output unseal tokens. If
|
||||
// provided, it sets the value of SecretShares. Ordering
|
||||
// is important.
|
||||
SecretPGPKeys []string `json:"-"`
|
||||
PGPKeys []string `json:"-"`
|
||||
|
||||
// SecretThreshold is the number of parts required
|
||||
// to open the vault. This is the T value of Shamir
|
||||
|
@ -117,11 +117,11 @@ func (s *SealConfig) Validate() error {
|
|||
if s.SecretThreshold > s.SecretShares {
|
||||
return fmt.Errorf("secret threshold cannot be larger than secret shares")
|
||||
}
|
||||
if len(s.SecretPGPKeys) > 0 && len(s.SecretPGPKeys) != s.SecretShares {
|
||||
if len(s.PGPKeys) > 0 && len(s.PGPKeys) != s.SecretShares {
|
||||
return fmt.Errorf("count mismatch between number of provided PGP keys and number of shares")
|
||||
}
|
||||
if len(s.SecretPGPKeys) > 0 {
|
||||
for _, keystring := range s.SecretPGPKeys {
|
||||
if len(s.PGPKeys) > 0 {
|
||||
for _, keystring := range s.PGPKeys {
|
||||
data, err := base64.StdEncoding.DecodeString(keystring)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error decoding given PGP key: %s", err)
|
||||
|
@ -739,10 +739,12 @@ func (c *Core) Initialize(config *SealConfig) (*InitResult, error) {
|
|||
results.SecretShares = shares
|
||||
}
|
||||
|
||||
if len(config.SecretPGPKeys) > 0 {
|
||||
if err := pgpkeys.EncryptShares(&results.SecretShares, &config.SecretPGPKeys); err != nil {
|
||||
if len(config.PGPKeys) > 0 {
|
||||
encryptedShares, err := pgpkeys.EncryptShares(results.SecretShares, config.PGPKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results.SecretShares = encryptedShares
|
||||
}
|
||||
|
||||
// Initialize the barrier
|
||||
|
@ -1217,10 +1219,12 @@ func (c *Core) RekeyUpdate(key []byte) (*RekeyResult, error) {
|
|||
results.SecretShares = shares
|
||||
}
|
||||
|
||||
if len(c.rekeyConfig.SecretPGPKeys) > 0 {
|
||||
if err := pgpkeys.EncryptShares(&results.SecretShares, &c.rekeyConfig.SecretPGPKeys); err != nil {
|
||||
if len(c.rekeyConfig.PGPKeys) > 0 {
|
||||
encryptedShares, err := pgpkeys.EncryptShares(results.SecretShares, c.rekeyConfig.PGPKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results.SecretShares = encryptedShares
|
||||
}
|
||||
|
||||
// Encode the seal configuration
|
||||
|
|
|
@ -61,7 +61,7 @@ description: |-
|
|||
This must be less than or equal to <code>secret_shares</code>.
|
||||
</li>
|
||||
<li>
|
||||
<spam class="param">secret_pgp_keys</span>
|
||||
<spam class="param">pgp_keys</span>
|
||||
<span class="param-flags">optional</spam>
|
||||
An array of PGP public keys used to encrypt the output unseal keys.
|
||||
Ordering is preserved. The keys must be base64-encoded from their
|
||||
|
|
|
@ -78,7 +78,7 @@ description: |-
|
|||
This must be less than or equal to <code>secret_shares</code>.
|
||||
</li>
|
||||
<li>
|
||||
<spam class="param">secret_pgp_keys</span>
|
||||
<spam class="param">pgp_keys</span>
|
||||
<span class="param-flags">optional</spam>
|
||||
An array of PGP public keys used to encrypt the output unseal keys.
|
||||
Ordering is preserved. The keys must be base64-encoded from their
|
||||
|
|
Loading…
Reference in New Issue