token: disallow periods on custom token IDs (#8646)
* token: disallow periods on custom token IDs * docs: update token API docs
This commit is contained in:
parent
1dbc6d3dd0
commit
ec8448ab56
|
@ -817,8 +817,13 @@ func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) err
|
|||
}
|
||||
}
|
||||
|
||||
if userSelectedID && strings.HasPrefix(entry.ID, "s.") {
|
||||
return fmt.Errorf("custom token ID cannot have the 's.' prefix")
|
||||
if userSelectedID {
|
||||
switch {
|
||||
case strings.HasPrefix(entry.ID, "s."):
|
||||
return fmt.Errorf("custom token ID cannot have the 's.' prefix")
|
||||
case strings.Contains(entry.ID, "."):
|
||||
return fmt.Errorf("custom token ID cannot have a '.' in the value")
|
||||
}
|
||||
}
|
||||
|
||||
if !userSelectedID {
|
||||
|
|
|
@ -231,57 +231,6 @@ func TestTokenStore_Salting(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTokenStore_ServiceTokenPrefix(t *testing.T) {
|
||||
c, _, initToken := TestCoreUnsealed(t)
|
||||
ts := c.tokenStore
|
||||
|
||||
// Ensure that a regular service token has a "s." prefix
|
||||
resp, err := ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: initToken,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
})
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: resp: %#v\nerr: %v", resp, err)
|
||||
}
|
||||
if !strings.HasPrefix(resp.Auth.ClientToken, "s.") {
|
||||
t.Fatalf("token %q does not have a 's.' prefix", resp.Auth.ClientToken)
|
||||
}
|
||||
|
||||
// Ensure that using a custon token ID results in a warning
|
||||
resp, err = ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: initToken,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
Data: map[string]interface{}{
|
||||
"id": "foobar",
|
||||
},
|
||||
})
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: resp: %#v\nerr: %v", resp, err)
|
||||
}
|
||||
expectedWarning := "Supplying a custom ID for the token uses the weaker SHA1 hashing instead of the more secure SHA2-256 HMAC for token obfuscation. SHA1 hashed tokens on the wire leads to less secure lookups."
|
||||
if resp.Warnings[0] != expectedWarning {
|
||||
t.Fatalf("expected warning not present")
|
||||
}
|
||||
|
||||
// Ensure that custom token ID having a "s." prefix fails
|
||||
resp, err = ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: initToken,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
Data: map[string]interface{}{
|
||||
"id": "s.foobar",
|
||||
},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if resp.Error().Error() != "custom token ID cannot have the 's.' prefix" {
|
||||
t.Fatalf("expected input error not present in error response")
|
||||
}
|
||||
}
|
||||
|
||||
type TokenEntryOld struct {
|
||||
ID string
|
||||
Accessor string
|
||||
|
@ -5633,3 +5582,87 @@ func TestTokenStore_Batch_NoCubbyhole(t *testing.T) {
|
|||
t.Fatalf("bad: expected error, got %#v", *resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenStore_TokenID(t *testing.T) {
|
||||
t.Run("no custom ID provided", func(t *testing.T) {
|
||||
c, _, initToken := TestCoreUnsealed(t)
|
||||
ts := c.tokenStore
|
||||
|
||||
// Ensure that a regular service token has a "s." prefix
|
||||
resp, err := ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: initToken,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
})
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: resp: %#v\nerr: %v", resp, err)
|
||||
}
|
||||
if !strings.HasPrefix(resp.Auth.ClientToken, "s.") {
|
||||
t.Fatalf("token %q does not have a 's.' prefix", resp.Auth.ClientToken)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("plain custom ID", func(t *testing.T) {
|
||||
core, _, root := TestCoreUnsealed(t)
|
||||
ts := core.tokenStore
|
||||
|
||||
resp, err := ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: root,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
Data: map[string]interface{}{
|
||||
"id": "foobar",
|
||||
},
|
||||
})
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: resp: %#v\nerr: %v", resp, err)
|
||||
}
|
||||
|
||||
// Ensure that using a custom token ID results in a warning
|
||||
expectedWarning := "Supplying a custom ID for the token uses the weaker SHA1 hashing instead of the more secure SHA2-256 HMAC for token obfuscation. SHA1 hashed tokens on the wire leads to less secure lookups."
|
||||
if resp.Warnings[0] != expectedWarning {
|
||||
t.Fatalf("expected warning not present")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("service token prefix in custom ID", func(t *testing.T) {
|
||||
c, _, initToken := TestCoreUnsealed(t)
|
||||
ts := c.tokenStore
|
||||
|
||||
// Ensure that custom token ID having a "s." prefix fails
|
||||
resp, err := ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: initToken,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
Data: map[string]interface{}{
|
||||
"id": "s.foobar",
|
||||
},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if resp.Error().Error() != "custom token ID cannot have the 's.' prefix" {
|
||||
t.Fatalf("expected input error not present in error response")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("period in custom ID", func(t *testing.T) {
|
||||
core, _, root := TestCoreUnsealed(t)
|
||||
ts := core.tokenStore
|
||||
|
||||
resp, err := ts.HandleRequest(namespace.RootContext(nil), &logical.Request{
|
||||
ClientToken: root,
|
||||
Path: "create",
|
||||
Operation: logical.UpdateOperation,
|
||||
Data: map[string]interface{}{
|
||||
"id": "foobar.baz",
|
||||
},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if resp.Error().Error() != "custom token ID cannot have a '.' in the value" {
|
||||
t.Fatalf("expected input error not present in error response")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ during this call.
|
|||
### Parameters
|
||||
|
||||
- `id` `(string: "")` – The ID of the client token. Can only be specified by a
|
||||
root token. Otherwise, the token ID is a randomly generated value.
|
||||
root token. The ID provided may not contain a `.` character. Otherwise, the
|
||||
token ID is a randomly generated value.
|
||||
- `role_name` `(string: "")` – The name of the token role.
|
||||
- `policies` `(array: "")` – A list of policies for the token. This must be a
|
||||
subset of the policies belonging to the token making the request, unless root.
|
||||
|
|
Loading…
Reference in New Issue