diff --git a/api/logical.go b/api/logical.go index ded776aaf2..2e967f4458 100644 --- a/api/logical.go +++ b/api/logical.go @@ -1,5 +1,15 @@ package api +import ( + "bytes" + "encoding/json" + "fmt" +) + +const ( + wrappedResponseLocation = "cubbyhole/response" +) + // Logical is used to perform logical backend operations on Vault. type Logical struct { c *Client @@ -80,3 +90,34 @@ func (c *Logical) Delete(path string) (*Secret, error) { return nil, nil } + +func (c *Logical) Unwrap(wrappingToken string) (*Secret, error) { + origToken := c.c.Token() + defer c.c.SetToken(origToken) + + c.c.SetToken(wrappingToken) + + secret, err := c.Read(wrappedResponseLocation) + if err != nil { + return nil, fmt.Errorf("error reading %s: %s", wrappedResponseLocation, err) + } + if secret == nil { + return nil, fmt.Errorf("no value found at %s", wrappedResponseLocation) + } + if secret.Data == nil { + return nil, fmt.Errorf("\"data\" not found in wrapping response") + } + if _, ok := secret.Data["response"]; !ok { + return nil, fmt.Errorf("\"response\" not found in wrapping response \"data\" map") + } + + wrappedSecret := new(Secret) + buf := bytes.NewBufferString(secret.Data["response"].(string)) + dec := json.NewDecoder(buf) + dec.UseNumber() + if err := dec.Decode(wrappedSecret); err != nil { + return nil, fmt.Errorf("error unmarshaling wrapped secret: %s", err) + } + + return wrappedSecret, nil +} diff --git a/command/unwrap.go b/command/unwrap.go index 1f6460a01b..df7bc3f9ee 100644 --- a/command/unwrap.go +++ b/command/unwrap.go @@ -1,8 +1,6 @@ package command import ( - "bytes" - "encoding/json" "flag" "fmt" "strings" @@ -12,10 +10,6 @@ import ( "github.com/hashicorp/vault/meta" ) -const ( - wrappedResponseLocation = "cubbyhole/response" -) - // UnwrapCommand is a Command that behaves like ReadCommand but specifically // for unwrapping cubbyhole-wrapped secrets type UnwrapCommand struct { @@ -58,9 +52,7 @@ func (c *UnwrapCommand) Run(args []string) int { return 2 } - client.SetToken(tokenID) - - secret, err = c.getUnwrappedResponse(client) + secret, err = client.Logical().Unwrap(tokenID) if err != nil { c.Ui.Error(err.Error()) return 1 @@ -78,33 +70,6 @@ func (c *UnwrapCommand) Run(args []string) int { return OutputSecret(c.Ui, format, secret) } -// getUnwrappedResponse is a helper to do the actual reading and unwrapping -func (c *UnwrapCommand) getUnwrappedResponse(client *api.Client) (*api.Secret, error) { - secret, err := client.Logical().Read(wrappedResponseLocation) - if err != nil { - return nil, fmt.Errorf("Error reading %s: %s", wrappedResponseLocation, err) - } - if secret == nil { - return nil, fmt.Errorf("No value found at %s", wrappedResponseLocation) - } - if secret.Data == nil { - return nil, fmt.Errorf("\"data\" not found in wrapping response") - } - if _, ok := secret.Data["response"]; !ok { - return nil, fmt.Errorf("\"response\" not found in wrapping response \"data\" map") - } - - wrappedSecret := new(api.Secret) - buf := bytes.NewBufferString(secret.Data["response"].(string)) - dec := json.NewDecoder(buf) - dec.UseNumber() - if err := dec.Decode(wrappedSecret); err != nil { - return nil, fmt.Errorf("Error unmarshaling wrapped secret: %s", err) - } - - return wrappedSecret, nil -} - func (c *UnwrapCommand) Synopsis() string { return "Unwrap a wrapped secret" }