Skip to content

Commit

Permalink
Add possibility to decode generated encoded root token to api (hashic…
Browse files Browse the repository at this point in the history
  • Loading branch information
l-with authored May 18, 2023
1 parent d52d307 commit 167def6
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 0 deletions.
3 changes: 3 additions & 0 deletions changelog/20595.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
core: Add possibility to decode a generated encoded root token via the rest API
```
20 changes: 20 additions & 0 deletions vault/logical_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
"github.com/hashicorp/vault/sdk/helper/roottoken"
"github.com/hashicorp/vault/sdk/helper/wrapping"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/version"
Expand Down Expand Up @@ -150,6 +151,7 @@ func NewSystemBackend(core *Core, logger log.Logger) *SystemBackend {
"health",
"generate-root/attempt",
"generate-root/update",
"decode-token",
"rekey/init",
"rekey/update",
"rekey/verify",
Expand Down Expand Up @@ -923,6 +925,24 @@ func (b *SystemBackend) handleRekeyDeleteRecovery(ctx context.Context, req *logi
return b.handleRekeyDelete(ctx, req, data, true)
}

func (b *SystemBackend) handleGenerateRootDecodeTokenUpdate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
encodedToken := data.Get("encoded_token").(string)
otp := data.Get("otp").(string)

token, err := roottoken.DecodeToken(encodedToken, otp, len(otp))
if err != nil {
return nil, err
}

// Generate the response
resp := &logical.Response{
Data: map[string]interface{}{
"token": token,
},
}
return resp, nil
}

func (b *SystemBackend) mountInfo(ctx context.Context, entry *MountEntry) map[string]interface{} {
info := map[string]interface{}{
"type": entry.Type,
Expand Down
26 changes: 26 additions & 0 deletions vault/logical_system_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,32 @@ func (b *SystemBackend) configPaths() []*framework.Path {
HelpSynopsis: strings.TrimSpace(sysHelp["generate-root"][0]),
HelpDescription: strings.TrimSpace(sysHelp["generate-root"][1]),
},
{
Pattern: "decode-token$",
Fields: map[string]*framework.FieldSchema{
"encoded_token": {
Type: framework.TypeString,
Description: "Specifies the encoded token (result from generate-root).",
},
"otp": {
Type: framework.TypeString,
Description: "Specifies the otp code for decode.",
},
},
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.handleGenerateRootDecodeTokenUpdate,
DisplayAttrs: &framework.DisplayAttributes{
OperationVerb: "decode",
},
Summary: "Decodes the encoded token with the otp.",
Responses: map[int][]framework.Response{
http.StatusOK: {{Description: "OK"}},
},
},
},
},

{
Pattern: "health$",
Fields: map[string]*framework.FieldSchema{
Expand Down
54 changes: 54 additions & 0 deletions vault/logical_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2420,6 +2420,60 @@ func TestSystemBackend_enableAudit(t *testing.T) {
}
}

// TestSystemBackend_decodeToken ensures the correct decoding of the encoded token.
// It also ensures that the API fails if there is some payload missing.
func TestSystemBackend_decodeToken(t *testing.T) {
encodedToken := "Bxg9JQQqOCNKBRICNwMIRzo2J3cWCBRi"
otp := "3JhHkONiyiaNYj14nnD9xZQS"
tokenExpected := "4RUmoevJ3lsLni9sTXcNnRE1"

_, b, _ := testCoreSystemBackend(t)

req := logical.TestRequest(t, logical.UpdateOperation, "decode-token")
req.Data["encoded_token"] = encodedToken
req.Data["otp"] = otp

resp, err := b.HandleRequest(namespace.RootContext(nil), req)
if err != nil {
t.Fatalf("err: %v", err)
}

schema.ValidateResponse(
t,
schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation),
resp,
true,
)

token, ok := resp.Data["token"]
if !ok {
t.Fatalf("did not get token back in response, response was %#v", resp.Data)
}

if token.(string) != tokenExpected {
t.Fatalf("bad token back: %s", token.(string))
}

datas := []map[string]interface{}{
nil,
{"encoded_token": encodedToken},
{"otp": otp},
}
for _, data := range datas {
req.Data = data
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
if err == nil {
t.Fatalf("no error despite missing payload")
}
schema.ValidateResponse(
t,
schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation),
resp,
true,
)
}
}

func TestSystemBackend_auditHash(t *testing.T) {
c, b, _ := testCoreSystemBackend(t)
c.auditBackends["noop"] = corehelpers.NoopAuditFactory(nil)
Expand Down
30 changes: 30 additions & 0 deletions website/content/api-docs/system/decode-token.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
layout: api
page_title: /sys/decode-token - HTTP API
description: The `/sys/decode-token` endpoint is used to decode the encoded token which is the result of /sys/generate-root.
---

# `/sys/decode-token`

The `/sys/decode-token` endpoint is used to decode the encoded token which is the result of the [/sys/generate-root](/vault/api-docs/system/generate-root) API.

## Parameters

- `encoded_token` `(string: <required>)` – Specifies the encoded token (result from /sys/generate-root).

- `otp` `(string: <required>)` - Specifies the otp code for decode.

## Sample Response

```json
{
"request_id": "9bc0fab8-d65c-3961-afe6-d05f50c5fd22",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"token": "4RUmoevJ3lsLni9sTXcNnRE1"
},
"warnings": null
}
```
4 changes: 4 additions & 0 deletions website/data/api-docs-nav-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,10 @@
"title": "<code>/sys/generate-root</code>",
"path": "system/generate-root"
},
{
"title": "<code>/sys/decode-token</code>",
"path": "system/decode-token"
},
{
"title": "<code>/sys/health</code>",
"path": "system/health"
Expand Down

0 comments on commit 167def6

Please sign in to comment.