1package token
2
3import (
4	"encoding/base64"
5	"reflect"
6	"sort"
7	"strings"
8	"testing"
9	"time"
10
11	"github.com/go-test/deep"
12	"github.com/hashicorp/vault/api"
13	credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
14	credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
15	"github.com/hashicorp/vault/helper/jsonutil"
16	vaulthttp "github.com/hashicorp/vault/http"
17	"github.com/hashicorp/vault/logical"
18	"github.com/hashicorp/vault/vault"
19)
20
21func TestTokenStore_TokenInvalidEntityID(t *testing.T) {
22	coreConfig := &vault.CoreConfig{
23		CredentialBackends: map[string]logical.Factory{
24			"userpass": credUserpass.Factory,
25		},
26	}
27	cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
28		HandlerFunc: vaulthttp.Handler,
29	})
30	cluster.Start()
31	defer cluster.Cleanup()
32
33	core := cluster.Cores[0].Core
34	vault.TestWaitActive(t, core)
35	client := cluster.Cores[0].Client
36
37	// Enable userpass auth
38	err := client.Sys().EnableAuthWithOptions("userpass", &api.EnableAuthOptions{
39		Type: "userpass",
40	})
41	if err != nil {
42		t.Fatal(err)
43	}
44
45	// Add a user to userpass backend
46	_, err = client.Logical().Write("auth/userpass/users/testuser", map[string]interface{}{
47		"password": "testpassword",
48	})
49	if err != nil {
50		t.Fatal(err)
51	}
52
53	secret, err := client.Logical().Write("auth/userpass/login/testuser", map[string]interface{}{
54		"password": "testpassword",
55	})
56	if err != nil {
57		t.Fatal(err)
58	}
59	clientToken := secret.Auth.ClientToken
60
61	secret, err = client.Logical().Write("auth/token/lookup", map[string]interface{}{
62		"token": clientToken,
63	})
64	if err != nil {
65		t.Fatal(err)
66	}
67
68	entityID := secret.Data["entity_id"].(string)
69
70	_, err = client.Logical().Delete("identity/entity/id/" + entityID)
71	if err != nil {
72		t.Fatal(err)
73	}
74
75	client.SetToken(clientToken)
76
77	secret, err = client.Logical().Write("auth/token/lookup-self", nil)
78	if err == nil {
79		t.Fatalf("expected error due to token being invalid when its entity is invalid")
80	}
81}
82
83func TestTokenStore_IdentityPolicies(t *testing.T) {
84	coreConfig := &vault.CoreConfig{
85		CredentialBackends: map[string]logical.Factory{
86			"ldap": credLdap.Factory,
87		},
88		EnableRaw: true,
89	}
90	cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
91		HandlerFunc: vaulthttp.Handler,
92	})
93	cluster.Start()
94	defer cluster.Cleanup()
95
96	core := cluster.Cores[0].Core
97	vault.TestWaitActive(t, core)
98	client := cluster.Cores[0].Client
99
100	// Enable LDAP auth
101	err := client.Sys().EnableAuthWithOptions("ldap", &api.EnableAuthOptions{
102		Type: "ldap",
103	})
104	if err != nil {
105		t.Fatal(err)
106	}
107
108	// Configure LDAP auth
109	_, err = client.Logical().Write("auth/ldap/config", map[string]interface{}{
110		"url":      "ldap://ldap.forumsys.com",
111		"userattr": "uid",
112		"userdn":   "dc=example,dc=com",
113		"groupdn":  "dc=example,dc=com",
114		"binddn":   "cn=read-only-admin,dc=example,dc=com",
115	})
116	if err != nil {
117		t.Fatal(err)
118	}
119
120	// Create group in LDAP auth
121	_, err = client.Logical().Write("auth/ldap/groups/testgroup1", map[string]interface{}{
122		"policies": "testgroup1-policy",
123	})
124	if err != nil {
125		t.Fatal(err)
126	}
127
128	// Create user in LDAP auth. We add two groups, but we should filter out
129	// the ones that don't match aliases later (we will check for this)
130	_, err = client.Logical().Write("auth/ldap/users/tesla", map[string]interface{}{
131		"policies": "default",
132		"groups":   "testgroup1,testgroup2",
133	})
134	if err != nil {
135		t.Fatal(err)
136	}
137
138	// Login using LDAP
139	secret, err := client.Logical().Write("auth/ldap/login/tesla", map[string]interface{}{
140		"password": "password",
141	})
142	if err != nil {
143		t.Fatal(err)
144	}
145	ldapClientToken := secret.Auth.ClientToken
146
147	expectedPolicies := []string{
148		"default",
149		"testgroup1-policy",
150	}
151	if !reflect.DeepEqual(expectedPolicies, secret.Auth.Policies) {
152		t.Fatalf("bad: identity policies; expected: %#v\nactual: %#v", expectedPolicies, secret.Auth.Policies)
153	}
154
155	// At this point there shouldn't be any identity policy on the token
156	secret, err = client.Logical().Write("auth/token/lookup", map[string]interface{}{
157		"token": ldapClientToken,
158	})
159	if err != nil {
160		t.Fatal(err)
161	}
162	_, ok := secret.Data["identity_policies"]
163	if ok {
164		t.Fatalf("identity_policies should not have been set")
165	}
166
167	// Extract the entity ID of the token and set some policies on the entity
168	entityID := secret.Data["entity_id"].(string)
169	_, err = client.Logical().Write("identity/entity/id/"+entityID, map[string]interface{}{
170		"policies": []string{
171			"entity_policy_1",
172			"entity_policy_2",
173		},
174	})
175	if err != nil {
176		t.Fatal(err)
177	}
178
179	// Lookup the token and expect entity policies on the token
180	secret, err = client.Logical().Write("auth/token/lookup", map[string]interface{}{
181		"token": ldapClientToken,
182	})
183	if err != nil {
184		t.Fatal(err)
185	}
186	identityPolicies := secret.Data["identity_policies"].([]interface{})
187	var actualPolicies []string
188	for _, item := range identityPolicies {
189		actualPolicies = append(actualPolicies, item.(string))
190	}
191	sort.Strings(actualPolicies)
192
193	expectedPolicies = []string{
194		"entity_policy_1",
195		"entity_policy_2",
196	}
197	sort.Strings(expectedPolicies)
198	if !reflect.DeepEqual(expectedPolicies, actualPolicies) {
199		t.Fatalf("bad: identity policies; expected: %#v\nactual: %#v", expectedPolicies, actualPolicies)
200	}
201
202	// Create identity group and add entity as its member
203	secret, err = client.Logical().Write("identity/group", map[string]interface{}{
204		"policies": []string{
205			"group_policy_1",
206			"group_policy_2",
207		},
208		"member_entity_ids": []string{
209			entityID,
210		},
211	})
212	if err != nil {
213		t.Fatal(err)
214	}
215
216	// Lookup token and expect both entity and group policies on the token
217	secret, err = client.Logical().Write("auth/token/lookup", map[string]interface{}{
218		"token": ldapClientToken,
219	})
220	if err != nil {
221		t.Fatal(err)
222	}
223	identityPolicies = secret.Data["identity_policies"].([]interface{})
224	actualPolicies = nil
225	for _, item := range identityPolicies {
226		actualPolicies = append(actualPolicies, item.(string))
227	}
228	sort.Strings(actualPolicies)
229
230	expectedPolicies = []string{
231		"entity_policy_1",
232		"entity_policy_2",
233		"group_policy_1",
234		"group_policy_2",
235	}
236	sort.Strings(expectedPolicies)
237	if !reflect.DeepEqual(expectedPolicies, actualPolicies) {
238		t.Fatalf("bad: identity policies; expected: %#v\nactual: %#v", expectedPolicies, actualPolicies)
239	}
240
241	// Create an external group and renew the token. This should add external
242	// group policies to the token.
243	auths, err := client.Sys().ListAuth()
244	if err != nil {
245		t.Fatal(err)
246	}
247	ldapMountAccessor1 := auths["ldap/"].Accessor
248
249	// Create an external group
250	secret, err = client.Logical().Write("identity/group", map[string]interface{}{
251		"type": "external",
252		"policies": []string{
253			"external_group_policy_1",
254			"external_group_policy_2",
255		},
256	})
257	if err != nil {
258		t.Fatal(err)
259	}
260	ldapExtGroupID1 := secret.Data["id"].(string)
261
262	// Associate a group from LDAP auth as a group-alias in the external group
263	_, err = client.Logical().Write("identity/group-alias", map[string]interface{}{
264		"name":           "testgroup1",
265		"mount_accessor": ldapMountAccessor1,
266		"canonical_id":   ldapExtGroupID1,
267	})
268	if err != nil {
269		t.Fatal(err)
270	}
271
272	// Renew token to refresh external group memberships
273	secret, err = client.Auth().Token().Renew(ldapClientToken, 10)
274	if err != nil {
275		t.Fatal(err)
276	}
277
278	// Lookup token and expect entity, group and external group policies on the
279	// token
280	secret, err = client.Logical().Write("auth/token/lookup", map[string]interface{}{
281		"token": ldapClientToken,
282	})
283	if err != nil {
284		t.Fatal(err)
285	}
286	identityPolicies = secret.Data["identity_policies"].([]interface{})
287	actualPolicies = nil
288	for _, item := range identityPolicies {
289		actualPolicies = append(actualPolicies, item.(string))
290	}
291	sort.Strings(actualPolicies)
292
293	expectedPolicies = []string{
294		"entity_policy_1",
295		"entity_policy_2",
296		"group_policy_1",
297		"group_policy_2",
298		"external_group_policy_1",
299		"external_group_policy_2",
300	}
301	sort.Strings(expectedPolicies)
302	if !reflect.DeepEqual(expectedPolicies, actualPolicies) {
303		t.Fatalf("bad: identity policies; expected: %#v\nactual: %#v", expectedPolicies, actualPolicies)
304	}
305
306	// Log in and get a new token, then renew it. See issue #4829. The logic is
307	// continued after the next block.
308	secret, err = client.Logical().Write("auth/ldap/login/tesla", map[string]interface{}{
309		"password": "password",
310	})
311	if err != nil {
312		t.Fatal(err)
313	}
314	token4829 := secret.Auth.ClientToken
315
316	// Check that the lease for the token contains only the single group; this
317	// should be true for both as one was fresh and the other was a renew
318	// (which is why we do the renew check on the 4839 token after this block)
319	secret, err = client.Logical().List("sys/raw/sys/expire/id/auth/ldap/login/tesla/")
320	if err != nil {
321		t.Fatal(err)
322	}
323	for _, key := range secret.Data["keys"].([]interface{}) {
324		secret, err := client.Logical().Read("sys/raw/sys/expire/id/auth/ldap/login/tesla/" + key.(string))
325		if err != nil {
326			t.Fatal(err)
327		}
328		//t.Logf("%#v", *secret)
329		var resp logical.Response
330		if err := jsonutil.DecodeJSON([]byte(secret.Data["value"].(string)), &resp); err != nil {
331			t.Fatal(err)
332		}
333		if len(resp.Auth.GroupAliases) != 1 || resp.Auth.GroupAliases[0].Name != "testgroup1" {
334			t.Fatalf("bad: %#v", resp.Auth.GroupAliases)
335		}
336	}
337
338	secret, err = client.Auth().Token().Renew(token4829, 10)
339	if err != nil {
340		t.Fatal(err)
341	}
342}
343
344func TestTokenStore_CIDRBlocks(t *testing.T) {
345	testPolicy := `
346path "auth/token/create" {
347	capabilities = ["update"]
348}
349`
350
351	cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
352		HandlerFunc: vaulthttp.Handler,
353	})
354	cluster.Start()
355	defer cluster.Cleanup()
356
357	core := cluster.Cores[0].Core
358	vault.TestWaitActive(t, core)
359	client := cluster.Cores[0].Client
360	rootToken := client.Token()
361
362	var err error
363	var secret *api.Secret
364
365	_, err = client.Logical().Write("sys/policies/acl/test", map[string]interface{}{
366		"policy": testPolicy,
367	})
368	if err != nil {
369		t.Fatal(err)
370	}
371
372	// Test normally
373	_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
374		"bound_cidrs": []string{},
375	})
376	if err != nil {
377		t.Fatal(err)
378	}
379	secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
380		Policies: []string{"default"},
381	}, "testrole")
382	if err != nil {
383		t.Fatal(err)
384	}
385	client.SetToken(secret.Auth.ClientToken)
386	_, err = client.Auth().Token().LookupSelf()
387	if err != nil {
388		t.Fatal(err)
389	}
390
391	// CIDR blocks, containing localhost
392	client.SetToken(rootToken)
393	_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
394		"bound_cidrs":      []string{"127.0.0.1/32", "1.2.3.4/8", "5.6.7.8/24"},
395		"allowed_policies": "test",
396	})
397	if err != nil {
398		t.Fatal(err)
399	}
400	secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
401		Policies: []string{"test", "default"},
402	}, "testrole")
403	if err != nil {
404		t.Fatal(err)
405	}
406	client.SetToken(secret.Auth.ClientToken)
407	_, err = client.Auth().Token().LookupSelf()
408	if err != nil {
409		t.Fatal(err)
410	}
411
412	// Before moving on, validate that a child token created from this token
413	// inherits the bound cidr blocks
414	client.SetToken(secret.Auth.ClientToken)
415	childSecret, err := client.Auth().Token().Create(&api.TokenCreateRequest{
416		Policies: []string{"default"},
417	})
418	if err != nil {
419		t.Fatal(err)
420	}
421	if err != nil {
422		t.Fatal(err)
423	}
424	client.SetToken(childSecret.Auth.ClientToken)
425	childInfo, err := client.Auth().Token().LookupSelf()
426	if err != nil {
427		t.Fatal(err)
428	}
429	if diff := deep.Equal(childInfo.Data["bound_cidrs"], []interface{}{"127.0.0.1", "1.2.3.4/8", "5.6.7.8/24"}); diff != nil {
430		t.Fatal(diff)
431	}
432
433	// CIDR blocks, not containing localhost (should fail)
434	client.SetToken(rootToken)
435	_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
436		"bound_cidrs": []string{"1.2.3.4/8", "5.6.7.8/24"},
437	})
438	if err != nil {
439		t.Fatal(err)
440	}
441	secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
442		Policies: []string{"default"},
443	}, "testrole")
444	if err != nil {
445		t.Fatal(err)
446	}
447	client.SetToken(secret.Auth.ClientToken)
448	_, err = client.Auth().Token().LookupSelf()
449	if err == nil {
450		t.Fatal("expected error")
451	}
452	if !strings.Contains(err.Error(), "permission denied") {
453		t.Fatalf("unexpected error: %v", err)
454	}
455
456	// Root token, no ttl, should work
457	client.SetToken(rootToken)
458	_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
459		"bound_cidrs":      []string{"1.2.3.4/8", "5.6.7.8/24"},
460		"allowed_policies": "",
461	})
462	if err != nil {
463		t.Fatal(err)
464	}
465	secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{}, "testrole")
466	if err != nil {
467		t.Fatal(err)
468	}
469	client.SetToken(secret.Auth.ClientToken)
470	_, err = client.Auth().Token().LookupSelf()
471	if err != nil {
472		t.Fatal(err)
473	}
474
475	// Root token, ttl, should not work
476	client.SetToken(rootToken)
477	_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
478		"bound_cidrs": []string{"1.2.3.4/8", "5.6.7.8/24"},
479		"period":      3600,
480	})
481	if err != nil {
482		t.Fatal(err)
483	}
484	secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{}, "testrole")
485	if err != nil {
486		t.Fatal(err)
487	}
488	client.SetToken(secret.Auth.ClientToken)
489	_, err = client.Auth().Token().LookupSelf()
490	if err == nil {
491		t.Fatal("expected error")
492	}
493	if !strings.Contains(err.Error(), "permission denied") {
494		t.Fatalf("unexpected error: %v", err)
495	}
496}
497
498func TestTokenStore_RevocationOnStartup(t *testing.T) {
499	cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
500		HandlerFunc: vaulthttp.Handler,
501		NumCores:    1,
502	})
503	cluster.Start()
504	defer cluster.Cleanup()
505
506	core := cluster.Cores[0].Core
507	vault.TestWaitActive(t, core)
508	client := cluster.Cores[0].Client
509	rootToken := client.Token()
510
511	type leaseEntry struct {
512		LeaseID         string                 `json:"lease_id"`
513		ClientToken     string                 `json:"client_token"`
514		Path            string                 `json:"path"`
515		Data            map[string]interface{} `json:"data"`
516		Secret          *logical.Secret        `json:"secret"`
517		Auth            *logical.Auth          `json:"auth"`
518		IssueTime       time.Time              `json:"issue_time"`
519		ExpireTime      time.Time              `json:"expire_time"`
520		LastRenewalTime time.Time              `json:"last_renewal_time"`
521	}
522
523	var secret *api.Secret
524	var err error
525	var tokens []string
526	// Create tokens
527	for i := 0; i < 500; i++ {
528		secret, err = client.Auth().Token().Create(&api.TokenCreateRequest{
529			Policies: []string{"default"},
530		})
531		if err != nil {
532			t.Fatal(err)
533		}
534		tokens = append(tokens, secret.Auth.ClientToken)
535	}
536
537	const tokenPath string = "sys/raw/sys/token/id/"
538	secret, err = client.Logical().List(tokenPath)
539	if err != nil {
540		t.Fatal(err)
541	}
542	totalTokens := len(secret.Data["keys"].([]interface{}))
543
544	// Get the list of leases
545	const leasePath string = "sys/raw/sys/expire/id/auth/token/create/"
546	secret, err = client.Logical().List(leasePath)
547	if err != nil {
548		t.Fatal(err)
549	}
550	leases := secret.Data["keys"].([]interface{})
551	if len(leases) != 500 {
552		t.Fatalf("unexpected number of leases: %d", len(leases))
553	}
554
555	// Holds non-root leases
556	var validLeases []string
557	// Fake times in the past
558	for _, lease := range leases {
559		secret, err = client.Logical().Read(leasePath + lease.(string))
560		var entry leaseEntry
561		if err := jsonutil.DecodeJSON([]byte(secret.Data["value"].(string)), &entry); err != nil {
562			t.Fatal(err)
563		}
564		if entry.ExpireTime.IsZero() {
565			continue
566		}
567		validLeases = append(validLeases, lease.(string))
568		entry.IssueTime = entry.IssueTime.Add(-1 * time.Hour * 24 * 365)
569		entry.ExpireTime = entry.ExpireTime.Add(-1 * time.Hour * 24 * 365)
570		jsonEntry, err := jsonutil.EncodeJSON(&entry)
571		if err != nil {
572			t.Fatal(err)
573		}
574		if _, err := client.Logical().Write(leasePath+lease.(string), map[string]interface{}{
575			"value": string(jsonEntry),
576		}); err != nil {
577			t.Fatal(err)
578		}
579	}
580
581	if err := client.Sys().Seal(); err != nil {
582		t.Fatal(err)
583	}
584
585	var status *api.SealStatusResponse
586	for i := 0; i < len(cluster.BarrierKeys); i++ {
587		status, err = client.Sys().Unseal(string(base64.StdEncoding.EncodeToString(cluster.BarrierKeys[i])))
588		if err != nil {
589			t.Fatal(err)
590		}
591		if !status.Sealed {
592			break
593		}
594	}
595	if status.Sealed {
596		t.Fatal("did not unseal properly")
597	}
598
599	// Give lease loading some time to process
600	time.Sleep(5 * time.Second)
601
602	for i, token := range tokens {
603		client.SetToken(token)
604		_, err := client.Logical().Write("cubbyhole/foo", map[string]interface{}{
605			"value": "bar",
606		})
607		if err == nil {
608			t.Errorf("expected error but did not get one, token num %d", i)
609		}
610	}
611
612	expectedLeases := len(leases) - len(validLeases)
613
614	client.SetToken(rootToken)
615	secret, err = client.Logical().List(leasePath)
616	if err != nil {
617		t.Fatal(err)
618	}
619
620	switch {
621	case secret == nil:
622		if expectedLeases != 0 {
623			t.Fatalf("nil secret back but expected %d leases", expectedLeases)
624		}
625
626	case secret.Data == nil:
627		if expectedLeases != 0 {
628			t.Fatalf("nil secret data back but expected %d leases, secret is %#v", expectedLeases, *secret)
629		}
630
631	default:
632		leasesLeft := len(secret.Data["keys"].([]interface{}))
633		if leasesLeft != expectedLeases {
634			t.Fatalf("found %d leases left, expected %d", leasesLeft, expectedLeases)
635		}
636	}
637
638	expectedTokens := totalTokens - len(validLeases)
639	secret, err = client.Logical().List(tokenPath)
640	if err != nil {
641		t.Fatal(err)
642	}
643	tokensLeft := len(secret.Data["keys"].([]interface{}))
644	if tokensLeft != expectedTokens {
645		t.Fatalf("found %d tokens left, expected %d", tokensLeft, expectedTokens)
646	}
647}
648