mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-28 14:11:10 +01:00
Add API methods for creating a DR Operation Token and make generate root accept strategy types (#3565)
* Add API and Command code for generating a DR Operation Token * Update generate root to accept different token strategies
This commit is contained in:
parent
46be396b13
commit
6fc21d88e2
@ -1,7 +1,15 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
|
func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
|
||||||
r := c.c.NewRequest("GET", "/v1/sys/generate-root/attempt")
|
return c.generateRootStatusCommon("/v1/sys/generate-root/attempt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) GenerateDROperationTokenStatus() (*GenerateRootStatusResponse, error) {
|
||||||
|
return c.generateRootStatusCommon("/v1/sys/generate-dr-operation-token/attempt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) generateRootStatusCommon(path string) (*GenerateRootStatusResponse, error) {
|
||||||
|
r := c.c.NewRequest("GET", path)
|
||||||
resp, err := c.c.RawRequest(r)
|
resp, err := c.c.RawRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -14,12 +22,20 @@ func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||||
|
return c.generateRootInitCommon("/v1/sys/generate-root/attempt", otp, pgpKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) GenerateDROperationTokenInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||||
|
return c.generateRootInitCommon("/v1/sys/generate-dr-operation-token/attempt", otp, pgpKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) generateRootInitCommon(path, otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"otp": otp,
|
"otp": otp,
|
||||||
"pgp_key": pgpKey,
|
"pgp_key": pgpKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/attempt")
|
r := c.c.NewRequest("PUT", path)
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
if err := r.SetJSONBody(body); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -36,7 +52,15 @@ func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Sys) GenerateRootCancel() error {
|
func (c *Sys) GenerateRootCancel() error {
|
||||||
r := c.c.NewRequest("DELETE", "/v1/sys/generate-root/attempt")
|
return c.generateRootCancelCommon("/v1/sys/generate-root/attempt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) GenerateDROperationTokenCancel() error {
|
||||||
|
return c.generateRootCancelCommon("/v1/sys/generate-dr-operation-token/attempt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) generateRootCancelCommon(path string) error {
|
||||||
|
r := c.c.NewRequest("DELETE", path)
|
||||||
resp, err := c.c.RawRequest(r)
|
resp, err := c.c.RawRequest(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@ -45,12 +69,20 @@ func (c *Sys) GenerateRootCancel() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Sys) GenerateRootUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
func (c *Sys) GenerateRootUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||||
|
return c.generateRootUpdateCommon("/v1/sys/generate-root/update", shard, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) GenerateDROperationTokenUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||||
|
return c.generateRootUpdateCommon("/v1/sys/generate-dr-operation-token/update", shard, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) generateRootUpdateCommon(path, shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"key": shard,
|
"key": shard,
|
||||||
"nonce": nonce,
|
"nonce": nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/update")
|
r := c.c.NewRequest("PUT", path)
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
if err := r.SetJSONBody(body); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,11 +29,12 @@ type GenerateRootCommand struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *GenerateRootCommand) Run(args []string) int {
|
func (c *GenerateRootCommand) Run(args []string) int {
|
||||||
var init, cancel, status, genotp bool
|
var init, cancel, status, genotp, drToken bool
|
||||||
var nonce, decode, otp, pgpKey string
|
var nonce, decode, otp, pgpKey string
|
||||||
var pgpKeyArr pgpkeys.PubKeyFilesFlag
|
var pgpKeyArr pgpkeys.PubKeyFilesFlag
|
||||||
flags := c.Meta.FlagSet("generate-root", meta.FlagSetDefault)
|
flags := c.Meta.FlagSet("generate-root", meta.FlagSetDefault)
|
||||||
flags.BoolVar(&init, "init", false, "")
|
flags.BoolVar(&init, "init", false, "")
|
||||||
|
flags.BoolVar(&drToken, "dr-token", false, "")
|
||||||
flags.BoolVar(&cancel, "cancel", false, "")
|
flags.BoolVar(&cancel, "cancel", false, "")
|
||||||
flags.BoolVar(&status, "status", false, "")
|
flags.BoolVar(&status, "status", false, "")
|
||||||
flags.BoolVar(&genotp, "genotp", false, "")
|
flags.BoolVar(&genotp, "genotp", false, "")
|
||||||
@ -77,7 +78,11 @@ func (c *GenerateRootCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the root generation is started
|
// Check if the root generation is started
|
||||||
rootGenerationStatus, err := client.Sys().GenerateRootStatus()
|
f := client.Sys().GenerateRootStatus
|
||||||
|
if drToken {
|
||||||
|
f = client.Sys().GenerateDROperationTokenStatus
|
||||||
|
}
|
||||||
|
rootGenerationStatus, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
|
||||||
return 1
|
return 1
|
||||||
@ -133,16 +138,20 @@ func (c *GenerateRootCommand) Run(args []string) int {
|
|||||||
// Check if we are running doing any restricted variants
|
// Check if we are running doing any restricted variants
|
||||||
switch {
|
switch {
|
||||||
case init:
|
case init:
|
||||||
return c.initGenerateRoot(client, otp, pgpKey)
|
return c.initGenerateRoot(client, otp, pgpKey, drToken)
|
||||||
case cancel:
|
case cancel:
|
||||||
return c.cancelGenerateRoot(client)
|
return c.cancelGenerateRoot(client, drToken)
|
||||||
case status:
|
case status:
|
||||||
return c.rootGenerationStatus(client)
|
return c.rootGenerationStatus(client, drToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the root generation process if not started
|
// Start the root generation process if not started
|
||||||
if !rootGenerationStatus.Started {
|
if !rootGenerationStatus.Started {
|
||||||
rootGenerationStatus, err = client.Sys().GenerateRootInit(otp, pgpKey)
|
f := client.Sys().GenerateRootInit
|
||||||
|
if drToken {
|
||||||
|
f = client.Sys().GenerateDROperationTokenInit
|
||||||
|
}
|
||||||
|
rootGenerationStatus, err = f(otp, pgpKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
|
||||||
return 1
|
return 1
|
||||||
@ -179,14 +188,19 @@ func (c *GenerateRootCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Provide the key, this may potentially complete the update
|
// Provide the key, this may potentially complete the update
|
||||||
statusResp, err := client.Sys().GenerateRootUpdate(strings.TrimSpace(key), c.Nonce)
|
{
|
||||||
if err != nil {
|
f := client.Sys().GenerateRootUpdate
|
||||||
c.Ui.Error(fmt.Sprintf("Error attempting generate-root update: %s", err))
|
if drToken {
|
||||||
return 1
|
f = client.Sys().GenerateDROperationTokenUpdate
|
||||||
|
}
|
||||||
|
statusResp, err := f(strings.TrimSpace(key), c.Nonce)
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error attempting generate-root update: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c.dumpStatus(statusResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.dumpStatus(statusResp)
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,9 +238,14 @@ func (c *GenerateRootCommand) decode(encodedVal, otp string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initGenerateRoot is used to start the generation process
|
// initGenerateRoot is used to start the generation process
|
||||||
func (c *GenerateRootCommand) initGenerateRoot(client *api.Client, otp string, pgpKey string) int {
|
func (c *GenerateRootCommand) initGenerateRoot(client *api.Client, otp string, pgpKey string, drToken bool) int {
|
||||||
// Start the rekey
|
// Start the rekey
|
||||||
status, err := client.Sys().GenerateRootInit(otp, pgpKey)
|
f := client.Sys().GenerateRootInit
|
||||||
|
if drToken {
|
||||||
|
f = client.Sys().GenerateDROperationTokenInit
|
||||||
|
}
|
||||||
|
|
||||||
|
status, err := f(otp, pgpKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
|
||||||
return 1
|
return 1
|
||||||
@ -238,8 +257,12 @@ func (c *GenerateRootCommand) initGenerateRoot(client *api.Client, otp string, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cancelGenerateRoot is used to abort the generation process
|
// cancelGenerateRoot is used to abort the generation process
|
||||||
func (c *GenerateRootCommand) cancelGenerateRoot(client *api.Client) int {
|
func (c *GenerateRootCommand) cancelGenerateRoot(client *api.Client, drToken bool) int {
|
||||||
err := client.Sys().GenerateRootCancel()
|
f := client.Sys().GenerateRootCancel
|
||||||
|
if drToken {
|
||||||
|
f = client.Sys().GenerateDROperationTokenCancel
|
||||||
|
}
|
||||||
|
err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Failed to cancel root generation: %s", err))
|
c.Ui.Error(fmt.Sprintf("Failed to cancel root generation: %s", err))
|
||||||
return 1
|
return 1
|
||||||
@ -249,9 +272,13 @@ func (c *GenerateRootCommand) cancelGenerateRoot(client *api.Client) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rootGenerationStatus is used just to fetch and dump the status
|
// rootGenerationStatus is used just to fetch and dump the status
|
||||||
func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int {
|
func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client, drToken bool) int {
|
||||||
// Check the status
|
// Check the status
|
||||||
status, err := client.Sys().GenerateRootStatus()
|
f := client.Sys().GenerateRootStatus
|
||||||
|
if drToken {
|
||||||
|
f = client.Sys().GenerateDROperationTokenStatus
|
||||||
|
}
|
||||||
|
status, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
|
||||||
return 1
|
return 1
|
||||||
@ -350,6 +377,10 @@ Generate Root Options:
|
|||||||
the unseal key is not being passed in via the command
|
the unseal key is not being passed in via the command
|
||||||
line the nonce parameter is not required, and will
|
line the nonce parameter is not required, and will
|
||||||
instead be displayed with the key prompt.
|
instead be displayed with the key prompt.
|
||||||
|
|
||||||
|
-dr-token Generate a Disaster Recovery operation token. This flag
|
||||||
|
should be set on '-init', '-cancel', and every time a
|
||||||
|
key is provided to specify the type of token to generate.
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,8 +67,8 @@ func Handler(core *vault.Core) http.Handler {
|
|||||||
mux.Handle("/v1/sys/unseal", handleSysUnseal(core))
|
mux.Handle("/v1/sys/unseal", handleSysUnseal(core))
|
||||||
mux.Handle("/v1/sys/leader", handleSysLeader(core))
|
mux.Handle("/v1/sys/leader", handleSysLeader(core))
|
||||||
mux.Handle("/v1/sys/health", handleSysHealth(core))
|
mux.Handle("/v1/sys/health", handleSysHealth(core))
|
||||||
mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleSysGenerateRootAttempt(core)))
|
mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleSysGenerateRootAttempt(core, vault.GenerateStandardRootTokenStrategy)))
|
||||||
mux.Handle("/v1/sys/generate-root/update", handleRequestForwarding(core, handleSysGenerateRootUpdate(core)))
|
mux.Handle("/v1/sys/generate-root/update", handleRequestForwarding(core, handleSysGenerateRootUpdate(core, vault.GenerateStandardRootTokenStrategy)))
|
||||||
mux.Handle("/v1/sys/rekey/init", handleRequestForwarding(core, handleSysRekeyInit(core, false)))
|
mux.Handle("/v1/sys/rekey/init", handleRequestForwarding(core, handleSysRekeyInit(core, false)))
|
||||||
mux.Handle("/v1/sys/rekey/update", handleRequestForwarding(core, handleSysRekeyUpdate(core, false)))
|
mux.Handle("/v1/sys/rekey/update", handleRequestForwarding(core, handleSysRekeyUpdate(core, false)))
|
||||||
mux.Handle("/v1/sys/rekey-recovery-key/init", handleRequestForwarding(core, handleSysRekeyInit(core, true)))
|
mux.Handle("/v1/sys/rekey-recovery-key/init", handleRequestForwarding(core, handleSysRekeyInit(core, true)))
|
||||||
|
|||||||
@ -10,13 +10,13 @@ import (
|
|||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleSysGenerateRootAttempt(core *vault.Core) http.Handler {
|
func handleSysGenerateRootAttempt(core *vault.Core, generateStrategy vault.GenerateRootStrategy) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
handleSysGenerateRootAttemptGet(core, w, r)
|
handleSysGenerateRootAttemptGet(core, w, r)
|
||||||
case "POST", "PUT":
|
case "POST", "PUT":
|
||||||
handleSysGenerateRootAttemptPut(core, w, r)
|
handleSysGenerateRootAttemptPut(core, w, r, generateStrategy)
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
handleSysGenerateRootAttemptDelete(core, w, r)
|
handleSysGenerateRootAttemptDelete(core, w, r)
|
||||||
default:
|
default:
|
||||||
@ -77,7 +77,7 @@ func handleSysGenerateRootAttemptGet(core *vault.Core, w http.ResponseWriter, r
|
|||||||
respondOk(w, status)
|
respondOk(w, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSysGenerateRootAttemptPut(core *vault.Core, w http.ResponseWriter, r *http.Request) {
|
func handleSysGenerateRootAttemptPut(core *vault.Core, w http.ResponseWriter, r *http.Request, generateStrategy vault.GenerateRootStrategy) {
|
||||||
// Parse the request
|
// Parse the request
|
||||||
var req GenerateRootInitRequest
|
var req GenerateRootInitRequest
|
||||||
if err := parseRequest(r, w, &req); err != nil {
|
if err := parseRequest(r, w, &req); err != nil {
|
||||||
@ -91,7 +91,7 @@ func handleSysGenerateRootAttemptPut(core *vault.Core, w http.ResponseWriter, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attemptialize the generation
|
// Attemptialize the generation
|
||||||
err := core.GenerateRootInit(req.OTP, req.PGPKey)
|
err := core.GenerateRootInit(req.OTP, req.PGPKey, generateStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, http.StatusBadRequest, err)
|
respondError(w, http.StatusBadRequest, err)
|
||||||
return
|
return
|
||||||
@ -109,7 +109,7 @@ func handleSysGenerateRootAttemptDelete(core *vault.Core, w http.ResponseWriter,
|
|||||||
respondOk(w, nil)
|
respondOk(w, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSysGenerateRootUpdate(core *vault.Core) http.Handler {
|
func handleSysGenerateRootUpdate(core *vault.Core, generateStrategy vault.GenerateRootStrategy) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Parse the request
|
// Parse the request
|
||||||
var req GenerateRootUpdateRequest
|
var req GenerateRootUpdateRequest
|
||||||
@ -141,7 +141,7 @@ func handleSysGenerateRootUpdate(core *vault.Core) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the key to make progress on root generation
|
// Use the key to make progress on root generation
|
||||||
result, err := core.GenerateRootUpdate(key, req.Nonce)
|
result, err := core.GenerateRootUpdate(key, req.Nonce, generateStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, http.StatusBadRequest, err)
|
respondError(w, http.StatusBadRequest, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -12,6 +12,42 @@ import (
|
|||||||
"github.com/hashicorp/vault/shamir"
|
"github.com/hashicorp/vault/shamir"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const coreDROperationTokenPath = "core/dr-operation-token"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// GenerateStandardRootTokenStrategy is the strategy used to generate a
|
||||||
|
// typical root token
|
||||||
|
GenerateStandardRootTokenStrategy GenerateRootStrategy = generateStandardRootToken{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenerateRootStrategy allows us to swap out the strategy we want to use to
|
||||||
|
// create a token upon completion of the generate root process.
|
||||||
|
type GenerateRootStrategy interface {
|
||||||
|
generate(*Core) (string, func(), error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateStandardRootToken implements the GenerateRootStrategy and is in
|
||||||
|
// charge of creating standard root tokens.
|
||||||
|
type generateStandardRootToken struct{}
|
||||||
|
|
||||||
|
func (g generateStandardRootToken) generate(c *Core) (string, func(), error) {
|
||||||
|
te, err := c.tokenStore.rootToken()
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Error("core: root token generation failed", "error", err)
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if te == nil {
|
||||||
|
c.logger.Error("core: got nil token entry back from root generation")
|
||||||
|
return "", nil, fmt.Errorf("got nil token entry back from root generation")
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupFunc := func() {
|
||||||
|
c.tokenStore.Revoke(te.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return te.ID, cleanupFunc, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateRootConfig holds the configuration for a root generation
|
// GenerateRootConfig holds the configuration for a root generation
|
||||||
// command.
|
// command.
|
||||||
type GenerateRootConfig struct {
|
type GenerateRootConfig struct {
|
||||||
@ -19,6 +55,7 @@ type GenerateRootConfig struct {
|
|||||||
PGPKey string
|
PGPKey string
|
||||||
PGPFingerprint string
|
PGPFingerprint string
|
||||||
OTP string
|
OTP string
|
||||||
|
Strategy GenerateRootStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRootResult holds the result of a root generation update
|
// GenerateRootResult holds the result of a root generation update
|
||||||
@ -68,12 +105,13 @@ func (c *Core) GenerateRootConfiguration() (*GenerateRootConfig, error) {
|
|||||||
conf = new(GenerateRootConfig)
|
conf = new(GenerateRootConfig)
|
||||||
*conf = *c.generateRootConfig
|
*conf = *c.generateRootConfig
|
||||||
conf.OTP = ""
|
conf.OTP = ""
|
||||||
|
conf.Strategy = nil
|
||||||
}
|
}
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRootInit is used to initialize the root generation settings
|
// GenerateRootInit is used to initialize the root generation settings
|
||||||
func (c *Core) GenerateRootInit(otp, pgpKey string) error {
|
func (c *Core) GenerateRootInit(otp, pgpKey string, strategy GenerateRootStrategy) error {
|
||||||
var fingerprint string
|
var fingerprint string
|
||||||
switch {
|
switch {
|
||||||
case len(otp) > 0:
|
case len(otp) > 0:
|
||||||
@ -127,6 +165,7 @@ func (c *Core) GenerateRootInit(otp, pgpKey string) error {
|
|||||||
OTP: otp,
|
OTP: otp,
|
||||||
PGPKey: pgpKey,
|
PGPKey: pgpKey,
|
||||||
PGPFingerprint: fingerprint,
|
PGPFingerprint: fingerprint,
|
||||||
|
Strategy: strategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.logger.IsInfo() {
|
if c.logger.IsInfo() {
|
||||||
@ -136,7 +175,7 @@ func (c *Core) GenerateRootInit(otp, pgpKey string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRootUpdate is used to provide a new key part
|
// GenerateRootUpdate is used to provide a new key part
|
||||||
func (c *Core) GenerateRootUpdate(key []byte, nonce string) (*GenerateRootResult, error) {
|
func (c *Core) GenerateRootUpdate(key []byte, nonce string, strategy GenerateRootStrategy) (*GenerateRootResult, error) {
|
||||||
// Verify the key length
|
// Verify the key length
|
||||||
min, max := c.barrier.KeyLength()
|
min, max := c.barrier.KeyLength()
|
||||||
max += shamir.ShareOverhead
|
max += shamir.ShareOverhead
|
||||||
@ -189,6 +228,10 @@ func (c *Core) GenerateRootUpdate(key []byte, nonce string) (*GenerateRootResult
|
|||||||
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this root generation operation is %s", c.generateRootConfig.Nonce)
|
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this root generation operation is %s", c.generateRootConfig.Nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strategy != c.generateRootConfig.Strategy {
|
||||||
|
return nil, fmt.Errorf("incorrect stategy supplied; a generate root operation of another type is already in progress")
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we already have this piece
|
// Check if we already have this piece
|
||||||
for _, existing := range c.generateRootProgress {
|
for _, existing := range c.generateRootProgress {
|
||||||
if bytes.Equal(existing, key) {
|
if bytes.Equal(existing, key) {
|
||||||
@ -238,24 +281,20 @@ func (c *Core) GenerateRootUpdate(key []byte, nonce string) (*GenerateRootResult
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
te, err := c.tokenStore.rootToken()
|
// Run the generate strategy
|
||||||
|
tokenUUID, cleanupFunc, err := strategy.generate(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Error("core: root token generation failed", "error", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if te == nil {
|
|
||||||
c.logger.Error("core: got nil token entry back from root generation")
|
|
||||||
return nil, fmt.Errorf("got nil token entry back from root generation")
|
|
||||||
}
|
|
||||||
|
|
||||||
uuidBytes, err := uuid.ParseUUID(te.ID)
|
uuidBytes, err := uuid.ParseUUID(tokenUUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.tokenStore.Revoke(te.ID)
|
cleanupFunc()
|
||||||
c.logger.Error("core: error getting generated token bytes", "error", err)
|
c.logger.Error("core: error getting generated token bytes", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if uuidBytes == nil {
|
if uuidBytes == nil {
|
||||||
c.tokenStore.Revoke(te.ID)
|
cleanupFunc()
|
||||||
c.logger.Error("core: got nil parsed UUID bytes")
|
c.logger.Error("core: got nil parsed UUID bytes")
|
||||||
return nil, fmt.Errorf("got nil parsed UUID bytes")
|
return nil, fmt.Errorf("got nil parsed UUID bytes")
|
||||||
}
|
}
|
||||||
@ -269,22 +308,22 @@ func (c *Core) GenerateRootUpdate(key []byte, nonce string) (*GenerateRootResult
|
|||||||
// just encode the value we're passing in.
|
// just encode the value we're passing in.
|
||||||
tokenBytes, err = xor.XORBase64(c.generateRootConfig.OTP, base64.StdEncoding.EncodeToString(uuidBytes))
|
tokenBytes, err = xor.XORBase64(c.generateRootConfig.OTP, base64.StdEncoding.EncodeToString(uuidBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.tokenStore.Revoke(te.ID)
|
cleanupFunc()
|
||||||
c.logger.Error("core: xor of root token failed", "error", err)
|
c.logger.Error("core: xor of root token failed", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case len(c.generateRootConfig.PGPKey) > 0:
|
case len(c.generateRootConfig.PGPKey) > 0:
|
||||||
_, tokenBytesArr, err := pgpkeys.EncryptShares([][]byte{[]byte(te.ID)}, []string{c.generateRootConfig.PGPKey})
|
_, tokenBytesArr, err := pgpkeys.EncryptShares([][]byte{[]byte(tokenUUID)}, []string{c.generateRootConfig.PGPKey})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.tokenStore.Revoke(te.ID)
|
cleanupFunc()
|
||||||
c.logger.Error("core: error encrypting new root token", "error", err)
|
c.logger.Error("core: error encrypting new root token", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tokenBytes = tokenBytesArr[0]
|
tokenBytes = tokenBytesArr[0]
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c.tokenStore.Revoke(te.ID)
|
cleanupFunc()
|
||||||
return nil, fmt.Errorf("unreachable condition")
|
return nil, fmt.Errorf("unreachable condition")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ func TestCore_GenerateRoot_Lifecycle(t *testing.T) {
|
|||||||
|
|
||||||
func testCore_GenerateRoot_Lifecycle_Common(t *testing.T, c *Core, keys [][]byte) {
|
func testCore_GenerateRoot_Lifecycle_Common(t *testing.T, c *Core, keys [][]byte) {
|
||||||
// Verify update not allowed
|
// Verify update not allowed
|
||||||
if _, err := c.GenerateRootUpdate(keys[0], ""); err == nil {
|
if _, err := c.GenerateRootUpdate(keys[0], "", GenerateStandardRootTokenStrategy); err == nil {
|
||||||
t.Fatalf("no root generation in progress")
|
t.Fatalf("no root generation in progress")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ func testCore_GenerateRoot_Lifecycle_Common(t *testing.T, c *Core, keys [][]byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start a root generation
|
// Start a root generation
|
||||||
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
|
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "", GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
@ -93,13 +93,13 @@ func testCore_GenerateRoot_Init_Common(t *testing.T, c *Core) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
|
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "", GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second should fail
|
// Second should fail
|
||||||
err = c.GenerateRootInit("", pgpkeys.TestPubKey1)
|
err = c.GenerateRootInit("", pgpkeys.TestPubKey1, GenerateStandardRootTokenStrategy)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("should fail")
|
t.Fatalf("should fail")
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ func testCore_GenerateRoot_InvalidMasterNonce_Common(t *testing.T, c *Core, keys
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
|
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "", GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
@ -136,14 +136,14 @@ func testCore_GenerateRoot_InvalidMasterNonce_Common(t *testing.T, c *Core, keys
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Provide the nonce (invalid)
|
// Provide the nonce (invalid)
|
||||||
_, err = c.GenerateRootUpdate(keys[0], "abcd")
|
_, err = c.GenerateRootUpdate(keys[0], "abcd", GenerateStandardRootTokenStrategy)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected error")
|
t.Fatalf("expected error")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide the master (invalid)
|
// Provide the master (invalid)
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
_, err = c.GenerateRootUpdate(key, rgconf.Nonce)
|
_, err = c.GenerateRootUpdate(key, rgconf.Nonce, GenerateStandardRootTokenStrategy)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected error")
|
t.Fatalf("expected error")
|
||||||
@ -164,7 +164,7 @@ func testCore_GenerateRoot_Update_OTP_Common(t *testing.T, c *Core, keys [][]byt
|
|||||||
|
|
||||||
otp := base64.StdEncoding.EncodeToString(otpBytes)
|
otp := base64.StdEncoding.EncodeToString(otpBytes)
|
||||||
// Start a root generation
|
// Start a root generation
|
||||||
err = c.GenerateRootInit(otp, "")
|
err = c.GenerateRootInit(otp, "", GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
@ -181,7 +181,7 @@ func testCore_GenerateRoot_Update_OTP_Common(t *testing.T, c *Core, keys [][]byt
|
|||||||
// Provide the keys
|
// Provide the keys
|
||||||
var result *GenerateRootResult
|
var result *GenerateRootResult
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
result, err = c.GenerateRootUpdate(key, rkconf.Nonce)
|
result, err = c.GenerateRootUpdate(key, rkconf.Nonce, GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ func TestCore_GenerateRoot_Update_PGP(t *testing.T) {
|
|||||||
|
|
||||||
func testCore_GenerateRoot_Update_PGP_Common(t *testing.T, c *Core, keys [][]byte) {
|
func testCore_GenerateRoot_Update_PGP_Common(t *testing.T, c *Core, keys [][]byte) {
|
||||||
// Start a root generation
|
// Start a root generation
|
||||||
err := c.GenerateRootInit("", pgpkeys.TestPubKey1)
|
err := c.GenerateRootInit("", pgpkeys.TestPubKey1, GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
@ -258,7 +258,7 @@ func testCore_GenerateRoot_Update_PGP_Common(t *testing.T, c *Core, keys [][]byt
|
|||||||
// Provide the keys
|
// Provide the keys
|
||||||
var result *GenerateRootResult
|
var result *GenerateRootResult
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
result, err = c.GenerateRootUpdate(key, rkconf.Nonce)
|
result, err = c.GenerateRootUpdate(key, rkconf.Nonce, GenerateStandardRootTokenStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user