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

This commit is contained in:
Dan Upton 2021-12-03 20:51:02 +00:00 committed by GitHub
parent aec3747ded
commit 8bb1b89554
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 25 deletions

View File

@ -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
// rules.
func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) {
// rules. Returns true if any elements were removed.
func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) bool {
c := *coords
var authzContext acl.AuthorizerContext
var removed bool
for i := 0; i < len(c); i++ {
c[i].FillAuthzContext(&authzContext)
@ -1417,10 +1418,12 @@ func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) {
continue
}
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:]...)
i--
}
*coords = c
return removed
}
// 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)
case *structs.IndexedCoordinates:
filt.filterCoordinates(&v.Coordinates)
v.QueryMeta.ResultsFilteredByACLs = filt.filterCoordinates(&v.Coordinates)
case *structs.IndexedHealthChecks:
v.QueryMeta.ResultsFilteredByACLs = filt.filterHealthChecks(&v.HealthChecks)

View File

@ -2767,31 +2767,57 @@ service "bar" {
func TestACL_filterCoordinates(t *testing.T) {
t.Parallel()
// Create some coordinates.
coords := structs.Coordinates{
&structs.Coordinate{
Node: "node1",
Coord: generateRandomCoordinate(),
},
&structs.Coordinate{
Node: "node2",
Coord: generateRandomCoordinate(),
logger := hclog.NewNullLogger()
makeList := func() *structs.IndexedCoordinates {
return &structs.IndexedCoordinates{
Coordinates: structs.Coordinates{
{Node: "node1", Coord: generateRandomCoordinate()},
{Node: "node2", Coord: generateRandomCoordinate()},
},
}
// Try permissive filtering.
filt := newACLFilter(acl.AllowAll(), nil)
filt.filterCoordinates(&coords)
if len(coords) != 2 {
t.Fatalf("bad: %#v", coords)
}
// Try restrictive filtering
filt = newACLFilter(acl.DenyAll(), nil)
filt.filterCoordinates(&coords)
if len(coords) != 0 {
t.Fatalf("bad: %#v", coords)
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) {

View File

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