Backport Add default ceiling policy into ce/main (#13821)

This commit is contained in:
Vault Automation 2026-04-10 10:04:46 -04:00 committed by GitHub
parent b98004d1dc
commit 4a2a1133fc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 107 additions and 41 deletions

View file

@ -455,7 +455,7 @@ func TestPredict_Policies(t *testing.T) {
{
"good_path",
client,
[]string{"default", "root"},
[]string{"default", "default-ceiling", "root"},
},
}

View file

@ -35,8 +35,8 @@ Usage: vault policy delete [options] NAME
$ vault policy delete my-policy
Note that it is not possible to delete the "default" or "root" policies.
These are built-in policies.
Note that it is not possible to delete the "default", "default-ceiling",
or "root" policies. These are built-in policies.
` + c.Flags().Help()

View file

@ -105,7 +105,7 @@ func TestPolicyDeleteCommand_Run(t *testing.T) {
t.Fatal(err)
}
list := []string{"default", "root"}
list := []string{"default", "default-ceiling", "root"}
if !reflect.DeepEqual(policies, list) {
t.Errorf("expected %q to be %q", policies, list)
}

View file

@ -80,7 +80,7 @@ func TestPolicyListCommand_Run(t *testing.T) {
t.Errorf("expected %d to be %d", code, exp)
}
expected := "default\nroot"
expected := "default\ndefault-ceiling\nroot"
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
if !strings.Contains(combined, expected) {
t.Errorf("expected %q to contain %q", combined, expected)

View file

@ -131,7 +131,7 @@ func TestPolicyWriteCommand_Run(t *testing.T) {
t.Fatal(err)
}
list := []string{"default", "my-policy", "root"}
list := []string{"default", "default-ceiling", "my-policy", "root"}
if !reflect.DeepEqual(policies, list) {
t.Errorf("expected %q to be %q", policies, list)
}
@ -172,7 +172,7 @@ func TestPolicyWriteCommand_Run(t *testing.T) {
t.Fatal(err)
}
list := []string{"default", "my-policy", "root"}
list := []string{"default", "default-ceiling", "my-policy", "root"}
if !reflect.DeepEqual(policies, list) {
t.Errorf("expected %q to be %q", policies, list)
}

View file

@ -29,11 +29,11 @@ func TestSysPolicies(t *testing.T) {
"auth": nil,
"mount_type": "system",
"data": map[string]interface{}{
"policies": []interface{}{"default", "root"},
"keys": []interface{}{"default", "root"},
"policies": []interface{}{"default", "default-ceiling", "root"},
"keys": []interface{}{"default", "default-ceiling", "root"},
},
"policies": []interface{}{"default", "root"},
"keys": []interface{}{"default", "root"},
"policies": []interface{}{"default", "default-ceiling", "root"},
"keys": []interface{}{"default", "default-ceiling", "root"},
}
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)
@ -98,11 +98,11 @@ func TestSysWritePolicy(t *testing.T) {
"auth": nil,
"mount_type": "system",
"data": map[string]interface{}{
"policies": []interface{}{"default", "foo", "root"},
"keys": []interface{}{"default", "foo", "root"},
"policies": []interface{}{"default", "default-ceiling", "foo", "root"},
"keys": []interface{}{"default", "default-ceiling", "foo", "root"},
},
"policies": []interface{}{"default", "foo", "root"},
"keys": []interface{}{"default", "foo", "root"},
"policies": []interface{}{"default", "default-ceiling", "foo", "root"},
"keys": []interface{}{"default", "default-ceiling", "foo", "root"},
}
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)
@ -134,6 +134,7 @@ func TestSysDeletePolicy(t *testing.T) {
// Also attempt to delete these since they should not be allowed (ignore
// responses, if they exist later that's sufficient)
resp = testHttpDelete(t, token, addr+"/v1/sys/policy/default")
resp = testHttpDelete(t, token, addr+"/v1/sys/policy/default-ceiling")
resp = testHttpDelete(t, token, addr+"/v1/sys/policy/response-wrapping")
resp = testHttpGet(t, token, addr+"/v1/sys/policy")
@ -148,11 +149,11 @@ func TestSysDeletePolicy(t *testing.T) {
"auth": nil,
"mount_type": "system",
"data": map[string]interface{}{
"policies": []interface{}{"default", "root"},
"keys": []interface{}{"default", "root"},
"policies": []interface{}{"default", "default-ceiling", "root"},
"keys": []interface{}{"default", "default-ceiling", "root"},
},
"policies": []interface{}{"default", "root"},
"keys": []interface{}{"default", "root"},
"policies": []interface{}{"default", "default-ceiling", "root"},
"keys": []interface{}{"default", "default-ceiling", "root"},
}
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)

View file

@ -24,7 +24,7 @@
{{#if (and (not-eq this.model.id "root") (or this.model.canUpdate this.model.canDelete))}}
<Toolbar>
<ToolbarActions>
{{#if (and (not-eq this.model.id "default") this.model.canDelete)}}
{{#if (and (not-eq this.model.id "default") (not-eq this.model.id "default-ceiling") this.model.canDelete)}}
<ConfirmAction
@buttonText="Delete policy"
class="toolbar-button"

View file

@ -413,8 +413,8 @@ func TestCoreMetrics_AvailablePolicies(t *testing.T) {
},
},
ExpectedValues: map[string]float32{
// The "default" policy will always be included
"acl": 2,
// The built-in ACL policies are always included.
"acl": 3,
"egp": 0,
"rgp": 0,
},
@ -429,8 +429,8 @@ func TestCoreMetrics_AvailablePolicies(t *testing.T) {
},
},
ExpectedValues: map[string]float32{
// The "default" policy will always be included
"acl": 3,
// The built-in ACL policies are always included.
"acl": 4,
"egp": 0,
"rgp": 0,
},

View file

@ -2722,8 +2722,8 @@ func TestSystemBackend_policyList(t *testing.T) {
)
exp := map[string]interface{}{
"keys": []string{"default", "root"},
"policies": []string{"default", "root"},
"keys": []string{"default", "default-ceiling", "root"},
"policies": []string{"default", "default-ceiling", "root"},
}
if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("got: %#v expect: %#v", resp.Data, exp)
@ -2801,8 +2801,8 @@ func TestSystemBackend_policyCRUD(t *testing.T) {
}
exp = map[string]interface{}{
"keys": []string{"default", "foo", "root"},
"policies": []string{"default", "foo", "root"},
"keys": []string{"default", "default-ceiling", "foo", "root"},
"policies": []string{"default", "default-ceiling", "foo", "root"},
}
if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("got: %#v expect: %#v", resp.Data, exp)
@ -2844,8 +2844,8 @@ func TestSystemBackend_policyCRUD(t *testing.T) {
}
exp = map[string]interface{}{
"keys": []string{"default", "root"},
"policies": []string{"default", "root"},
"keys": []string{"default", "default-ceiling", "root"},
"policies": []string{"default", "default-ceiling", "root"},
}
if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("got: %#v expect: %#v", resp.Data, exp)

View file

@ -36,6 +36,9 @@ const (
// defaultPolicyName is the name of the default policy
defaultPolicyName = "default"
// defaultCeilingPolicyName is the name of the default ceiling policy.
defaultCeilingPolicyName = "default-ceiling"
// responseWrappingPolicyName is the name of the fixed policy
responseWrappingPolicyName = "response-wrapping"
@ -159,6 +162,22 @@ path "sys/control-group/request" {
path "identity/oidc/provider/+/authorize" {
capabilities = ["read", "update"]
}
`
// defaultCeilingPolicy is the default ceiling policy.
defaultCeilingPolicy = `
# Allow an entity to inspect its own registration information
path "agent-registry/registration/entity_id/{{identity.entity.id}}" {
capabilities = ["read"]
}
# Allow an entity to read the default policies
path "policy/default" {
capabilities = ["read"]
}
path "policy/default-ceiling" {
capabilities = ["read"]
}
`
)
@ -280,6 +299,10 @@ func (c *Core) setupPolicyStore(ctx context.Context) error {
if err := c.policyStore.loadACLPolicy(ctx, defaultPolicyName, defaultPolicy); err != nil {
return err
}
// Ensure that the default ceiling policy exists, and if not, create it
if err := c.policyStore.loadACLPolicy(ctx, defaultCeilingPolicyName, defaultCeilingPolicy); err != nil {
return err
}
// Ensure that the response wrapping policy exists
if err := c.policyStore.loadACLPolicy(ctx, responseWrappingPolicyName, responseWrappingPolicy); err != nil {
return err
@ -835,8 +858,8 @@ func (ps *PolicyStore) switchedDeletePolicy(ctx context.Context, name string, po
if strutil.StrListContains(immutablePolicies, name) {
return fmt.Errorf("cannot delete %q policy", name)
}
if name == "default" {
return fmt.Errorf("cannot delete default policy")
if name == defaultPolicyName || name == defaultCeilingPolicyName {
return fmt.Errorf("cannot delete %s policy", name)
}
}

View file

@ -117,7 +117,8 @@ func testPolicyStoreCRUD(t *testing.T, ps *PolicyStore, ns *namespace.Namespace)
if err != nil {
t.Fatalf("err: %v", err)
}
if len(out) != 1 {
expected := []string{defaultPolicyName, defaultCeilingPolicyName}
if !reflect.DeepEqual(expected, out) {
t.Fatalf("bad: %v", out)
}
@ -139,17 +140,17 @@ func testPolicyStoreCRUD(t *testing.T, ps *PolicyStore, ns *namespace.Namespace)
t.Fatalf("bad: %v", p)
}
// List should contain two elements
// List should contain the two built-in assignable policies plus the new policy.
ctx = namespace.ContextWithNamespace(context.Background(), ns)
out, err = ps.ListPolicies(ctx, PolicyTypeACL)
if err != nil {
t.Fatalf("err: %v", err)
}
if len(out) != 2 {
if len(out) != 3 {
t.Fatalf("bad: %v", out)
}
expected := []string{"default", "dev"}
expected = []string{defaultPolicyName, defaultCeilingPolicyName, "dev"}
if !reflect.DeepEqual(expected, out) {
t.Fatalf("expected: %v\ngot: %v", expected, out)
}
@ -167,7 +168,8 @@ func testPolicyStoreCRUD(t *testing.T, ps *PolicyStore, ns *namespace.Namespace)
if err != nil {
t.Fatalf("err: %v", err)
}
if len(out) != 1 || out[0] != "default" {
expected = []string{defaultPolicyName, defaultCeilingPolicyName}
if !reflect.DeepEqual(expected, out) {
t.Fatalf("bad: %v", out)
}
@ -191,17 +193,57 @@ func TestPolicyStore_Predefined(t *testing.T) {
// Test predefined policy handling
func testPolicyStorePredefined(t *testing.T, ps *PolicyStore, ns *namespace.Namespace) {
// List should be two elements
// List should contain the built-in assignable ACL policies.
ctx := namespace.ContextWithNamespace(context.Background(), ns)
out, err := ps.ListPolicies(ctx, PolicyTypeACL)
if err != nil {
t.Fatalf("err: %v", err)
}
// This shouldn't contain response-wrapping since it's non-assignable
if len(out) != 1 || out[0] != "default" {
// This shouldn't contain response-wrapping since it's non-assignable.
expected := []string{defaultPolicyName, defaultCeilingPolicyName}
if !reflect.DeepEqual(expected, out) {
t.Fatalf("bad: %v", out)
}
ctx = namespace.ContextWithNamespace(context.Background(), ns)
pDefaultCeiling, err := ps.GetPolicy(ctx, defaultCeilingPolicyName, PolicyTypeToken)
if err != nil {
t.Fatalf("err: %v", err)
}
if pDefaultCeiling == nil {
t.Fatal("nil default ceiling policy")
}
if pDefaultCeiling.Raw != defaultCeilingPolicy {
t.Fatalf("bad: expected\n%s\ngot\n%s\n", defaultCeilingPolicy, pDefaultCeiling.Raw)
}
ctx = namespace.ContextWithNamespace(context.Background(), ns)
err = ps.DeletePolicy(ctx, pDefaultCeiling.Name, PolicyTypeACL)
if err == nil {
t.Fatalf("expected err deleting %s", pDefaultCeiling.Name)
}
ctx = namespace.ContextWithNamespace(context.Background(), ns)
updatedDefaultCeiling, err := ParseACLPolicy(ns, aclPolicy)
if err != nil {
t.Fatalf("err: %v", err)
}
updatedDefaultCeiling.Name = defaultCeilingPolicyName
err = ps.SetPolicy(ctx, updatedDefaultCeiling)
if err != nil {
t.Fatalf("expected err to be nil updating %s: %v", updatedDefaultCeiling.Name, err)
}
ctx = namespace.ContextWithNamespace(context.Background(), ns)
pDefaultCeiling, err = ps.GetPolicy(ctx, defaultCeilingPolicyName, PolicyTypeToken)
if err != nil {
t.Fatalf("err: %v", err)
}
if pDefaultCeiling == nil {
t.Fatal("nil updated default ceiling policy")
}
if pDefaultCeiling.Raw != updatedDefaultCeiling.Raw {
t.Fatalf("bad: expected\n%s\ngot\n%s\n", updatedDefaultCeiling.Raw, pDefaultCeiling.Raw)
}
// Response-wrapping policy checks
ctx = namespace.ContextWithNamespace(context.Background(), ns)
pCubby, err := ps.GetPolicy(ctx, "response-wrapping", PolicyTypeToken)
@ -353,7 +395,7 @@ func TestPolicyStore_PoliciesByNamespaces(t *testing.T) {
t.Fatalf("err: %v", err)
}
expectedResult := []string{"default", "dev"}
expectedResult := []string{defaultPolicyName, defaultCeilingPolicyName, "dev"}
if !reflect.DeepEqual(expectedResult, out) {
t.Fatalf("expected: %v\ngot: %v", expectedResult, out)
}