2015-03-18 20:19:19 +00:00
|
|
|
package vault
|
|
|
|
|
|
|
|
import (
|
2016-09-26 22:17:50 +00:00
|
|
|
"encoding/json"
|
2016-03-01 17:33:35 +00:00
|
|
|
"fmt"
|
2015-03-18 20:19:19 +00:00
|
|
|
"reflect"
|
2016-12-16 21:46:29 +00:00
|
|
|
"sort"
|
2016-03-01 17:33:35 +00:00
|
|
|
"strings"
|
2016-12-16 18:11:55 +00:00
|
|
|
"sync"
|
2015-03-18 20:19:19 +00:00
|
|
|
"testing"
|
2015-03-24 22:10:46 +00:00
|
|
|
"time"
|
|
|
|
|
2016-09-26 22:17:50 +00:00
|
|
|
"github.com/hashicorp/go-uuid"
|
2015-03-24 22:10:46 +00:00
|
|
|
"github.com/hashicorp/vault/logical"
|
2015-03-18 20:19:19 +00:00
|
|
|
)
|
|
|
|
|
2016-09-26 22:17:50 +00:00
|
|
|
type TokenEntryOld struct {
|
|
|
|
ID string
|
|
|
|
Accessor string
|
|
|
|
Parent string
|
|
|
|
Policies []string
|
|
|
|
Path string
|
|
|
|
Meta map[string]string
|
|
|
|
DisplayName string
|
|
|
|
NumUses int
|
|
|
|
CreationTime int64
|
|
|
|
TTL time.Duration
|
|
|
|
ExplicitMaxTTL time.Duration
|
|
|
|
Role string
|
|
|
|
Period time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_TokenEntryUpgrade(t *testing.T) {
|
|
|
|
var err error
|
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
// Use a struct that does not have struct tags to store the items and
|
|
|
|
// check if the lookup code handles them properly while reading back
|
|
|
|
entry := &TokenEntryOld{
|
|
|
|
DisplayName: "test-display-name",
|
|
|
|
Path: "test",
|
|
|
|
Policies: []string{"dev", "ops"},
|
|
|
|
CreationTime: time.Now().Unix(),
|
|
|
|
ExplicitMaxTTL: 100,
|
|
|
|
NumUses: 10,
|
|
|
|
}
|
|
|
|
entry.ID, err = uuid.GenerateUUID()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
enc, err := json.Marshal(entry)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
saltedId := ts.SaltID(entry.ID)
|
|
|
|
path := lookupPrefix + saltedId
|
|
|
|
le := &logical.StorageEntry{
|
|
|
|
Key: path,
|
|
|
|
Value: enc,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ts.view.Put(le); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(entry.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out.DisplayName != "test-display-name" {
|
|
|
|
t.Fatalf("bad: display_name: expected: test-display-name, actual: %s", out.DisplayName)
|
|
|
|
}
|
|
|
|
if out.CreationTime == 0 {
|
|
|
|
t.Fatal("bad: expected a non-zero creation time")
|
|
|
|
}
|
|
|
|
if out.ExplicitMaxTTL != 100 {
|
|
|
|
t.Fatalf("bad: explicit_max_ttl: expected: 100, actual: %d", out.ExplicitMaxTTL)
|
|
|
|
}
|
|
|
|
if out.NumUses != 10 {
|
|
|
|
t.Fatalf("bad: num_uses: expected: 10, actual: %d", out.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test the default case to ensure there are no regressions
|
|
|
|
ent := &TokenEntry{
|
|
|
|
DisplayName: "test-display-name",
|
|
|
|
Path: "test",
|
|
|
|
Policies: []string{"dev", "ops"},
|
|
|
|
CreationTime: time.Now().Unix(),
|
|
|
|
ExplicitMaxTTL: 100,
|
|
|
|
NumUses: 10,
|
|
|
|
}
|
|
|
|
if err := ts.create(ent); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out.DisplayName != "test-display-name" {
|
|
|
|
t.Fatalf("bad: display_name: expected: test-display-name, actual: %s", out.DisplayName)
|
|
|
|
}
|
|
|
|
if out.CreationTime == 0 {
|
|
|
|
t.Fatal("bad: expected a non-zero creation time")
|
|
|
|
}
|
|
|
|
if out.ExplicitMaxTTL != 100 {
|
|
|
|
t.Fatalf("bad: explicit_max_ttl: expected: 100, actual: %d", out.ExplicitMaxTTL)
|
|
|
|
}
|
|
|
|
if out.NumUses != 10 {
|
|
|
|
t.Fatalf("bad: num_uses: expected: 10, actual: %d", out.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in the deprecated fields and read out from proper fields
|
|
|
|
ent = &TokenEntry{
|
|
|
|
Path: "test",
|
|
|
|
Policies: []string{"dev", "ops"},
|
|
|
|
DisplayNameDeprecated: "test-display-name",
|
|
|
|
CreationTimeDeprecated: time.Now().Unix(),
|
|
|
|
ExplicitMaxTTLDeprecated: 100,
|
|
|
|
NumUsesDeprecated: 10,
|
|
|
|
}
|
|
|
|
if err := ts.create(ent); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out.DisplayName != "test-display-name" {
|
|
|
|
t.Fatalf("bad: display_name: expected: test-display-name, actual: %s", out.DisplayName)
|
|
|
|
}
|
|
|
|
if out.CreationTime == 0 {
|
|
|
|
t.Fatal("bad: expected a non-zero creation time")
|
|
|
|
}
|
|
|
|
if out.ExplicitMaxTTL != 100 {
|
|
|
|
t.Fatalf("bad: explicit_max_ttl: expected: 100, actual: %d", out.ExplicitMaxTTL)
|
|
|
|
}
|
|
|
|
if out.NumUses != 10 {
|
|
|
|
t.Fatalf("bad: num_uses: expected: 10, actual: %d", out.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if NumUses picks up a lower value
|
|
|
|
ent = &TokenEntry{
|
|
|
|
Path: "test",
|
|
|
|
NumUses: 5,
|
|
|
|
NumUsesDeprecated: 10,
|
|
|
|
}
|
|
|
|
if err := ts.create(ent); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out.NumUses != 5 {
|
|
|
|
t.Fatalf("bad: num_uses: expected: 5, actual: %d", out.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Switch the values from deprecated and proper field and check if the
|
|
|
|
// lower value is still getting picked up
|
|
|
|
ent = &TokenEntry{
|
|
|
|
Path: "test",
|
|
|
|
NumUses: 10,
|
|
|
|
NumUsesDeprecated: 5,
|
|
|
|
}
|
|
|
|
if err := ts.create(ent); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out.NumUses != 5 {
|
|
|
|
t.Fatalf("bad: num_uses: expected: 5, actual: %d", out.NumUses)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 20:58:12 +00:00
|
|
|
func getBackendConfig(c *Core) *logical.BackendConfig {
|
|
|
|
return &logical.BackendConfig{
|
|
|
|
Logger: c.logger,
|
|
|
|
System: logical.StaticSystemView{
|
|
|
|
DefaultLeaseTTLVal: time.Hour * 24,
|
2016-09-28 22:32:49 +00:00
|
|
|
MaxLeaseTTLVal: time.Hour * 24 * 32,
|
2015-09-04 20:58:12 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 19:13:09 +00:00
|
|
|
func testMakeToken(t *testing.T, ts *TokenStore, root, client, ttl string, policy []string) {
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["id"] = client
|
|
|
|
req.Data["policies"] = policy
|
|
|
|
req.Data["ttl"] = ttl
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken != client {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testCoreMakeToken(t *testing.T, c *Core, root, client, ttl string, policy []string) {
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["id"] = client
|
|
|
|
req.Data["policies"] = policy
|
|
|
|
req.Data["ttl"] = ttl
|
|
|
|
|
|
|
|
resp, err := c.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken != client {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 17:50:26 +00:00
|
|
|
func TestTokenStore_AccessorIndex(t *testing.T) {
|
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}}
|
|
|
|
if err := ts.create(ent); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that accessor is created
|
|
|
|
if out == nil || out.Accessor == "" {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
|
2016-07-29 22:20:38 +00:00
|
|
|
aEntry, err := ts.lookupByAccessor(out.Accessor)
|
2016-03-09 17:50:26 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the value returned from the index matches the token ID
|
2016-07-29 22:20:38 +00:00
|
|
|
if aEntry.TokenID != ent.ID {
|
|
|
|
t.Fatalf("bad: got\n%s\nexpected\n%s\n", aEntry.TokenID, ent.ID)
|
2016-03-09 17:50:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_LookupAccessor(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
testMakeToken(t, ts, root, "tokenid", "", []string{"foo"})
|
|
|
|
out, err := ts.Lookup("tokenid")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out == nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "lookup-accessor")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"accessor": out.Accessor,
|
|
|
|
}
|
2016-03-09 17:50:26 +00:00
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if resp.Data == nil {
|
|
|
|
t.Fatalf("response should contain data")
|
|
|
|
}
|
|
|
|
|
|
|
|
if resp.Data["accessor"].(string) == "" {
|
|
|
|
t.Fatalf("accessor should not be empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the lookup-accessor operation does not return the token ID
|
|
|
|
if resp.Data["id"].(string) != "" {
|
|
|
|
t.Fatalf("token ID should not be returned")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-29 22:20:38 +00:00
|
|
|
func TestTokenStore_HandleRequest_ListAccessors(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
testKeys := []string{"token1", "token2", "token3", "token4"}
|
|
|
|
for _, key := range testKeys {
|
|
|
|
testMakeToken(t, ts, root, key, "", []string{"foo"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revoke root to make the number of accessors match
|
|
|
|
ts.revokeSalted(ts.SaltID(root))
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.ListOperation, "accessors")
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if resp.Data == nil {
|
|
|
|
t.Fatalf("response should contain data")
|
|
|
|
}
|
|
|
|
if resp.Data["keys"] == nil {
|
|
|
|
t.Fatalf("keys should not be empty")
|
|
|
|
}
|
|
|
|
keys := resp.Data["keys"].([]string)
|
|
|
|
if len(keys) != len(testKeys) {
|
|
|
|
t.Fatalf("wrong number of accessors found")
|
|
|
|
}
|
2016-08-01 17:07:41 +00:00
|
|
|
if len(resp.Warnings()) != 0 {
|
|
|
|
t.Fatalf("got warnings:\n%#v", resp.Warnings())
|
|
|
|
}
|
2016-07-29 22:20:38 +00:00
|
|
|
|
|
|
|
// Test upgrade from old struct method of accessor storage (of token id)
|
|
|
|
for _, accessor := range keys {
|
|
|
|
aEntry, err := ts.lookupByAccessor(accessor)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if aEntry.TokenID == "" || aEntry.AccessorID == "" {
|
|
|
|
t.Fatalf("error, accessor entry looked up is empty, but no error thrown")
|
|
|
|
}
|
|
|
|
path := accessorPrefix + ts.SaltID(accessor)
|
|
|
|
le := &logical.StorageEntry{Key: path, Value: []byte(aEntry.TokenID)}
|
|
|
|
if err := ts.view.Put(le); err != nil {
|
|
|
|
t.Fatalf("failed to persist accessor index entry: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the lookup again, should get same result
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if resp.Data == nil {
|
|
|
|
t.Fatalf("response should contain data")
|
|
|
|
}
|
|
|
|
if resp.Data["keys"] == nil {
|
|
|
|
t.Fatalf("keys should not be empty")
|
|
|
|
}
|
|
|
|
keys2 := resp.Data["keys"].([]string)
|
|
|
|
if len(keys) != len(testKeys) {
|
|
|
|
t.Fatalf("wrong number of accessors found")
|
|
|
|
}
|
2016-08-01 17:07:41 +00:00
|
|
|
if len(resp.Warnings()) != 0 {
|
|
|
|
t.Fatalf("got warnings:\n%#v", resp.Warnings())
|
|
|
|
}
|
2016-07-29 22:20:38 +00:00
|
|
|
|
|
|
|
for _, accessor := range keys2 {
|
|
|
|
aEntry, err := ts.lookupByAccessor(accessor)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if aEntry.TokenID == "" || aEntry.AccessorID == "" {
|
|
|
|
t.Fatalf("error, accessor entry looked up is empty, but no error thrown")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 17:50:26 +00:00
|
|
|
func TestTokenStore_HandleRequest_RevokeAccessor(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
testMakeToken(t, ts, root, "tokenid", "", []string{"foo"})
|
|
|
|
out, err := ts.Lookup("tokenid")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if out == nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "revoke-accessor")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"accessor": out.Accessor,
|
|
|
|
}
|
2016-03-09 17:50:26 +00:00
|
|
|
|
|
|
|
_, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err = ts.Lookup("tokenid")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad:\ngot %#v\nexpected: nil\n", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:16:37 +00:00
|
|
|
func TestTokenStore_RootToken(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-24 00:16:37 +00:00
|
|
|
|
2016-01-20 00:44:33 +00:00
|
|
|
te, err := ts.rootToken()
|
2015-03-24 00:16:37 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if te.ID == "" {
|
|
|
|
t.Fatalf("missing ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(te.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, te) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", te, out)
|
2015-03-24 00:16:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 20:19:19 +00:00
|
|
|
func TestTokenStore_CreateLookup(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
c, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-18 20:19:19 +00:00
|
|
|
|
2015-03-23 20:39:43 +00:00
|
|
|
ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-03-18 20:19:19 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if ent.ID == "" {
|
|
|
|
t.Fatalf("missing ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, ent) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", ent, out)
|
2015-03-24 21:22:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// New store should share the salt
|
2015-09-04 20:58:12 +00:00
|
|
|
ts2, err := NewTokenStore(c, getBackendConfig(c))
|
2015-03-24 21:22:50 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2017-02-17 04:09:39 +00:00
|
|
|
if err := ts2.Initialize(); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2015-03-24 21:22:50 +00:00
|
|
|
|
|
|
|
// Should still match
|
|
|
|
out, err = ts2.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, ent) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", ent, out)
|
2015-03-24 21:22:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_CreateLookup_ProvidedID(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
c, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-24 21:22:50 +00:00
|
|
|
|
|
|
|
ent := &TokenEntry{
|
|
|
|
ID: "foobarbaz",
|
|
|
|
Path: "test",
|
|
|
|
Policies: []string{"dev", "ops"},
|
|
|
|
}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-03-24 21:22:50 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if ent.ID != "foobarbaz" {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: ent.ID: expected:\"foobarbaz\"\n actual:%s", ent.ID)
|
2015-03-24 21:22:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, ent) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", ent, out)
|
2015-03-18 20:19:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// New store should share the salt
|
2015-09-04 20:58:12 +00:00
|
|
|
ts2, err := NewTokenStore(c, getBackendConfig(c))
|
2015-03-18 20:19:19 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2017-02-17 04:09:39 +00:00
|
|
|
if err := ts2.Initialize(); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2015-03-18 20:19:19 +00:00
|
|
|
|
|
|
|
// Should still match
|
|
|
|
out, err = ts2.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, ent) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", ent, out)
|
2015-03-18 20:19:19 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-18 20:50:36 +00:00
|
|
|
|
2015-04-17 18:51:04 +00:00
|
|
|
func TestTokenStore_UseToken(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-04-17 18:51:04 +00:00
|
|
|
|
|
|
|
// Lookup the root token
|
|
|
|
ent, err := ts.Lookup(root)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Root is an unlimited use token, should be a no-op
|
2016-05-02 07:11:14 +00:00
|
|
|
te, err := ts.UseToken(ent)
|
2015-04-17 18:51:04 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2016-05-02 07:11:14 +00:00
|
|
|
if te == nil {
|
|
|
|
t.Fatalf("token entry after use was nil")
|
|
|
|
}
|
2015-04-17 18:51:04 +00:00
|
|
|
|
|
|
|
// Lookup the root token again
|
|
|
|
ent2, err := ts.Lookup(root)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(ent, ent2) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: ent:%#v ent2:%#v", ent, ent2)
|
2015-04-17 18:51:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create a retstricted token
|
|
|
|
ent = &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}, NumUses: 2}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-04-17 18:51:04 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the token
|
2016-05-02 07:11:14 +00:00
|
|
|
te, err = ts.UseToken(ent)
|
2015-04-17 18:51:04 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2016-05-02 07:11:14 +00:00
|
|
|
if te == nil {
|
|
|
|
t.Fatalf("token entry for use #1 was nil")
|
|
|
|
}
|
2015-04-17 18:51:04 +00:00
|
|
|
|
|
|
|
// Lookup the token
|
|
|
|
ent2, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should be reduced
|
|
|
|
if ent2.NumUses != 1 {
|
|
|
|
t.Fatalf("bad: %#v", ent2)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the token
|
2016-05-02 07:11:14 +00:00
|
|
|
te, err = ts.UseToken(ent)
|
2015-04-17 18:51:04 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2016-05-02 07:11:14 +00:00
|
|
|
if te == nil {
|
|
|
|
t.Fatalf("token entry for use #2 was nil")
|
|
|
|
}
|
2016-12-16 18:11:55 +00:00
|
|
|
if te.NumUses != tokenRevocationDeferred {
|
2016-05-02 07:11:14 +00:00
|
|
|
t.Fatalf("token entry after use #2 did not have revoke flag")
|
|
|
|
}
|
|
|
|
ts.Revoke(te.ID)
|
2015-04-17 18:51:04 +00:00
|
|
|
|
|
|
|
// Lookup the token
|
|
|
|
ent2, err = ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should be revoked
|
|
|
|
if ent2 != nil {
|
|
|
|
t.Fatalf("bad: %#v", ent2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 20:50:36 +00:00
|
|
|
func TestTokenStore_Revoke(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-18 20:50:36 +00:00
|
|
|
|
2015-03-23 20:39:43 +00:00
|
|
|
ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err := ts.Revoke("")
|
|
|
|
if err.Error() != "cannot revoke blank token" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
err = ts.Revoke(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-10 22:12:04 +00:00
|
|
|
func TestTokenStore_Revoke_Leases(t *testing.T) {
|
2017-01-07 23:18:22 +00:00
|
|
|
c, ts, _, _ := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
view := NewBarrierView(c.barrier, "noop/")
|
2015-04-10 22:12:04 +00:00
|
|
|
|
|
|
|
// Mount a noop backend
|
|
|
|
noop := &NoopBackend{}
|
2017-01-07 23:18:22 +00:00
|
|
|
ts.expiration.router.Mount(noop, "", &MountEntry{UUID: ""}, view)
|
2015-04-10 22:12:04 +00:00
|
|
|
|
|
|
|
ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-04-10 22:12:04 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a lease
|
|
|
|
req := &logical.Request{
|
|
|
|
Operation: logical.ReadOperation,
|
|
|
|
Path: "secret/foo",
|
|
|
|
ClientToken: ent.ID,
|
|
|
|
}
|
|
|
|
resp := &logical.Response{
|
|
|
|
Secret: &logical.Secret{
|
|
|
|
LeaseOptions: logical.LeaseOptions{
|
2015-08-21 00:47:17 +00:00
|
|
|
TTL: 20 * time.Millisecond,
|
2015-04-10 22:12:04 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"access_key": "xyz",
|
|
|
|
"secret_key": "abcd",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
leaseID, err := ts.expiration.Register(req, resp)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revoke the token
|
|
|
|
err = ts.Revoke(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the lease is gone
|
|
|
|
out, err := ts.expiration.loadEntry(leaseID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 20:50:36 +00:00
|
|
|
func TestTokenStore_Revoke_Orphan(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-18 20:50:36 +00:00
|
|
|
|
2015-03-23 20:39:43 +00:00
|
|
|
ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent2 := &TokenEntry{Parent: ent.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent2); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err := ts.Revoke(ent.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(ent2.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, ent2) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", ent2, out)
|
2015-03-18 20:50:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_RevokeTree(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-18 20:50:36 +00:00
|
|
|
|
|
|
|
ent1 := &TokenEntry{}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent1); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent2 := &TokenEntry{Parent: ent1.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent2); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent3 := &TokenEntry{Parent: ent2.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent3); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent4 := &TokenEntry{Parent: ent2.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent4); err != nil {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err := ts.RevokeTree("")
|
2017-04-26 23:26:48 +00:00
|
|
|
if err.Error() != "cannot tree-revoke blank token" {
|
2015-03-18 20:50:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
err = ts.RevokeTree(ent1.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lookup := []string{ent1.ID, ent2.ID, ent3.ID, ent4.ID}
|
|
|
|
for _, id := range lookup {
|
|
|
|
out, err := ts.Lookup(id)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 17:22:30 +00:00
|
|
|
func TestTokenStore_RevokeSelf(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-09-17 17:22:30 +00:00
|
|
|
|
|
|
|
ent1 := &TokenEntry{}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent1); err != nil {
|
2015-09-17 17:22:30 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent2 := &TokenEntry{Parent: ent1.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent2); err != nil {
|
2015-09-17 17:22:30 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent3 := &TokenEntry{Parent: ent2.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent3); err != nil {
|
2015-09-17 17:22:30 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ent4 := &TokenEntry{Parent: ent2.ID}
|
2015-10-30 14:59:26 +00:00
|
|
|
if err := ts.create(ent4); err != nil {
|
2015-09-17 17:22:30 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "revoke-self")
|
2015-09-17 17:22:30 +00:00
|
|
|
req.ClientToken = ent1.ID
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
lookup := []string{ent1.ID, ent2.ID, ent3.ID, ent4.ID}
|
|
|
|
for _, id := range lookup {
|
|
|
|
out, err := ts.Lookup(id)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-25 19:59:02 +00:00
|
|
|
func TestTokenStore_HandleRequest_NonAssignable(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"default", "foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
2016-09-29 04:01:28 +00:00
|
|
|
req.Data["policies"] = []string{"default", "foo", responseWrappingPolicyName}
|
2016-07-25 19:59:02 +00:00
|
|
|
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("got a nil response")
|
|
|
|
}
|
|
|
|
if !resp.IsError() {
|
|
|
|
t.Fatalf("expected error; response is %#v", *resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-15 21:24:07 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_DisplayName(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-04-15 21:24:07 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-04-15 21:24:07 +00:00
|
|
|
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,
|
2016-03-09 18:45:36 +00:00
|
|
|
Accessor: resp.Auth.Accessor,
|
2015-04-15 21:24:07 +00:00
|
|
|
Parent: root,
|
|
|
|
Policies: []string{"root"},
|
|
|
|
Path: "auth/token/create",
|
|
|
|
DisplayName: "token-foo-bar-baz",
|
2015-09-18 20:33:52 +00:00
|
|
|
TTL: 0,
|
2015-04-15 21:24:07 +00:00
|
|
|
}
|
|
|
|
out, err := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2015-09-18 20:33:52 +00:00
|
|
|
expected.CreationTime = out.CreationTime
|
2015-04-15 21:24:07 +00:00
|
|
|
if !reflect.DeepEqual(out, expected) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, out)
|
2015-04-15 21:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-17 18:34:25 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NumUses(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-04-17 18:34:25 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-04-17 18:34:25 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["num_uses"] = "1"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := &TokenEntry{
|
|
|
|
ID: resp.Auth.ClientToken,
|
2016-03-09 18:45:36 +00:00
|
|
|
Accessor: resp.Auth.Accessor,
|
2015-04-17 18:34:25 +00:00
|
|
|
Parent: root,
|
|
|
|
Policies: []string{"root"},
|
|
|
|
Path: "auth/token/create",
|
|
|
|
DisplayName: "token",
|
|
|
|
NumUses: 1,
|
2015-09-18 20:33:52 +00:00
|
|
|
TTL: 0,
|
2015-04-17 18:34:25 +00:00
|
|
|
}
|
|
|
|
out, err := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2015-09-18 20:33:52 +00:00
|
|
|
expected.CreationTime = out.CreationTime
|
2015-04-17 18:34:25 +00:00
|
|
|
if !reflect.DeepEqual(out, expected) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, out)
|
2015-04-17 18:34:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NumUses_Invalid(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-04-17 18:34:25 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-04-17 18:34:25 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["num_uses"] = "-1"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NumUses_Restricted(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-04-17 18:34:25 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-04-17 18:34:25 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["num_uses"] = "1"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We should NOT be able to use the restricted token to create a new token
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
_, err = ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 22:10:46 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NoPolicy(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
2015-04-07 21:19:52 +00:00
|
|
|
if err != nil {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-04-07 21:19:52 +00:00
|
|
|
|
|
|
|
expected := &TokenEntry{
|
2015-04-15 21:24:07 +00:00
|
|
|
ID: resp.Auth.ClientToken,
|
2016-03-09 18:45:36 +00:00
|
|
|
Accessor: resp.Auth.Accessor,
|
2015-04-15 21:24:07 +00:00
|
|
|
Parent: root,
|
|
|
|
Policies: []string{"root"},
|
|
|
|
Path: "auth/token/create",
|
|
|
|
DisplayName: "token",
|
2015-09-18 20:33:52 +00:00
|
|
|
TTL: 0,
|
2015-04-07 21:19:52 +00:00
|
|
|
}
|
|
|
|
out, err := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2015-09-18 20:33:52 +00:00
|
|
|
expected.CreationTime = out.CreationTime
|
2015-04-07 21:19:52 +00:00
|
|
|
if !reflect.DeepEqual(out, expected) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, out)
|
2015-03-24 22:10:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_BadParent(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, _ := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = "random"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Data["error"] != "parent token lookup failed" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken == "" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_RootID(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["id"] = "foobar"
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken != "foobar" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NonRootID(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "client", "", []string{"foo"})
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = "client"
|
|
|
|
req.Data["id"] = "foobar"
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-09-19 16:33:52 +00:00
|
|
|
if resp.Data["error"] != "root or sudo privileges required to specify token id" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NonRoot_Subset(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "client", "", []string{"foo", "bar"})
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = "client"
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken == "" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NonRoot_InvalidSubset(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "client", "", []string{"foo", "bar"})
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = "client"
|
|
|
|
req.Data["policies"] = []string{"foo", "bar", "baz"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-24 22:12:52 +00:00
|
|
|
if resp.Data["error"] != "child policies must be subset of parent" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-03 18:32:17 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NonRoot_RootChild(t *testing.T) {
|
2016-08-05 22:56:22 +00:00
|
|
|
core, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
ps := core.policyStore
|
|
|
|
|
|
|
|
policy, _ := Parse(tokenCreationPolicy)
|
|
|
|
policy.Name = "test1"
|
|
|
|
if err := ps.SetPolicy(policy); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
testMakeToken(t, ts, root, "sudoClient", "", []string{"test1"})
|
2016-08-03 18:32:17 +00:00
|
|
|
|
2016-08-05 14:04:02 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2016-08-05 21:58:48 +00:00
|
|
|
req.ClientToken = "sudoClient"
|
2016-08-06 00:07:18 +00:00
|
|
|
req.MountPoint = "auth/token/"
|
2016-08-06 00:22:07 +00:00
|
|
|
req.Data["policies"] = []string{"root"}
|
2016-08-05 14:04:02 +00:00
|
|
|
|
2016-08-05 21:58:48 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
2016-08-03 18:32:17 +00:00
|
|
|
if err != logical.ErrInvalidRequest {
|
2016-08-06 00:22:07 +00:00
|
|
|
t.Fatalf("err: %v; resp: %#v", err, resp)
|
2016-08-06 00:07:18 +00:00
|
|
|
}
|
|
|
|
if resp == nil || resp.Data == nil {
|
|
|
|
t.Fatalf("expected a response")
|
2016-08-03 18:32:17 +00:00
|
|
|
}
|
2016-08-05 22:56:22 +00:00
|
|
|
if resp.Data["error"].(string) != "root tokens may not be created without parent token being root" {
|
2016-08-03 18:32:17 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-10 00:32:40 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_Root_RootChild_NoExpiry_Expiry(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"ttl": "5m",
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v; resp: %#v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil || resp.Auth == nil {
|
|
|
|
t.Fatalf("failed to create a root token using another root token")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"root"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: root; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
if resp.Auth.TTL.Seconds() != 300 {
|
|
|
|
t.Fatalf("bad: expected 300 second ttl, got %v", resp.Auth.TTL.Seconds())
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"ttl": "0",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-05 14:04:02 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_Root_RootChild(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
2016-08-06 00:22:07 +00:00
|
|
|
t.Fatalf("err: %v; resp: %#v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil || resp.Auth == nil {
|
|
|
|
t.Fatalf("failed to create a root token using another root token")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"root"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: root; actual: %s", resp.Auth.Policies)
|
2016-08-05 14:04:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 22:10:46 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_NonRoot_NoParent(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "client", "", []string{"foo"})
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = "client"
|
|
|
|
req.Data["no_parent"] = true
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-09-19 16:33:52 +00:00
|
|
|
if resp.Data["error"] != "root or sudo privileges required to create orphan token" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_Root_NoParent(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["no_parent"] = true
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
2015-11-03 20:10:46 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, _ := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if out.Parent != "" {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_PathBased_NoParent(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-11-03 20:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create-orphan")
|
2015-11-03 20:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
|
2015-03-24 22:10:46 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken == "" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:26:39 +00:00
|
|
|
out, _ := ts.Lookup(resp.Auth.ClientToken)
|
2015-03-24 22:10:46 +00:00
|
|
|
if out.Parent != "" {
|
|
|
|
t.Fatalf("bad: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_Metadata(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
2015-03-31 03:26:39 +00:00
|
|
|
meta := map[string]string{
|
2015-03-24 22:10:46 +00:00
|
|
|
"user": "armon",
|
|
|
|
"source": "github",
|
|
|
|
}
|
|
|
|
req.Data["meta"] = meta
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken == "" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:26:39 +00:00
|
|
|
out, _ := ts.Lookup(resp.Auth.ClientToken)
|
2015-03-24 22:10:46 +00:00
|
|
|
if !reflect.DeepEqual(out.Meta, meta) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", meta, out.Meta)
|
2015-03-24 22:10:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_CreateToken_Lease(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-03-24 22:10:46 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
req.Data["lease"] = "1h"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-03-31 03:26:39 +00:00
|
|
|
if resp.Auth.ClientToken == "" {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
2015-08-21 00:47:17 +00:00
|
|
|
if resp.Auth.TTL != time.Hour {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
2015-04-03 21:04:50 +00:00
|
|
|
if !resp.Auth.Renewable {
|
2015-03-24 22:10:46 +00:00
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-25 13:46:20 +00:00
|
|
|
func TestTokenStore_HandleRequest_CreateToken_TTL(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-09-25 13:46:20 +00:00
|
|
|
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
2015-09-25 13:46:20 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
req.Data["ttl"] = "1h"
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.TTL != time.Hour {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
if !resp.Auth.Renewable {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 22:30:09 +00:00
|
|
|
func TestTokenStore_HandleRequest_Revoke(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "child", "", []string{"root", "foo"})
|
|
|
|
testMakeToken(t, ts, "child", "sub-child", "", []string{"foo"})
|
2015-03-24 22:30:09 +00:00
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "revoke")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "child",
|
|
|
|
}
|
2015-03-24 22:30:09 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup("child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub-child should not exist
|
|
|
|
out, err = ts.Lookup("sub-child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_RevokeOrphan(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "child", "", []string{"root", "foo"})
|
|
|
|
testMakeToken(t, ts, "child", "sub-child", "", []string{"foo"})
|
2015-03-24 22:30:09 +00:00
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "revoke-orphan")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "child",
|
|
|
|
}
|
2015-09-16 13:22:15 +00:00
|
|
|
req.ClientToken = root
|
2015-03-24 22:30:09 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup("child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub-child should exist!
|
|
|
|
out, err = ts.Lookup("sub-child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out == nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 13:22:15 +00:00
|
|
|
func TestTokenStore_HandleRequest_RevokeOrphan_NonRoot(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
2015-12-30 19:30:02 +00:00
|
|
|
testMakeToken(t, ts, root, "child", "", []string{"foo"})
|
2015-09-16 13:22:15 +00:00
|
|
|
|
|
|
|
out, err := ts.Lookup("child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out == nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "revoke-orphan")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "child",
|
|
|
|
}
|
2015-09-16 13:22:15 +00:00
|
|
|
req.ClientToken = "child"
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != logical.ErrInvalidRequest {
|
|
|
|
t.Fatalf("did not get error when non-root revoking itself with orphan flag; resp is %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should still exist
|
|
|
|
out, err = ts.Lookup("child")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out == nil {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 22:39:33 +00:00
|
|
|
func TestTokenStore_HandleRequest_Lookup(t *testing.T) {
|
2016-01-09 02:21:02 +00:00
|
|
|
c, ts, _, root := TestCoreWithTokenStore(t)
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "lookup")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": root,
|
|
|
|
}
|
2015-03-24 22:39:33 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
exp := map[string]interface{}{
|
2016-05-11 20:51:18 +00:00
|
|
|
"id": root,
|
|
|
|
"accessor": resp.Data["accessor"].(string),
|
|
|
|
"policies": []string{"root"},
|
|
|
|
"path": "auth/token/root",
|
|
|
|
"meta": map[string]string(nil),
|
|
|
|
"display_name": "root",
|
|
|
|
"orphan": true,
|
|
|
|
"num_uses": 0,
|
|
|
|
"creation_ttl": int64(0),
|
|
|
|
"ttl": int64(0),
|
|
|
|
"explicit_max_ttl": int64(0),
|
2017-05-04 02:03:42 +00:00
|
|
|
"expire_time": nil,
|
2015-12-30 19:30:02 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 20:28:27 +00:00
|
|
|
if resp.Data["creation_time"].(int64) == 0 {
|
2015-12-30 19:30:02 +00:00
|
|
|
t.Fatalf("creation time was zero")
|
2015-03-31 19:50:07 +00:00
|
|
|
}
|
2015-09-18 20:33:52 +00:00
|
|
|
delete(resp.Data, "creation_time")
|
2015-12-30 19:30:02 +00:00
|
|
|
|
2015-03-31 19:50:07 +00:00
|
|
|
if !reflect.DeepEqual(resp.Data, exp) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", exp, resp.Data)
|
2015-11-09 18:19:59 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 19:30:02 +00:00
|
|
|
testCoreMakeToken(t, c, root, "client", "3600s", []string{"foo"})
|
2015-11-09 18:19:59 +00:00
|
|
|
|
2016-04-28 19:15:37 +00:00
|
|
|
// Test via GET
|
2016-08-24 19:59:43 +00:00
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "lookup")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "client",
|
|
|
|
}
|
2015-11-09 18:19:59 +00:00
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
exp = map[string]interface{}{
|
2016-05-11 20:51:18 +00:00
|
|
|
"id": "client",
|
|
|
|
"accessor": resp.Data["accessor"],
|
|
|
|
"policies": []string{"default", "foo"},
|
|
|
|
"path": "auth/token/create",
|
|
|
|
"meta": map[string]string(nil),
|
|
|
|
"display_name": "token",
|
|
|
|
"orphan": false,
|
|
|
|
"num_uses": 0,
|
|
|
|
"creation_ttl": int64(3600),
|
|
|
|
"ttl": int64(3600),
|
|
|
|
"explicit_max_ttl": int64(0),
|
2016-06-01 21:30:31 +00:00
|
|
|
"renewable": true,
|
2015-12-30 19:30:02 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 20:28:27 +00:00
|
|
|
if resp.Data["creation_time"].(int64) == 0 {
|
2015-12-30 19:30:02 +00:00
|
|
|
t.Fatalf("creation time was zero")
|
2015-11-09 18:19:59 +00:00
|
|
|
}
|
|
|
|
delete(resp.Data, "creation_time")
|
2017-05-04 02:03:42 +00:00
|
|
|
if resp.Data["issue_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatal("issue time is default time")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "issue_time")
|
|
|
|
if resp.Data["expire_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatal("expire time is default time")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "expire_time")
|
2015-12-30 19:30:02 +00:00
|
|
|
|
2016-02-01 16:16:32 +00:00
|
|
|
// Depending on timing of the test this may have ticked down, so accept 3599
|
|
|
|
if resp.Data["ttl"].(int64) == 3599 {
|
|
|
|
resp.Data["ttl"] = int64(3600)
|
|
|
|
}
|
|
|
|
|
2015-11-09 18:19:59 +00:00
|
|
|
if !reflect.DeepEqual(resp.Data, exp) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", exp, resp.Data)
|
2015-03-31 19:50:07 +00:00
|
|
|
}
|
2015-12-30 19:30:02 +00:00
|
|
|
|
2016-04-28 19:15:37 +00:00
|
|
|
// Test via POST
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "lookup")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "client",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
exp = map[string]interface{}{
|
2016-05-11 20:51:18 +00:00
|
|
|
"id": "client",
|
|
|
|
"accessor": resp.Data["accessor"],
|
|
|
|
"policies": []string{"default", "foo"},
|
|
|
|
"path": "auth/token/create",
|
|
|
|
"meta": map[string]string(nil),
|
|
|
|
"display_name": "token",
|
|
|
|
"orphan": false,
|
|
|
|
"num_uses": 0,
|
|
|
|
"creation_ttl": int64(3600),
|
|
|
|
"ttl": int64(3600),
|
|
|
|
"explicit_max_ttl": int64(0),
|
2016-06-01 21:30:31 +00:00
|
|
|
"renewable": true,
|
2016-04-28 19:15:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 20:28:27 +00:00
|
|
|
if resp.Data["creation_time"].(int64) == 0 {
|
2016-04-28 19:15:37 +00:00
|
|
|
t.Fatalf("creation time was zero")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "creation_time")
|
2017-05-04 02:03:42 +00:00
|
|
|
if resp.Data["issue_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatal("issue time is default time")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "issue_time")
|
|
|
|
if resp.Data["expire_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatal("expire time is default time")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "expire_time")
|
2016-04-28 19:15:37 +00:00
|
|
|
|
|
|
|
// Depending on timing of the test this may have ticked down, so accept 3599
|
|
|
|
if resp.Data["ttl"].(int64) == 3599 {
|
|
|
|
resp.Data["ttl"] = int64(3600)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Data, exp) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", exp, resp.Data)
|
2016-04-28 19:15:37 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 19:30:02 +00:00
|
|
|
// Test last_renewal_time functionality
|
2016-08-24 19:59:43 +00:00
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "renew")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "client",
|
|
|
|
}
|
2015-12-30 19:30:02 +00:00
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
2016-08-24 19:59:43 +00:00
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "lookup")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": "client",
|
|
|
|
}
|
2015-12-30 19:30:02 +00:00
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
2016-07-12 20:28:27 +00:00
|
|
|
if resp.Data["last_renewal_time"].(int64) == 0 {
|
2015-12-30 19:30:02 +00:00
|
|
|
t.Fatalf("last_renewal_time was zero")
|
|
|
|
}
|
2015-03-31 19:50:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_LookupSelf(t *testing.T) {
|
2017-05-04 02:03:42 +00:00
|
|
|
c, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
testCoreMakeToken(t, c, root, "client", "3600s", []string{"foo"})
|
|
|
|
|
2015-03-31 19:51:00 +00:00
|
|
|
req := logical.TestRequest(t, logical.ReadOperation, "lookup-self")
|
2017-05-04 02:03:42 +00:00
|
|
|
req.ClientToken = "client"
|
2015-03-31 19:50:07 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
exp := map[string]interface{}{
|
2017-05-04 02:03:42 +00:00
|
|
|
"id": "client",
|
2016-05-11 20:51:18 +00:00
|
|
|
"accessor": resp.Data["accessor"],
|
2017-05-04 02:03:42 +00:00
|
|
|
"policies": []string{"default", "foo"},
|
|
|
|
"path": "auth/token/create",
|
2016-05-11 20:51:18 +00:00
|
|
|
"meta": map[string]string(nil),
|
2017-05-04 02:03:42 +00:00
|
|
|
"display_name": "token",
|
|
|
|
"orphan": false,
|
|
|
|
"renewable": true,
|
2016-05-11 20:51:18 +00:00
|
|
|
"num_uses": 0,
|
2017-05-04 02:03:42 +00:00
|
|
|
"creation_ttl": int64(3600),
|
|
|
|
"ttl": int64(3600),
|
2016-05-11 20:51:18 +00:00
|
|
|
"explicit_max_ttl": int64(0),
|
2015-12-30 19:30:02 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 20:28:27 +00:00
|
|
|
if resp.Data["creation_time"].(int64) == 0 {
|
2015-12-30 19:30:02 +00:00
|
|
|
t.Fatalf("creation time was zero")
|
2015-03-24 22:39:33 +00:00
|
|
|
}
|
2015-09-18 20:33:52 +00:00
|
|
|
delete(resp.Data, "creation_time")
|
2017-05-04 02:03:42 +00:00
|
|
|
if resp.Data["issue_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatalf("creation time was zero")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "issue_time")
|
|
|
|
if resp.Data["expire_time"].(time.Time).IsZero() {
|
|
|
|
t.Fatalf("expire time was zero")
|
|
|
|
}
|
|
|
|
delete(resp.Data, "expire_time")
|
|
|
|
|
|
|
|
// Depending on timing of the test this may have ticked down, so accept 3599
|
|
|
|
if resp.Data["ttl"].(int64) == 3599 {
|
|
|
|
resp.Data["ttl"] = int64(3600)
|
|
|
|
}
|
2015-12-30 19:30:02 +00:00
|
|
|
|
2015-03-24 22:39:33 +00:00
|
|
|
if !reflect.DeepEqual(resp.Data, exp) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", exp, resp.Data)
|
2015-03-24 22:39:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-03 19:11:49 +00:00
|
|
|
func TestTokenStore_HandleRequest_Renew(t *testing.T) {
|
|
|
|
exp := mockExpiration(t)
|
|
|
|
ts := exp.tokenStore
|
|
|
|
|
|
|
|
// Create new token
|
2016-01-20 00:44:33 +00:00
|
|
|
root, err := ts.rootToken()
|
2015-04-03 19:11:49 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new token
|
|
|
|
auth := &logical.Auth{
|
|
|
|
ClientToken: root.ID,
|
2015-04-09 19:14:04 +00:00
|
|
|
LeaseOptions: logical.LeaseOptions{
|
2015-08-21 00:47:17 +00:00
|
|
|
TTL: time.Hour,
|
2015-04-09 19:14:04 +00:00
|
|
|
Renewable: true,
|
|
|
|
},
|
2015-04-03 19:11:49 +00:00
|
|
|
}
|
2015-04-09 21:23:37 +00:00
|
|
|
err = exp.RegisterAuth("auth/token/root", auth)
|
2015-04-03 19:11:49 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-04-11 04:21:06 +00:00
|
|
|
// Get the original expire time to compare
|
|
|
|
originalExpire := auth.ExpirationTime()
|
|
|
|
|
2016-07-07 21:44:14 +00:00
|
|
|
beforeRenew := time.Now()
|
2016-08-24 19:59:43 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "renew")
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"token": root.ID,
|
|
|
|
"increment": "3600s",
|
|
|
|
}
|
|
|
|
|
2015-06-17 22:58:20 +00:00
|
|
|
req.Data["increment"] = "3600s"
|
2015-04-03 19:11:49 +00:00
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2015-04-11 04:21:06 +00:00
|
|
|
|
|
|
|
// Get the new expire time
|
|
|
|
newExpire := resp.Auth.ExpirationTime()
|
2015-06-17 21:28:13 +00:00
|
|
|
if newExpire.Before(originalExpire) {
|
2015-10-07 16:49:13 +00:00
|
|
|
t.Fatalf("should expire later: %s %s", newExpire, originalExpire)
|
|
|
|
}
|
|
|
|
if newExpire.Before(beforeRenew.Add(time.Hour)) {
|
|
|
|
t.Fatalf("should have at least an hour: %s %s", newExpire, beforeRenew)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_HandleRequest_RenewSelf(t *testing.T) {
|
|
|
|
exp := mockExpiration(t)
|
|
|
|
ts := exp.tokenStore
|
|
|
|
|
|
|
|
// Create new token
|
2016-01-20 00:44:33 +00:00
|
|
|
root, err := ts.rootToken()
|
2015-10-07 16:49:13 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new token
|
|
|
|
auth := &logical.Auth{
|
|
|
|
ClientToken: root.ID,
|
|
|
|
LeaseOptions: logical.LeaseOptions{
|
|
|
|
TTL: time.Hour,
|
|
|
|
Renewable: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
err = exp.RegisterAuth("auth/token/root", auth)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the original expire time to compare
|
|
|
|
originalExpire := auth.ExpirationTime()
|
|
|
|
|
2016-07-07 21:44:14 +00:00
|
|
|
beforeRenew := time.Now()
|
2016-01-07 15:30:47 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "renew-self")
|
2015-10-07 16:49:13 +00:00
|
|
|
req.ClientToken = auth.ClientToken
|
|
|
|
req.Data["increment"] = "3600s"
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the new expire time
|
|
|
|
newExpire := resp.Auth.ExpirationTime()
|
|
|
|
if newExpire.Before(originalExpire) {
|
2015-06-17 21:28:13 +00:00
|
|
|
t.Fatalf("should expire later: %s %s", newExpire, originalExpire)
|
|
|
|
}
|
|
|
|
if newExpire.Before(beforeRenew.Add(time.Hour)) {
|
|
|
|
t.Fatalf("should have at least an hour: %s %s", newExpire, beforeRenew)
|
2015-04-03 19:11:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 19:13:09 +00:00
|
|
|
func TestTokenStore_RoleCRUD(t *testing.T) {
|
2016-03-09 16:59:54 +00:00
|
|
|
core, _, _, root := TestCoreWithTokenStore(t)
|
2016-02-29 19:13:09 +00:00
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
req := logical.TestRequest(t, logical.ReadOperation, "auth/token/roles/test")
|
2015-03-24 22:10:46 +00:00
|
|
|
req.ClientToken = root
|
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
resp, err := core.HandleRequest(req)
|
2015-03-24 22:10:46 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2016-02-29 19:13:09 +00:00
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("should not see a role")
|
2015-03-24 22:10:46 +00:00
|
|
|
}
|
2015-03-24 22:52:07 +00:00
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
// First test creation
|
|
|
|
req.Operation = logical.CreateOperation
|
2016-02-29 19:13:09 +00:00
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"orphan": true,
|
|
|
|
"period": "72h",
|
|
|
|
"allowed_policies": "test1,test2",
|
2016-03-01 20:30:37 +00:00
|
|
|
"path_suffix": "happenin",
|
2016-02-29 19:13:09 +00:00
|
|
|
}
|
2015-03-24 22:52:07 +00:00
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
resp, err = core.HandleRequest(req)
|
2015-03-24 22:52:07 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2016-02-29 19:13:09 +00:00
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Data = map[string]interface{}{}
|
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
resp, err = core.HandleRequest(req)
|
2016-02-29 19:13:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("got a nil response")
|
|
|
|
}
|
|
|
|
|
2016-04-14 11:56:09 +00:00
|
|
|
expected := map[string]interface{}{
|
2016-08-02 17:33:03 +00:00
|
|
|
"name": "test",
|
|
|
|
"orphan": true,
|
|
|
|
"period": int64(259200),
|
|
|
|
"allowed_policies": []string{"test1", "test2"},
|
|
|
|
"disallowed_policies": []string{},
|
|
|
|
"path_suffix": "happenin",
|
|
|
|
"explicit_max_ttl": int64(0),
|
|
|
|
"renewable": true,
|
2016-02-29 19:13:09 +00:00
|
|
|
}
|
|
|
|
|
2016-04-14 11:56:09 +00:00
|
|
|
if !reflect.DeepEqual(expected, resp.Data) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
|
2016-02-29 19:13:09 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 16:59:54 +00:00
|
|
|
// Now test updating; this should be set to an UpdateOperation
|
|
|
|
// automatically due to the existence check
|
|
|
|
req.Operation = logical.CreateOperation
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": "79h",
|
|
|
|
"allowed_policies": "test3",
|
|
|
|
"path_suffix": "happenin",
|
2016-06-08 19:17:22 +00:00
|
|
|
"renewable": false,
|
2016-03-09 16:59:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Data = map[string]interface{}{}
|
|
|
|
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("got a nil response")
|
|
|
|
}
|
|
|
|
|
2016-04-14 11:56:09 +00:00
|
|
|
expected = map[string]interface{}{
|
2016-08-02 17:33:03 +00:00
|
|
|
"name": "test",
|
|
|
|
"orphan": true,
|
|
|
|
"period": int64(284400),
|
|
|
|
"allowed_policies": []string{"test3"},
|
|
|
|
"disallowed_policies": []string{},
|
|
|
|
"path_suffix": "happenin",
|
|
|
|
"explicit_max_ttl": int64(0),
|
|
|
|
"renewable": false,
|
2016-05-11 20:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(expected, resp.Data) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
|
2016-05-11 20:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now set explicit max ttl and clear the period
|
|
|
|
req.Operation = logical.CreateOperation
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"explicit_max_ttl": "5",
|
|
|
|
"period": "0s",
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Data = map[string]interface{}{}
|
|
|
|
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("got a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
expected = map[string]interface{}{
|
2016-08-02 17:33:03 +00:00
|
|
|
"name": "test",
|
|
|
|
"orphan": true,
|
|
|
|
"explicit_max_ttl": int64(5),
|
|
|
|
"allowed_policies": []string{"test3"},
|
|
|
|
"disallowed_policies": []string{},
|
|
|
|
"path_suffix": "happenin",
|
|
|
|
"period": int64(0),
|
|
|
|
"renewable": false,
|
2016-03-09 16:59:54 +00:00
|
|
|
}
|
|
|
|
|
2016-04-14 11:56:09 +00:00
|
|
|
if !reflect.DeepEqual(expected, resp.Data) {
|
2016-07-07 21:44:14 +00:00
|
|
|
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
|
2016-03-09 16:59:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-29 19:13:09 +00:00
|
|
|
req.Operation = logical.ListOperation
|
2016-03-09 16:59:54 +00:00
|
|
|
req.Path = "auth/token/roles"
|
2016-02-29 19:13:09 +00:00
|
|
|
req.Data = map[string]interface{}{}
|
2016-03-09 16:59:54 +00:00
|
|
|
resp, err = core.HandleRequest(req)
|
2016-02-29 19:13:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("got a nil response")
|
|
|
|
}
|
|
|
|
keysInt, ok := resp.Data["keys"]
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("did not find keys in response")
|
|
|
|
}
|
|
|
|
keys, ok := keysInt.([]string)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("could not convert keys interface to key list")
|
|
|
|
}
|
|
|
|
if len(keys) != 1 {
|
|
|
|
t.Fatalf("unexpected number of keys: %d", len(keys))
|
|
|
|
}
|
|
|
|
if keys[0] != "test" {
|
|
|
|
t.Fatalf("expected \"test\", got \"%s\"", keys[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.DeleteOperation
|
2016-03-09 16:59:54 +00:00
|
|
|
req.Path = "auth/token/roles/test"
|
|
|
|
resp, err = core.HandleRequest(req)
|
2016-02-29 19:13:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
2016-03-09 16:59:54 +00:00
|
|
|
resp, err = core.HandleRequest(req)
|
2016-02-29 19:13:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
2015-03-24 22:52:07 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-01 17:33:35 +00:00
|
|
|
|
2017-01-18 02:34:14 +00:00
|
|
|
func TestTokenStore_RoleDisallowedPoliciesWithRoot(t *testing.T) {
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
// Don't set disallowed_policies. Verify that a read on the role does return a non-nil value.
|
|
|
|
roleReq := &logical.Request{
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Path: "roles/role1",
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"disallowed_policies": "root,testpolicy",
|
|
|
|
},
|
|
|
|
ClientToken: root,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
roleReq.Operation = logical.ReadOperation
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{"root", "testpolicy"}
|
|
|
|
if !reflect.DeepEqual(resp.Data["disallowed_policies"], expected) {
|
|
|
|
t.Fatalf("bad: expected: %#v, actual: %#v", expected, resp.Data["disallowed_policies"])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 19:21:15 +00:00
|
|
|
func TestTokenStore_RoleDisallowedPolicies(t *testing.T) {
|
|
|
|
var req *logical.Request
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
core, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
ps := core.policyStore
|
|
|
|
|
|
|
|
// Create 3 different policies
|
|
|
|
policy, _ := Parse(tokenCreationPolicy)
|
|
|
|
policy.Name = "test1"
|
|
|
|
if err := ps.SetPolicy(policy); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
policy, _ = Parse(tokenCreationPolicy)
|
|
|
|
policy.Name = "test2"
|
|
|
|
if err := ps.SetPolicy(policy); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
policy, _ = Parse(tokenCreationPolicy)
|
|
|
|
policy.Name = "test3"
|
|
|
|
if err := ps.SetPolicy(policy); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create roles with different disallowed_policies configuration
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "roles/test1")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"disallowed_policies": "test1",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "roles/test23")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"disallowed_policies": "test2,test3",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "roles/test123")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"disallowed_policies": "test1,test2,test3",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a token that has all the policies defined above
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"test1", "test2", "test3"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil || resp.Auth == nil {
|
|
|
|
t.Fatal("got nil response")
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: ClientToken; resp:%#v", resp)
|
|
|
|
}
|
|
|
|
parentToken := resp.Auth.ClientToken
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create/test1")
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil || resp != nil && !resp.IsError() {
|
2016-12-16 05:36:39 +00:00
|
|
|
t.Fatalf("expected an error response, got %#v", resp)
|
2016-08-02 19:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create/test23")
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil || resp != nil && !resp.IsError() {
|
|
|
|
t.Fatal("expected an error response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create/test123")
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil || resp != nil && !resp.IsError() {
|
|
|
|
t.Fatal("expected an error response")
|
|
|
|
}
|
|
|
|
|
2017-01-18 21:11:25 +00:00
|
|
|
// Disallowed should act as a blacklist so make sure we can still make
|
|
|
|
// something with other policies in the request
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create/test123")
|
|
|
|
req.Data["policies"] = []string{"foo", "bar"}
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || resp == nil || resp.IsError() {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
2016-08-02 19:21:15 +00:00
|
|
|
// Create a role to have 'default' policy disallowed
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "roles/default")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"disallowed_policies": "default",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create/default")
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil || resp != nil && !resp.IsError() {
|
|
|
|
t.Fatal("expected an error response")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 17:33:03 +00:00
|
|
|
func TestTokenStore_RoleAllowedPolicies(t *testing.T) {
|
2016-03-01 17:33:35 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "test1,test2",
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Data = map[string]interface{}{}
|
|
|
|
|
|
|
|
req.Path = "create/test"
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Data["policies"] = []string{"test2"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
2016-12-16 05:36:39 +00:00
|
|
|
|
|
|
|
// When allowed_policies is blank, should fall back to a subset of the parent policies
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data["policies"] = []string{"test1", "test2", "test3"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil || resp.Auth == nil {
|
|
|
|
t.Fatal("got nil response")
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: ClientToken; resp:%#v", resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"default", "test1", "test2", "test3"}) {
|
|
|
|
t.Fatalf("bad: %#v", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
parentToken := resp.Auth.ClientToken
|
|
|
|
|
|
|
|
req.Data = map[string]interface{}{}
|
|
|
|
req.ClientToken = parentToken
|
|
|
|
|
|
|
|
req.Path = "create/test"
|
|
|
|
req.Data["policies"] = []string{"foo"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Data["policies"] = []string{"test2"}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(req.Data, "policies")
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"default", "test1", "test2", "test3"}) {
|
|
|
|
t.Fatalf("bad: %#v", resp.Auth.Policies)
|
|
|
|
}
|
2016-03-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_RoleOrphan(t *testing.T) {
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"orphan": true,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Path = "create/test"
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.Parent != "" {
|
|
|
|
t.Fatalf("expected orphan token, but found a parent")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.HasPrefix(out.Path, "auth/token/create/test") {
|
|
|
|
t.Fatalf("expected role in path but did not find it")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 20:30:37 +00:00
|
|
|
func TestTokenStore_RolePathSuffix(t *testing.T) {
|
2016-03-01 17:33:35 +00:00
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
2016-03-01 20:30:37 +00:00
|
|
|
"path_suffix": "happenin",
|
2016-03-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Path = "create/test"
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, err := ts.Lookup(resp.Auth.ClientToken)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2016-03-01 20:30:37 +00:00
|
|
|
if out.Path != "auth/token/create/test/happenin" {
|
2016-03-01 17:33:35 +00:00
|
|
|
t.Fatalf("expected role in path but did not find it")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_RolePeriod(t *testing.T) {
|
|
|
|
core, _, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
2016-07-01 15:59:39 +00:00
|
|
|
core.defaultLeaseTTL = 10 * time.Second
|
|
|
|
core.maxLeaseTTL = 10 * time.Second
|
2016-03-01 17:33:35 +00:00
|
|
|
|
|
|
|
// Note: these requests are sent to Core since Core handles registration
|
|
|
|
// with the expiration manager and we need the storage to be consistent
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 300,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
// This first set of logic is to verify that a normal non-root token will
|
2016-07-01 15:59:39 +00:00
|
|
|
// be given a TTL of 10 seconds, and that renewing will not cause the TTL to
|
2016-03-01 17:33:35 +00:00
|
|
|
// increase since that's the configured backend max. Then we verify that
|
|
|
|
// increment works.
|
|
|
|
{
|
|
|
|
req.Path = "auth/token/create"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"default"},
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
2016-07-01 15:59:39 +00:00
|
|
|
if ttl > 10 {
|
2016-03-01 17:33:35 +00:00
|
|
|
t.Fatalf("TTL too large")
|
|
|
|
}
|
|
|
|
|
2016-07-01 15:59:39 +00:00
|
|
|
// Let the TTL go down a bit to 8 seconds
|
2016-03-01 17:33:35 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
2016-07-01 15:59:39 +00:00
|
|
|
if ttl > 8 {
|
2016-03-01 17:33:35 +00:00
|
|
|
t.Fatalf("TTL too large")
|
|
|
|
}
|
|
|
|
|
2016-07-01 15:59:39 +00:00
|
|
|
// Renewing should not have the increment increase since we've hit the
|
|
|
|
// max
|
2016-03-01 17:33:35 +00:00
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 1,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
2016-07-01 15:59:39 +00:00
|
|
|
if ttl > 8 {
|
2016-03-01 17:33:35 +00:00
|
|
|
t.Fatalf("TTL too large")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we create a token against the role. We should be able to renew;
|
|
|
|
// increment should be ignored as well.
|
|
|
|
{
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create/test"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-03-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 299 {
|
2016-06-08 18:49:48 +00:00
|
|
|
t.Fatalf("TTL too small (expected %d, got %d", 299, ttl)
|
2016-03-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Let the TTL go down a bit to 3 seconds
|
2016-08-16 20:47:46 +00:00
|
|
|
time.Sleep(3 * time.Second)
|
2016-03-01 17:33:35 +00:00
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 1,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 299 {
|
2016-06-08 18:49:48 +00:00
|
|
|
t.Fatalf("TTL too small (expected %d, got %d", 299, ttl)
|
2016-03-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-11 20:51:18 +00:00
|
|
|
|
|
|
|
func TestTokenStore_RoleExplicitMaxTTL(t *testing.T) {
|
|
|
|
core, _, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
core.defaultLeaseTTL = 5 * time.Second
|
|
|
|
core.maxLeaseTTL = 5 * time.Hour
|
|
|
|
|
|
|
|
// Note: these requests are sent to Core since Core handles registration
|
|
|
|
// with the expiration manager and we need the storage to be consistent
|
|
|
|
|
2016-05-11 22:46:55 +00:00
|
|
|
// Make sure we can't make it larger than the system/mount max; we should get a warning on role write and an error on token creation
|
2016-05-11 20:51:18 +00:00
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
2016-05-11 22:46:55 +00:00
|
|
|
"explicit_max_ttl": "100h",
|
2016-05-11 20:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2016-05-11 22:46:55 +00:00
|
|
|
if resp == nil {
|
|
|
|
t.Fatalf("expected a warning")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create/test"
|
|
|
|
resp, err = core.HandleRequest(req)
|
2016-06-08 19:25:17 +00:00
|
|
|
if err != nil {
|
2016-05-11 22:46:55 +00:00
|
|
|
t.Fatalf("expected an error")
|
|
|
|
}
|
2016-06-08 19:25:17 +00:00
|
|
|
if len(resp.Warnings()) == 0 {
|
|
|
|
t.Fatalf("expected a warning")
|
|
|
|
}
|
2016-05-11 22:46:55 +00:00
|
|
|
|
|
|
|
// Reset to a good explicit max
|
|
|
|
req = logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
2016-07-01 15:37:27 +00:00
|
|
|
"explicit_max_ttl": "10s",
|
2016-05-11 22:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
2016-05-11 20:51:18 +00:00
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
// This first set of logic is to verify that a normal non-root token will
|
|
|
|
// be given a TTL of 5 seconds, and that renewing will cause the TTL to
|
|
|
|
// increase
|
|
|
|
{
|
|
|
|
req.Path = "auth/token/create"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"default"},
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl > 5 {
|
|
|
|
t.Fatalf("TTL too large")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let the TTL go down a bit to 3 seconds
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 4 {
|
|
|
|
t.Fatalf("TTL too small after renewal")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we create a token against the role. After renew our max should still
|
|
|
|
// be the same.
|
|
|
|
{
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create/test"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-05-11 20:51:18 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
2016-07-01 15:37:27 +00:00
|
|
|
if ttl > 10 {
|
2016-05-11 20:51:18 +00:00
|
|
|
t.Fatalf("TTL too big")
|
|
|
|
}
|
|
|
|
maxTTL := resp.Data["explicit_max_ttl"].(int64)
|
2016-07-01 15:37:27 +00:00
|
|
|
if maxTTL != 10 {
|
2016-05-11 20:51:18 +00:00
|
|
|
t.Fatalf("expected 6 for explicit max TTL, got %d", maxTTL)
|
|
|
|
}
|
|
|
|
|
2016-07-01 15:37:27 +00:00
|
|
|
// Let the TTL go down a bit to ~7 seconds (8 against explicit max)
|
2016-05-11 20:51:18 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 300,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
2016-07-01 15:37:27 +00:00
|
|
|
if ttl > 8 {
|
2016-05-11 20:51:18 +00:00
|
|
|
t.Fatalf("TTL too big")
|
|
|
|
}
|
|
|
|
|
2016-07-01 15:37:27 +00:00
|
|
|
// Let the TTL go down a bit more to ~5 seconds (6 against explicit max)
|
2016-05-11 20:51:18 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 300,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
2016-07-01 15:37:27 +00:00
|
|
|
if ttl > 6 {
|
2016-05-11 20:51:18 +00:00
|
|
|
t.Fatalf("TTL too big")
|
|
|
|
}
|
|
|
|
|
|
|
|
// It should expire
|
2016-07-01 15:37:27 +00:00
|
|
|
time.Sleep(8 * time.Second)
|
2016-05-11 20:51:18 +00:00
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 300,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-13 18:03:22 +00:00
|
|
|
|
|
|
|
func TestTokenStore_Periodic(t *testing.T) {
|
|
|
|
core, _, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
core.defaultLeaseTTL = 10 * time.Second
|
|
|
|
core.maxLeaseTTL = 10 * time.Second
|
|
|
|
|
|
|
|
// Note: these requests are sent to Core since Core handles registration
|
|
|
|
// with the expiration manager and we need the storage to be consistent
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test")
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 300,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected a nil response")
|
|
|
|
}
|
|
|
|
|
|
|
|
// First make one directly and verify on renew it uses the period.
|
|
|
|
{
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 299 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL too small (expected %d, got %d)", 299, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 11:17:14 +00:00
|
|
|
// Let the TTL go down a bit
|
2016-08-13 18:03:22 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 1,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 299 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL too small (expected %d, got %d)", 299, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the same with an explicit max TTL
|
|
|
|
{
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 300,
|
|
|
|
"explicit_max_ttl": 150,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 149 || ttl > 150 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL bad (expected %d, got %d)", 149, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 11:17:14 +00:00
|
|
|
// Let the TTL go down a bit
|
2016-08-13 18:03:22 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 76,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 140 || ttl > 150 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL bad (expected around %d, got %d)", 145, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we create a token against the role and also set the te value
|
2016-08-13 19:45:13 +00:00
|
|
|
// directly. We should use the smaller of the two and be able to renew;
|
|
|
|
// increment should be ignored as well.
|
2016-08-13 18:03:22 +00:00
|
|
|
{
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create/test"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 150,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 149 || ttl > 150 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL bad (expected %d, got %d)", 149, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 11:17:14 +00:00
|
|
|
// Let the TTL go down a bit
|
2016-08-13 18:03:22 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 1,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 149 {
|
2016-08-14 11:17:14 +00:00
|
|
|
t.Fatalf("TTL bad (expected %d, got %d)", 149, ttl)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now do the same, also using an explicit max in the role
|
|
|
|
{
|
|
|
|
req.Path = "auth/token/roles/test"
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 300,
|
|
|
|
"explicit_max_ttl": 150,
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = root
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/create/test"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"period": 150,
|
|
|
|
"explicit_max_ttl": 130,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
if resp == nil {
|
|
|
|
t.Fatal("response was nil")
|
|
|
|
}
|
|
|
|
if resp.Auth == nil {
|
2016-12-21 18:08:27 +00:00
|
|
|
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
2016-08-14 11:17:14 +00:00
|
|
|
}
|
|
|
|
if resp.Auth.ClientToken == "" {
|
|
|
|
t.Fatalf("bad: %#v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.ClientToken = resp.Auth.ClientToken
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl := resp.Data["ttl"].(int64)
|
|
|
|
if ttl < 129 || ttl > 130 {
|
|
|
|
t.Fatalf("TTL bad (expected %d, got %d)", 129, ttl)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let the TTL go down a bit
|
|
|
|
time.Sleep(4 * time.Second)
|
|
|
|
|
|
|
|
req.Operation = logical.UpdateOperation
|
|
|
|
req.Path = "auth/token/renew-self"
|
|
|
|
req.Data = map[string]interface{}{
|
|
|
|
"increment": 1,
|
|
|
|
}
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Operation = logical.ReadOperation
|
|
|
|
req.Path = "auth/token/lookup-self"
|
|
|
|
resp, err = core.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
ttl = resp.Data["ttl"].(int64)
|
|
|
|
if ttl > 127 {
|
|
|
|
t.Fatalf("TTL bad (expected < %d, got %d)", 128, ttl)
|
2016-08-13 18:03:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-16 05:36:39 +00:00
|
|
|
|
|
|
|
func TestTokenStore_NoDefaultPolicy(t *testing.T) {
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
core, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
ps := core.policyStore
|
|
|
|
policy, _ := Parse(tokenCreationPolicy)
|
|
|
|
policy.Name = "policy1"
|
|
|
|
if err := ps.SetPolicy(policy); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Root token creates a token with desired policy. The created token
|
|
|
|
// should also have 'default' attached to it.
|
|
|
|
tokenData := map[string]interface{}{
|
|
|
|
"policies": []string{"policy1"},
|
|
|
|
}
|
|
|
|
tokenReq := &logical.Request{
|
|
|
|
Path: "create",
|
|
|
|
ClientToken: root,
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Data: tokenData,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"default", "policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy, default]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
newToken := resp.Auth.ClientToken
|
|
|
|
|
|
|
|
// Root token creates a token with desired policy, but also requests
|
|
|
|
// that the token to not have 'default' policy. The resulting token
|
|
|
|
// should not have 'default' policy on it.
|
|
|
|
tokenData["no_default_policy"] = true
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A non-root token which has 'default' policy attached requests for a
|
|
|
|
// child token. Child token should also have 'default' policy attached.
|
|
|
|
tokenReq.ClientToken = newToken
|
|
|
|
tokenReq.Data = nil
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"default", "policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [default policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A non-root token which has 'default' policy attached, request for a
|
|
|
|
// child token to not have 'default' policy while not sending a list
|
|
|
|
tokenReq.Data = map[string]interface{}{
|
|
|
|
"no_default_policy": true,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// In this case "default" shouldn't exist because we are not inheriting
|
|
|
|
// parent policies
|
|
|
|
tokenReq.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"policy1"},
|
|
|
|
"no_default_policy": true,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a non-root token which does not have 'default' policy
|
|
|
|
// attached
|
|
|
|
newToken = resp.Auth.ClientToken
|
|
|
|
tokenReq.Data = nil
|
|
|
|
tokenReq.ClientToken = newToken
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
roleReq := &logical.Request{
|
|
|
|
ClientToken: root,
|
|
|
|
Path: "roles/role1",
|
|
|
|
Operation: logical.CreateOperation,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
tokenReq.Path = "create/role1"
|
|
|
|
tokenReq.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"policy1"},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If 'allowed_policies' in role does not have 'default' in it, the
|
|
|
|
// tokens generated using that role should still have the 'default' policy
|
|
|
|
// attached to them.
|
|
|
|
roleReq.Operation = logical.UpdateOperation
|
|
|
|
roleReq.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "policy1",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"default", "policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [default policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If 'allowed_policies' in role does not have 'default' in it, the
|
|
|
|
// tokens generated using that role should not have 'default' policy
|
|
|
|
// attached to them if disallowed_policies contains "default"
|
|
|
|
roleReq.Operation = logical.UpdateOperation
|
|
|
|
roleReq.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "policy1",
|
|
|
|
"disallowed_policies": "default",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
roleReq.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "",
|
|
|
|
"disallowed_policies": "default",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, []string{"policy1"}) {
|
|
|
|
t.Fatalf("bad: policies: expected: [policy1]; actual: %s", resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that if default is in both allowed and disallowed, disallowed wins
|
|
|
|
roleReq.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "default",
|
|
|
|
"disallowed_policies": "default",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(tokenReq.Data, "policies")
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err == nil || (resp != nil && !resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenStore_AllowedDisallowedPolicies(t *testing.T) {
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
roleReq := &logical.Request{
|
|
|
|
ClientToken: root,
|
|
|
|
Path: "roles/role1",
|
|
|
|
Operation: logical.CreateOperation,
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"allowed_policies": "allowed1,allowed2",
|
|
|
|
"disallowed_policies": "disallowed1,disallowed2",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenReq := &logical.Request{
|
|
|
|
Path: "create/role1",
|
|
|
|
ClientToken: root,
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"policies": []string{"allowed1"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{"allowed1", "default"}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, expected) {
|
|
|
|
t.Fatalf("bad: expected:%#v actual:%#v", expected, resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try again with automatic default adding turned off
|
|
|
|
tokenReq = &logical.Request{
|
|
|
|
Path: "create/role1",
|
|
|
|
ClientToken: root,
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"policies": []string{"allowed1"},
|
|
|
|
"no_default_policy": true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected = []string{"allowed1"}
|
|
|
|
if !reflect.DeepEqual(resp.Auth.Policies, expected) {
|
|
|
|
t.Fatalf("bad: expected:%#v actual:%#v", expected, resp.Auth.Policies)
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenReq.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"disallowed1"},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected an error")
|
|
|
|
}
|
|
|
|
|
|
|
|
roleReq.Operation = logical.UpdateOperation
|
|
|
|
roleReq.Data = map[string]interface{}{
|
|
|
|
"allowed_policies": "allowed1,common",
|
|
|
|
"disallowed_policies": "disallowed1,common",
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(roleReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err: %v, resp: %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenReq.Data = map[string]interface{}{
|
|
|
|
"policies": []string{"allowed1", "common"},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected an error")
|
|
|
|
}
|
|
|
|
}
|
2016-12-16 18:11:55 +00:00
|
|
|
|
|
|
|
// Issue 2189
|
|
|
|
func TestTokenStore_RevokeUseCountToken(t *testing.T) {
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
cubbyFuncLock := &sync.RWMutex{}
|
|
|
|
cubbyFuncLock.Lock()
|
|
|
|
|
|
|
|
exp := mockExpiration(t)
|
|
|
|
ts := exp.tokenStore
|
|
|
|
root, _ := exp.tokenStore.rootToken()
|
|
|
|
|
|
|
|
tokenReq := &logical.Request{
|
|
|
|
Path: "create",
|
|
|
|
ClientToken: root.ID,
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"num_uses": 1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
tut := resp.Auth.ClientToken
|
|
|
|
saltTut := ts.SaltID(tut)
|
|
|
|
te, err := ts.lookupSalted(saltTut, false)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("nil entry")
|
|
|
|
}
|
|
|
|
if te.NumUses != 1 {
|
|
|
|
t.Fatalf("bad: %d", te.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
te, err = ts.UseToken(te)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("nil entry")
|
|
|
|
}
|
|
|
|
if te.NumUses != tokenRevocationDeferred {
|
|
|
|
t.Fatalf("bad: %d", te.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should return no entry because it's tainted
|
|
|
|
te, err = ts.lookupSalted(saltTut, false)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te != nil {
|
|
|
|
t.Fatalf("%#v", te)
|
|
|
|
}
|
|
|
|
|
|
|
|
// But it should show up in an API lookup call
|
|
|
|
req := &logical.Request{
|
|
|
|
Path: "lookup-self",
|
|
|
|
ClientToken: tut,
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if resp == nil || resp.Data == nil || resp.Data["num_uses"] == nil {
|
|
|
|
t.Fatal("nil resp or data")
|
|
|
|
}
|
|
|
|
if resp.Data["num_uses"].(int) != -1 {
|
|
|
|
t.Fatalf("bad: %v", resp.Data["num_uses"])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should return tainted entries
|
|
|
|
te, err = ts.lookupSalted(saltTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("nil entry")
|
|
|
|
}
|
|
|
|
if te.NumUses != tokenRevocationDeferred {
|
|
|
|
t.Fatalf("bad: %d", te.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
origDestroyCubbyhole := ts.cubbyholeDestroyer
|
|
|
|
|
|
|
|
ts.cubbyholeDestroyer = func(*TokenStore, string) error {
|
|
|
|
return fmt.Errorf("keep it frosty")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ts.revokeSalted(saltTut)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected err")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since revocation failed we should see the tokenRevocationFailed canary value
|
|
|
|
te, err = ts.lookupSalted(saltTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("nil entry")
|
|
|
|
}
|
|
|
|
if te.NumUses != tokenRevocationFailed {
|
|
|
|
t.Fatalf("bad: %d", te.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the race condition situation by making the process sleep
|
|
|
|
ts.cubbyholeDestroyer = func(*TokenStore, string) error {
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
return fmt.Errorf("keep it frosty")
|
|
|
|
}
|
|
|
|
cubbyFuncLock.Unlock()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
cubbyFuncLock.RLock()
|
|
|
|
err := ts.revokeSalted(saltTut)
|
|
|
|
cubbyFuncLock.RUnlock()
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Give time for the function to start and grab locks
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
te, err = ts.lookupSalted(saltTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("nil entry")
|
|
|
|
}
|
|
|
|
if te.NumUses != tokenRevocationInProgress {
|
|
|
|
t.Fatalf("bad: %d", te.NumUses)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let things catch up
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
// Put back to normal
|
|
|
|
cubbyFuncLock.Lock()
|
|
|
|
defer cubbyFuncLock.Unlock()
|
|
|
|
ts.cubbyholeDestroyer = origDestroyCubbyhole
|
|
|
|
|
|
|
|
err = ts.revokeSalted(saltTut)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
te, err = ts.lookupSalted(saltTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if te != nil {
|
|
|
|
t.Fatal("found entry")
|
|
|
|
}
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
|
|
|
// Create a token, delete the token entry while leaking accessors, invoke tidy
|
|
|
|
// and check if the dangling accessor entry is getting removed
|
|
|
|
func TestTokenStore_HandleTidyCase1(t *testing.T) {
|
|
|
|
var resp *logical.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
_, ts, _, root := TestCoreWithTokenStore(t)
|
|
|
|
|
|
|
|
// List the number of accessors. Since there is only root token
|
|
|
|
// present, the list operation should return only one key.
|
|
|
|
accessorListReq := &logical.Request{
|
|
|
|
Operation: logical.ListOperation,
|
|
|
|
Path: "accessors",
|
|
|
|
ClientToken: root,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(accessorListReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
numberOfAccessors := len(resp.Data["keys"].([]string))
|
|
|
|
if numberOfAccessors != 1 {
|
|
|
|
t.Fatalf("bad: number of accessors. Expected: 1, Actual: %d", numberOfAccessors)
|
|
|
|
}
|
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
for i := 1; i <= 100; i++ {
|
|
|
|
// Create a regular token
|
|
|
|
tokenReq := &logical.Request{
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
Path: "create",
|
|
|
|
ClientToken: root,
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"policies": []string{"policy1"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tokenReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
tut := resp.Auth.ClientToken
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Creation of another token should end up with incrementing
|
|
|
|
// the number of accessors
|
|
|
|
// the storage
|
|
|
|
resp, err = ts.HandleRequest(accessorListReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
numberOfAccessors = len(resp.Data["keys"].([]string))
|
|
|
|
if numberOfAccessors != i+1 {
|
|
|
|
t.Fatalf("bad: number of accessors. Expected: %d, Actual: %d", i+1, numberOfAccessors)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Revoke the token while leaking other items associated with the
|
|
|
|
// token. Do this by doing what revokeSalted used to do before it was
|
|
|
|
// fixed, i.e., by deleting the storage entry for token and its
|
|
|
|
// cubbyhole and by not deleting its secondary index, its accessor and
|
|
|
|
// associated leases.
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
saltedTut := ts.SaltID(tut)
|
|
|
|
_, err = ts.lookupSalted(saltedTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to lookup token: %v", err)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Destroy the token index
|
|
|
|
path := lookupPrefix + saltedTut
|
|
|
|
if ts.view.Delete(path); err != nil {
|
|
|
|
t.Fatalf("failed to delete token entry: %v", err)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Destroy the cubby space
|
|
|
|
err = ts.destroyCubbyhole(saltedTut)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to destroyCubbyhole: %v", err)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Leaking of accessor should have resulted in no change to the number
|
|
|
|
// of accessors
|
|
|
|
resp, err = ts.HandleRequest(accessorListReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
numberOfAccessors = len(resp.Data["keys"].([]string))
|
|
|
|
if numberOfAccessors != i+1 {
|
|
|
|
t.Fatalf("bad: number of accessors. Expected: %d, Actual: %d", i+1, numberOfAccessors)
|
|
|
|
}
|
2016-12-16 20:29:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tidyReq := &logical.Request{
|
|
|
|
Path: "tidy",
|
|
|
|
Operation: logical.UpdateOperation,
|
|
|
|
ClientToken: root,
|
|
|
|
}
|
|
|
|
resp, err = ts.HandleRequest(tidyReq)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if resp != nil && resp.IsError() {
|
|
|
|
t.Fatalf("resp: %#v", resp)
|
|
|
|
}
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
2016-12-16 20:40:34 +00:00
|
|
|
// Tidy should have removed all the dangling accessor entries
|
2016-12-16 20:29:27 +00:00
|
|
|
resp, err = ts.HandleRequest(accessorListReq)
|
|
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
|
|
t.Fatalf("err:%v resp:%v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
numberOfAccessors = len(resp.Data["keys"].([]string))
|
|
|
|
if numberOfAccessors != 1 {
|
|
|
|
t.Fatalf("bad: number of accessors. Expected: 1, Actual: %d", numberOfAccessors)
|
|
|
|
}
|
|
|
|
}
|
2016-12-16 21:46:29 +00:00
|
|
|
|
|
|
|
func TestTokenStore_TidyLeaseRevocation(t *testing.T) {
|
|
|
|
exp := mockExpiration(t)
|
|
|
|
ts := exp.tokenStore
|
|
|
|
|
|
|
|
noop := &NoopBackend{}
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "logical/")
|
|
|
|
meUUID, err := uuid.GenerateUUID()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
exp.router.Mount(noop, "prod/aws/", &MountEntry{UUID: meUUID}, view)
|
|
|
|
|
|
|
|
// Create new token
|
|
|
|
root, err := ts.rootToken()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
req := logical.TestRequest(t, logical.UpdateOperation, "create")
|
|
|
|
req.ClientToken = root.ID
|
|
|
|
req.Data["policies"] = []string{"default"}
|
|
|
|
|
|
|
|
resp, err := ts.HandleRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v %v", err, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new token
|
|
|
|
auth := &logical.Auth{
|
|
|
|
ClientToken: resp.Auth.ClientToken,
|
|
|
|
LeaseOptions: logical.LeaseOptions{
|
|
|
|
TTL: time.Hour,
|
|
|
|
Renewable: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
err = exp.RegisterAuth("auth/token/create", auth)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tut := resp.Auth.ClientToken
|
|
|
|
|
|
|
|
req = &logical.Request{
|
|
|
|
Path: "prod/aws/foo",
|
|
|
|
ClientToken: tut,
|
|
|
|
}
|
|
|
|
resp = &logical.Response{
|
|
|
|
Secret: &logical.Secret{
|
|
|
|
LeaseOptions: logical.LeaseOptions{
|
|
|
|
TTL: time.Hour,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
leases := []string{}
|
|
|
|
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
leaseId, err := exp.Register(req, resp)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
leases = append(leases, leaseId)
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(leases)
|
|
|
|
|
|
|
|
storedLeases, err := exp.lookupByToken(tut)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
sort.Strings(storedLeases)
|
|
|
|
if !reflect.DeepEqual(leases, storedLeases) {
|
|
|
|
t.Fatalf("bad: %#v vs %#v", leases, storedLeases)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now, delete the token entry. The leases should still exist.
|
|
|
|
saltedTut := ts.SaltID(tut)
|
|
|
|
te, err := ts.lookupSalted(saltedTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to lookup token: %v", err)
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
t.Fatal("got nil token entry")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Destroy the token index
|
|
|
|
path := lookupPrefix + saltedTut
|
|
|
|
if ts.view.Delete(path); err != nil {
|
|
|
|
t.Fatalf("failed to delete token entry: %v", err)
|
|
|
|
}
|
|
|
|
te, err = ts.lookupSalted(saltedTut, true)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to lookup token: %v", err)
|
|
|
|
}
|
|
|
|
if te != nil {
|
|
|
|
t.Fatal("got token entry")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify leases still exist
|
|
|
|
storedLeases, err = exp.lookupByToken(tut)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
sort.Strings(storedLeases)
|
|
|
|
if !reflect.DeepEqual(leases, storedLeases) {
|
|
|
|
t.Fatalf("bad: %#v vs %#v", leases, storedLeases)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call tidy
|
|
|
|
ts.handleTidy(nil, nil)
|
|
|
|
|
|
|
|
// Verify leases are gone
|
|
|
|
storedLeases, err = exp.lookupByToken(tut)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(storedLeases) > 0 {
|
|
|
|
t.Fatal("found leases")
|
|
|
|
}
|
|
|
|
}
|