Address comments from review.

This commit is contained in:
Jeff Mitchell 2015-08-25 15:33:58 -07:00
parent 0b580d0521
commit cc232e6f79
12 changed files with 47 additions and 76 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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'

View File

@ -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)

View File

@ -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'

View File

@ -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 {

View File

@ -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
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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