Unverified Commit e620786b authored by Jeff Mitchell's avatar Jeff Mitchell Committed by GitHub
Browse files

Add `default-service`/`default-batch` to token store roles (#5711)

parent e20134b4
Showing with 225 additions and 93 deletions
+225 -93
......@@ -16,6 +16,15 @@ CHANGES:
If performing seal migration, the barrier config should first be upgraded
prior to starting migration.
CHANGES FROM BETA 1:
(Note: these items will be removed from the final 1.0 changelog as they are
only breaking changes from beta1)
* Token Store Roles and Batch Tokens: Roles now default to `default-service`
token type, issuing service tokens by default but allowing overriding by the
client. They now also support `default-batch` in addition to `service` and
`batch`.
FEATURES:
* AppRole support in Vault Agent Auto-Auth: You can now use AppRole
......
......@@ -331,90 +331,192 @@ func TestTokenStore_Roles_Batch(t *testing.T) {
var err error
var secret *api.Secret
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"bound_cidrs": []string{},
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "batch",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] == "b." {
t.Fatal(secret.Auth.ClientToken)
// Test service
{
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"bound_cidrs": []string{},
"token_type": "service",
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "batch",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "s." {
t.Fatal(secret.Auth.ClientToken)
}
}
// Test batch
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
})
// Orphan not set so we should error
if err == nil {
t.Fatal("expected error")
}
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
"orphan": true,
})
// Renewable set so we should error
if err == nil {
t.Fatal("expected error")
}
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
"orphan": true,
"renewable": false,
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "service",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "b." {
t.Fatal(secret.Auth.ClientToken)
{
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
})
// Orphan not set so we should error
if err == nil {
t.Fatal("expected error")
}
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
"orphan": true,
})
// Renewable set so we should error
if err == nil {
t.Fatal("expected error")
}
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "batch",
"orphan": true,
"renewable": false,
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "service",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "b." {
t.Fatal(secret.Auth.ClientToken)
}
}
// Back to normal
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "service",
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "batch",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
// Test default-service
{
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "default-service",
})
if err != nil {
t.Fatal(err)
}
// Client specifies batch
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "batch",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "b." {
t.Fatal(secret.Auth.ClientToken)
}
// Client specifies service
client.SetToken(rootToken)
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "service",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "s." {
t.Fatal(secret.Auth.ClientToken)
}
// Client doesn't specify
client.SetToken(rootToken)
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "s." {
t.Fatal(secret.Auth.ClientToken)
}
}
if secret.Auth.ClientToken[0:2] == "b." {
t.Fatal(secret.Auth.ClientToken)
// Test default-batch
{
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"token_type": "default-batch",
})
if err != nil {
t.Fatal(err)
}
// Client specifies batch
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "batch",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "b." {
t.Fatal(secret.Auth.ClientToken)
}
// Client specifies service
client.SetToken(rootToken)
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Type: "service",
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "s." {
t.Fatal(secret.Auth.ClientToken)
}
// Client doesn't specify
client.SetToken(rootToken)
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
}, "testrole")
if err != nil {
t.Fatal(err)
}
client.SetToken(secret.Auth.ClientToken)
_, err = client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
if secret.Auth.ClientToken[0:2] != "b." {
t.Fatal(secret.Auth.ClientToken)
}
}
}
......@@ -2155,7 +2155,14 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
tokenTypeStr := data.Type
if role != nil {
switch role.TokenType {
case logical.TokenTypeDefault, logical.TokenTypeService:
case logical.TokenTypeDefault, logical.TokenTypeDefaultService:
// Use the user-given value, but fall back to service
case logical.TokenTypeDefaultBatch:
// Use the user-given value, but fall back to batch
if tokenTypeStr == "" {
tokenTypeStr = logical.TokenTypeBatch.String()
}
case logical.TokenTypeService:
tokenTypeStr = logical.TokenTypeService.String()
case logical.TokenTypeBatch:
tokenTypeStr = logical.TokenTypeBatch.String()
......@@ -2927,6 +2934,10 @@ func (ts *TokenStore) tokenStoreRole(ctx context.Context, name string) (*tsRoleE
return nil, err
}
if result.TokenType == logical.TokenTypeDefault {
result.TokenType = logical.TokenTypeDefaultService
}
return &result, nil
}
......@@ -3121,19 +3132,26 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
}
tokenType := entry.TokenType
if tokenType == logical.TokenTypeDefault {
tokenType = logical.TokenTypeDefaultService
}
tokenTypeRaw, ok := data.GetOk("token_type")
if ok {
tokenTypeStr := tokenTypeRaw.(string)
switch tokenTypeStr {
case "", "service":
case "service":
tokenType = logical.TokenTypeService
case "batch":
tokenType = logical.TokenTypeBatch
case "default-service":
tokenType = logical.TokenTypeDefaultService
case "default-batch":
tokenType = logical.TokenTypeDefaultBatch
default:
return logical.ErrorResponse(fmt.Sprintf("invalid 'token_type' value %q", tokenTypeStr)), nil
}
} else if req.Operation == logical.CreateOperation {
tokenType = logical.TokenTypeService
tokenType = logical.TokenTypeDefaultService
}
entry.TokenType = tokenType
......
......@@ -2550,11 +2550,11 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"path_suffix": "happenin",
"explicit_max_ttl": int64(0),
"renewable": true,
"token_type": "service",
"token_type": "default-service",
}
if !reflect.DeepEqual(expected, resp.Data) {
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
if diff := deep.Equal(expected, resp.Data); diff != nil {
t.Fatal(diff)
}
// Now test updating; this should be set to an UpdateOperation
......@@ -2596,11 +2596,11 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"path_suffix": "happenin",
"explicit_max_ttl": int64(0),
"renewable": false,
"token_type": "service",
"token_type": "default-service",
}
if !reflect.DeepEqual(expected, resp.Data) {
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
if diff := deep.Equal(expected, resp.Data); diff != nil {
t.Fatal(diff)
}
// Now set explicit max ttl and clear the period
......@@ -2634,11 +2634,11 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"path_suffix": "happenin",
"period": int64(0),
"renewable": false,
"token_type": "service",
"token_type": "default-service",
}
if !reflect.DeepEqual(expected, resp.Data) {
t.Fatalf("bad: expected:%#v\nactual:%#v", expected, resp.Data)
if diff := deep.Equal(expected, resp.Data); diff != nil {
t.Fatal(diff)
}
req.Operation = logical.ListOperation
......
......@@ -675,8 +675,11 @@ tokens created against a role to be revoked using the
with no TTL will not be bound by these CIDRs; root tokens with TTLs will be
bound by these CIDRs.
- `token_type` `(string: "")` – Specifies the type of tokens that should be
returned by the role; either `service` or `batch`. If empty, `service` tokens
will be returned.
returned by the role. If either `service` or `batch` is specified, that kind
of token will always be returned. If `default-service`, `service` tokens will
be returned unless the client requests a `batch` type token at token creation
time. If `default-batch`, `batch` tokens will be returned unless the client
requests a `service` type token at token creation time.
### Sample Payload
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment