Fix bound cidrs propagation

This commit is contained in:
Jeff Mitchell
2019-01-15 10:55:36 -05:00
parent db2fbc5dd9
commit 100de68cfd
3 changed files with 58 additions and 7 deletions

View File

@@ -1,5 +1,11 @@
## 1.0.2 (Unreleased)
SECURITY:
* When creating a child token from a parent with `bound_cidrs`, the list of
CIDRs would not be propagated to the child token, allowing the child token
to be used from any address.
CHANGES:
* secret/aws: Role now returns `credential_type` instead of `credential_types`
@@ -40,10 +46,11 @@ BUG FIXES:
also provided [GH-5965]
* command/operator/rekey: Fix help output showing `-delete-backup` when it
should show `-backup-delete` [GH-5981]
* secret/aws: Make input `credential_type` match the output type (string, not
array) [GH-5972]
* core: Fix bound_cidrs not being propagated to child tokens
* replication: Correctly forward identity entity creation that originates from
performance standby nodes (Enterprise)
* secret/aws: Make input `credential_type` match the output type (string, not
array) [GH-5972]
* secret/cubbyhole: Properly cleanup cubbyhole after token revocation [GH-6006]
* ui (enterprise) - properly display perf-standby count on the license page [GH-5971]
* ui - fix disappearing nested secrets and go to the nearest parent when deleting

View File

@@ -8,6 +8,7 @@ import (
"testing"
"time"
"github.com/go-test/deep"
"github.com/hashicorp/vault/api"
credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
@@ -341,6 +342,12 @@ func TestTokenStore_IdentityPolicies(t *testing.T) {
}
func TestTokenStore_CIDRBlocks(t *testing.T) {
testPolicy := `
path "auth/token/create" {
capabilities = ["update"]
}
`
cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
HandlerFunc: vaulthttp.Handler,
})
@@ -355,6 +362,13 @@ func TestTokenStore_CIDRBlocks(t *testing.T) {
var err error
var secret *api.Secret
_, err = client.Logical().Write("sys/policies/acl/test", map[string]interface{}{
"policy": testPolicy,
})
if err != nil {
t.Fatal(err)
}
// Test normally
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"bound_cidrs": []string{},
@@ -377,13 +391,14 @@ func TestTokenStore_CIDRBlocks(t *testing.T) {
// CIDR blocks, containing localhost
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"bound_cidrs": []string{"127.0.0.1/32", "1.2.3.4/8", "5.6.7.8/24"},
"bound_cidrs": []string{"127.0.0.1/32", "1.2.3.4/8", "5.6.7.8/24"},
"allowed_policies": "test",
})
if err != nil {
t.Fatal(err)
}
secret, err = client.Auth().Token().CreateWithRole(&api.TokenCreateRequest{
Policies: []string{"default"},
Policies: []string{"test", "default"},
}, "testrole")
if err != nil {
t.Fatal(err)
@@ -394,6 +409,27 @@ func TestTokenStore_CIDRBlocks(t *testing.T) {
t.Fatal(err)
}
// Before moving on, validate that a child token created from this token
// inherits the bound cidr blocks
client.SetToken(secret.Auth.ClientToken)
childSecret, err := client.Auth().Token().Create(&api.TokenCreateRequest{
Policies: []string{"default"},
})
if err != nil {
t.Fatal(err)
}
if err != nil {
t.Fatal(err)
}
client.SetToken(childSecret.Auth.ClientToken)
childInfo, err := client.Auth().Token().LookupSelf()
if err != nil {
t.Fatal(err)
}
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 {
t.Fatal(diff)
}
// CIDR blocks, not containing localhost (should fail)
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
@@ -420,7 +456,8 @@ func TestTokenStore_CIDRBlocks(t *testing.T) {
// Root token, no ttl, should work
client.SetToken(rootToken)
_, err = client.Logical().Write("auth/token/roles/testrole", map[string]interface{}{
"bound_cidrs": []string{"1.2.3.4/8", "5.6.7.8/24"},
"bound_cidrs": []string{"1.2.3.4/8", "5.6.7.8/24"},
"allowed_policies": "",
})
if err != nil {
t.Fatal(err)

View File

@@ -2428,10 +2428,17 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
// At this point, it is clear whether the token is going to be an orphan or
// not. If the token is not going to be an orphan, inherit the parent's
// entity identifier into the child token. We must also verify that, if
// it's not an orphan, the parent isn't a batch token.
// entity identifier into the child token.
if te.Parent != "" {
te.EntityID = parent.EntityID
// If the parent has bound CIDRs, copy those into the child. We don't
// do this if role is not nil because then we always use the role's
// bound CIDRs; roles allow escalation of privilege in proper
// circumstances.
if role == nil {
te.BoundCIDRs = parent.BoundCIDRs
}
}
var explicitMaxTTLToUse time.Duration