coordinate: support `ResultsFilteredByACLs` flag/header (#11617)

pull/10778/head
Dan Upton 3 years ago committed by GitHub
parent eb90c7f3ad
commit 4c0956c03a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1405,10 +1405,11 @@ func (f *aclFilter) filterSessions(sessions *structs.Sessions) bool {
} }
// filterCoordinates is used to filter nodes in a coordinate dump based on ACL // filterCoordinates is used to filter nodes in a coordinate dump based on ACL
// rules. // rules. Returns true if any elements were removed.
func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) { func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) bool {
c := *coords c := *coords
var authzContext acl.AuthorizerContext var authzContext acl.AuthorizerContext
var removed bool
for i := 0; i < len(c); i++ { for i := 0; i < len(c); i++ {
c[i].FillAuthzContext(&authzContext) c[i].FillAuthzContext(&authzContext)
@ -1417,10 +1418,12 @@ func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) {
continue continue
} }
f.logger.Debug("dropping node from result due to ACLs", "node", structs.NodeNameString(node, c[i].GetEnterpriseMeta())) f.logger.Debug("dropping node from result due to ACLs", "node", structs.NodeNameString(node, c[i].GetEnterpriseMeta()))
removed = true
c = append(c[:i], c[i+1:]...) c = append(c[:i], c[i+1:]...)
i-- i--
} }
*coords = c *coords = c
return removed
} }
// filterIntentions is used to filter intentions based on ACL rules. // filterIntentions is used to filter intentions based on ACL rules.
@ -1827,7 +1830,7 @@ func filterACLWithAuthorizer(logger hclog.Logger, authorizer acl.Authorizer, sub
filt.filterDatacenterCheckServiceNodes(&v.DatacenterNodes) filt.filterDatacenterCheckServiceNodes(&v.DatacenterNodes)
case *structs.IndexedCoordinates: case *structs.IndexedCoordinates:
filt.filterCoordinates(&v.Coordinates) v.QueryMeta.ResultsFilteredByACLs = filt.filterCoordinates(&v.Coordinates)
case *structs.IndexedHealthChecks: case *structs.IndexedHealthChecks:
v.QueryMeta.ResultsFilteredByACLs = filt.filterHealthChecks(&v.HealthChecks) v.QueryMeta.ResultsFilteredByACLs = filt.filterHealthChecks(&v.HealthChecks)

@ -2767,31 +2767,57 @@ service "bar" {
func TestACL_filterCoordinates(t *testing.T) { func TestACL_filterCoordinates(t *testing.T) {
t.Parallel() t.Parallel()
// Create some coordinates.
coords := structs.Coordinates{
&structs.Coordinate{
Node: "node1",
Coord: generateRandomCoordinate(),
},
&structs.Coordinate{
Node: "node2",
Coord: generateRandomCoordinate(),
},
}
// Try permissive filtering. logger := hclog.NewNullLogger()
filt := newACLFilter(acl.AllowAll(), nil)
filt.filterCoordinates(&coords)
if len(coords) != 2 {
t.Fatalf("bad: %#v", coords)
}
// Try restrictive filtering makeList := func() *structs.IndexedCoordinates {
filt = newACLFilter(acl.DenyAll(), nil) return &structs.IndexedCoordinates{
filt.filterCoordinates(&coords) Coordinates: structs.Coordinates{
if len(coords) != 0 { {Node: "node1", Coord: generateRandomCoordinate()},
t.Fatalf("bad: %#v", coords) {Node: "node2", Coord: generateRandomCoordinate()},
},
}
} }
t.Run("allowed", func(t *testing.T) {
require := require.New(t)
list := makeList()
filterACLWithAuthorizer(logger, acl.AllowAll(), list)
require.Len(list.Coordinates, 2)
require.False(list.QueryMeta.ResultsFilteredByACLs, "ResultsFilteredByACLs should be false")
})
t.Run("allowed to read one node", func(t *testing.T) {
require := require.New(t)
policy, err := acl.NewPolicyFromSource(`
node "node1" {
policy = "read"
}
`, acl.SyntaxLegacy, nil, nil)
require.NoError(err)
authz, err := acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), []*acl.Policy{policy}, nil)
require.NoError(err)
list := makeList()
filterACLWithAuthorizer(logger, authz, list)
require.Len(list.Coordinates, 1)
require.True(list.QueryMeta.ResultsFilteredByACLs, "ResultsFilteredByACLs should be true")
})
t.Run("denied", func(t *testing.T) {
require := require.New(t)
list := makeList()
filterACLWithAuthorizer(logger, acl.DenyAll(), list)
require.Empty(list.Coordinates)
require.True(list.QueryMeta.ResultsFilteredByACLs, "ResultsFilteredByACLs should be true")
})
} }
func TestACL_filterSessions(t *testing.T) { func TestACL_filterSessions(t *testing.T) {

@ -452,6 +452,9 @@ func TestCoordinate_ListNodes_ACLFilter(t *testing.T) {
if len(resp.Coordinates) != 1 || resp.Coordinates[0].Node != "foo" { if len(resp.Coordinates) != 1 || resp.Coordinates[0].Node != "foo" {
t.Fatalf("bad: %#v", resp.Coordinates) t.Fatalf("bad: %#v", resp.Coordinates)
} }
if !resp.QueryMeta.ResultsFilteredByACLs {
t.Fatal("ResultsFilteredByACLs should be true")
}
} }
func TestCoordinate_Node(t *testing.T) { func TestCoordinate_Node(t *testing.T) {

Loading…
Cancel
Save