vault: token store allows specifying display_name

This commit is contained in:
Armon Dadgar 2015-04-15 14:24:07 -07:00
parent b4a3e57bf6
commit dd87f94dfb
3 changed files with 80 additions and 30 deletions

View File

@ -971,10 +971,11 @@ func TestCore_HandleRequest_CreateToken_Lease(t *testing.T) {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
expect := &TokenEntry{ expect := &TokenEntry{
ID: clientToken, ID: clientToken,
Parent: root, Parent: root,
Policies: []string{"foo"}, Policies: []string{"foo"},
Path: "auth/token/create", Path: "auth/token/create",
DisplayName: "token",
} }
if !reflect.DeepEqual(te, expect) { if !reflect.DeepEqual(te, expect) {
t.Fatalf("Bad: %#v expect: %#v", te, expect) t.Fatalf("Bad: %#v expect: %#v", te, expect)

View File

@ -5,6 +5,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"regexp"
"strings" "strings"
"time" "time"
@ -34,6 +35,11 @@ const (
tokenSubPath = "token/" tokenSubPath = "token/"
) )
var (
// displayNameSanitize is used to sanitize a display name given to a token.
displayNameSanitize = regexp.MustCompile("[^a-zA-Z0-9-]")
)
// TokenStore is used to manage client tokens. Tokens are used for // TokenStore is used to manage client tokens. Tokens are used for
// clients to authenticate, and each token is mapped to an applicable // clients to authenticate, and each token is mapped to an applicable
// set of policy which is used for authorization. // set of policy which is used for authorization.
@ -247,8 +253,9 @@ func (ts *TokenStore) SaltID(id string) string {
// RootToken is used to generate a new token with root privileges and no parent // RootToken is used to generate a new token with root privileges and no parent
func (ts *TokenStore) RootToken() (*TokenEntry, error) { func (ts *TokenStore) RootToken() (*TokenEntry, error) {
te := &TokenEntry{ te := &TokenEntry{
Policies: []string{"root"}, Policies: []string{"root"},
Path: "auth/token/root", Path: "auth/token/root",
DisplayName: "root",
} }
if err := ts.Create(te); err != nil { if err := ts.Create(te); err != nil {
return nil, err return nil, err
@ -435,11 +442,12 @@ func (ts *TokenStore) handleCreate(
// Read and parse the fields // Read and parse the fields
var data struct { var data struct {
ID string ID string
Policies []string Policies []string
Metadata map[string]string `mapstructure:"meta"` Metadata map[string]string `mapstructure:"meta"`
NoParent bool `mapstructure:"no_parent"` NoParent bool `mapstructure:"no_parent"`
Lease string Lease string
DisplayName string `mapstructure:"display_name"`
} }
if err := mapstructure.WeakDecode(req.Data, &data); err != nil { if err := mapstructure.WeakDecode(req.Data, &data); err != nil {
return logical.ErrorResponse(fmt.Sprintf( return logical.ErrorResponse(fmt.Sprintf(
@ -448,9 +456,18 @@ func (ts *TokenStore) handleCreate(
// Setup the token entry // Setup the token entry
te := TokenEntry{ te := TokenEntry{
Parent: req.ClientToken, Parent: req.ClientToken,
Path: "auth/token/create", Path: "auth/token/create",
Meta: data.Metadata, Meta: data.Metadata,
DisplayName: "token",
}
// Attach the given display name if any
if data.DisplayName != "" {
full := "token-" + data.DisplayName
full = displayNameSanitize.ReplaceAllString(full, "-")
full = strings.TrimSuffix(full, "-")
te.DisplayName = full
} }
// Allow specifying the ID of the token if the client is root // Allow specifying the ID of the token if the client is root
@ -593,10 +610,11 @@ func (ts *TokenStore) handleLookup(
// you could escalade your privileges. // you could escalade your privileges.
resp := &logical.Response{ resp := &logical.Response{
Data: map[string]interface{}{ Data: map[string]interface{}{
"id": out.ID, "id": out.ID,
"policies": out.Policies, "policies": out.Policies,
"path": out.Path, "path": out.Path,
"meta": out.Meta, "meta": out.Meta,
"display_name": out.DisplayName,
}, },
} }
return resp, nil return resp, nil

View File

@ -269,6 +269,34 @@ func TestTokenStore_RevokeTree(t *testing.T) {
} }
} }
func TestTokenStore_HandleRequest_CreateToken_DisplayName(t *testing.T) {
_, ts, root := mockTokenStore(t)
req := logical.TestRequest(t, logical.WriteOperation, "create")
req.ClientToken = root
req.Data["display_name"] = "foo_bar.baz!"
resp, err := ts.HandleRequest(req)
if err != nil {
t.Fatalf("err: %v %v", err, resp)
}
expected := &TokenEntry{
ID: resp.Auth.ClientToken,
Parent: root,
Policies: []string{"root"},
Path: "auth/token/create",
DisplayName: "token-foo-bar-baz",
}
out, err := ts.Lookup(resp.Auth.ClientToken)
if err != nil {
t.Fatalf("err: %v", err)
}
if !reflect.DeepEqual(out, expected) {
t.Fatalf("bad: %#v", out)
}
}
func TestTokenStore_HandleRequest_CreateToken_NoPolicy(t *testing.T) { func TestTokenStore_HandleRequest_CreateToken_NoPolicy(t *testing.T) {
_, ts, root := mockTokenStore(t) _, ts, root := mockTokenStore(t)
@ -281,10 +309,11 @@ func TestTokenStore_HandleRequest_CreateToken_NoPolicy(t *testing.T) {
} }
expected := &TokenEntry{ expected := &TokenEntry{
ID: resp.Auth.ClientToken, ID: resp.Auth.ClientToken,
Parent: root, Parent: root,
Policies: []string{"root"}, Policies: []string{"root"},
Path: "auth/token/create", Path: "auth/token/create",
DisplayName: "token",
} }
out, err := ts.Lookup(resp.Auth.ClientToken) out, err := ts.Lookup(resp.Auth.ClientToken)
if err != nil { if err != nil {
@ -560,10 +589,11 @@ func TestTokenStore_HandleRequest_Lookup(t *testing.T) {
} }
exp := map[string]interface{}{ exp := map[string]interface{}{
"id": root, "id": root,
"policies": []string{"root"}, "policies": []string{"root"},
"path": "auth/token/root", "path": "auth/token/root",
"meta": map[string]string(nil), "meta": map[string]string(nil),
"display_name": "root",
} }
if !reflect.DeepEqual(resp.Data, exp) { if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("bad: %#v exp: %#v", resp.Data, exp) t.Fatalf("bad: %#v exp: %#v", resp.Data, exp)
@ -623,10 +653,11 @@ func TestTokenStore_HandleRequest_LookupSelf(t *testing.T) {
} }
exp := map[string]interface{}{ exp := map[string]interface{}{
"id": root, "id": root,
"policies": []string{"root"}, "policies": []string{"root"},
"path": "auth/token/root", "path": "auth/token/root",
"meta": map[string]string(nil), "meta": map[string]string(nil),
"display_name": "root",
} }
if !reflect.DeepEqual(resp.Data, exp) { if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("bad: %#v exp: %#v", resp.Data, exp) t.Fatalf("bad: %#v exp: %#v", resp.Data, exp)