diff --git a/vault/token_store.go b/vault/token_store.go index 5b31c08722..7622abdf56 100644 --- a/vault/token_store.go +++ b/vault/token_store.go @@ -1076,6 +1076,11 @@ func (ts *TokenStore) handleCreateCommon( logical.ErrInvalidRequest } + // Prevent attempts to create a root token without an actual root token as parent + if strutil.StrListContains(data.Policies, "root") && !strutil.StrListContains(parent.Policies, "root") { + return logical.ErrorResponse("root tokens may not be created without parent token being root"), logical.ErrInvalidRequest + } + // Setup the token entry te := TokenEntry{ Parent: req.ClientToken, diff --git a/vault/token_store_test.go b/vault/token_store_test.go index e51ae26c43..3cb18cc5af 100644 --- a/vault/token_store_test.go +++ b/vault/token_store_test.go @@ -832,6 +832,23 @@ func TestTokenStore_HandleRequest_CreateToken_NonRoot_InvalidSubset(t *testing.T } } +func TestTokenStore_HandleRequest_CreateToken_NonRoot_RootChild(t *testing.T) { + _, ts, _, root := TestCoreWithTokenStore(t) + testMakeToken(t, ts, root, "client", "", []string{"foo", "bar"}) + + req := logical.TestRequest(t, logical.UpdateOperation, "create") + req.ClientToken = "client" + req.Data["policies"] = []string{"root", "foo", "bar"} + + resp, err := ts.HandleRequest(req) + if err != logical.ErrInvalidRequest { + t.Fatalf("err: %v %v", err, resp) + } + if resp.Data["error"] != "root tokens may not be created without parent token being root" { + t.Fatalf("bad: %#v", resp) + } +} + func TestTokenStore_HandleRequest_CreateToken_NonRoot_NoParent(t *testing.T) { _, ts, _, root := TestCoreWithTokenStore(t) testMakeToken(t, ts, root, "client", "", []string{"foo"})