From 9c04cbc40fdad04dcaad8758dca3c4033435ff5d Mon Sep 17 00:00:00 2001 From: Freddy Date: Fri, 23 Oct 2020 10:45:41 -0600 Subject: [PATCH] Add HasExact to topology endpoint (#9010) --- agent/consul/internal_endpoint_test.go | 10 ++++++++++ agent/consul/state/intention.go | 6 ++++++ agent/consul/state/intention_test.go | 23 +++++++++++++++++++++++ agent/structs/intention.go | 4 +++- agent/ui_endpoint.go | 4 ++-- agent/ui_endpoint_test.go | 14 +++++++++++++- 6 files changed, 57 insertions(+), 4 deletions(-) diff --git a/agent/consul/internal_endpoint_test.go b/agent/consul/internal_endpoint_test.go index 2fac2eb28e..cc919c19e3 100644 --- a/agent/consul/internal_endpoint_test.go +++ b/agent/consul/internal_endpoint_test.go @@ -1622,6 +1622,8 @@ func TestInternal_ServiceTopology(t *testing.T) { // web and web-proxy on node bar - upstream: redis // web and web-proxy on node baz - upstream: redis // redis and redis-proxy on node zip + // wildcard deny intention + // web -> redis exact intentino registerTestTopologyEntries(t, codec, "") var ( @@ -1650,6 +1652,9 @@ func TestInternal_ServiceTopology(t *testing.T) { Allowed: false, HasPermissions: false, ExternalSource: "nomad", + + // From wildcard deny + HasExact: false, }, } require.Equal(r, expectUp, out.ServiceTopology.UpstreamDecisions) @@ -1675,6 +1680,9 @@ func TestInternal_ServiceTopology(t *testing.T) { Allowed: false, HasPermissions: false, ExternalSource: "nomad", + + // From wildcard deny + HasExact: false, }, } require.Equal(r, expectDown, out.ServiceTopology.DownstreamDecisions) @@ -1686,6 +1694,7 @@ func TestInternal_ServiceTopology(t *testing.T) { redis.String(): { Allowed: false, HasPermissions: true, + HasExact: true, }, } require.Equal(r, expectUp, out.ServiceTopology.UpstreamDecisions) @@ -1712,6 +1721,7 @@ func TestInternal_ServiceTopology(t *testing.T) { web.String(): { Allowed: false, HasPermissions: true, + HasExact: true, }, } require.Equal(r, expectDown, out.ServiceTopology.DownstreamDecisions) diff --git a/agent/consul/state/intention.go b/agent/consul/state/intention.go index 8381f048d7..59a82e76c8 100644 --- a/agent/consul/state/intention.go +++ b/agent/consul/state/intention.go @@ -500,6 +500,12 @@ func (s *Store) IntentionDecision( } resp.ExternalSource = ixnMatch.Meta[structs.MetaExternalSource] + // Intentions with wildcard namespaces but specific names are not allowed (*/web -> */api) + // So we don't check namespaces to see if there's an exact intention + if ixnMatch.SourceName != structs.WildcardSpecifier && ixnMatch.DestinationName != structs.WildcardSpecifier { + resp.HasExact = true + } + return resp, nil } diff --git a/agent/consul/state/intention_test.go b/agent/consul/state/intention_test.go index 1b14daecf8..43637424d8 100644 --- a/agent/consul/state/intention_test.go +++ b/agent/consul/state/intention_test.go @@ -1132,6 +1132,16 @@ func TestStore_IntentionDecision(t *testing.T) { }, }, }, + &structs.ServiceIntentionsConfigEntry{ + Kind: structs.ServiceIntentions, + Name: "mysql", + Sources: []*structs.SourceIntention{ + { + Name: "*", + Action: structs.IntentionActionAllow, + }, + }, + }, } s := testConfigStateStore(t) @@ -1167,6 +1177,7 @@ func TestStore_IntentionDecision(t *testing.T) { expect: structs.IntentionDecisionSummary{ Allowed: false, HasPermissions: true, + HasExact: true, }, }, { @@ -1176,6 +1187,7 @@ func TestStore_IntentionDecision(t *testing.T) { expect: structs.IntentionDecisionSummary{ Allowed: false, HasPermissions: false, + HasExact: true, }, }, { @@ -1186,6 +1198,17 @@ func TestStore_IntentionDecision(t *testing.T) { Allowed: true, HasPermissions: false, ExternalSource: "nomad", + HasExact: true, + }, + }, + { + name: "allowed by source wildcard not exact", + src: "anything", + dst: "mysql", + expect: structs.IntentionDecisionSummary{ + Allowed: true, + HasPermissions: false, + HasExact: false, }, }, } diff --git a/agent/structs/intention.go b/agent/structs/intention.go index 800f7c1f27..29d2811a20 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -645,11 +645,13 @@ type IntentionQueryCheckResponse struct { // Currently contains: // - Whether all actions are allowed // - Whether the matching intention has L7 permissions attached -// - Whether the intention is managed by an external source like k8s, +// - Whether the intention is managed by an external source like k8s +// - Whether there is an exact, on-wildcard, intention referencing the two services type IntentionDecisionSummary struct { Allowed bool HasPermissions bool ExternalSource string + HasExact bool } // IntentionQueryExact holds the parameters for performing a lookup of an diff --git a/agent/ui_endpoint.go b/agent/ui_endpoint.go index 07729d99b3..842f45cae9 100644 --- a/agent/ui_endpoint.go +++ b/agent/ui_endpoint.go @@ -316,8 +316,8 @@ RPC: downstreams, _ := summarizeServices(out.ServiceTopology.Downstreams.ToServiceDump(), nil, "") var ( - upstreamResp []*ServiceTopologySummary - downstreamResp []*ServiceTopologySummary + upstreamResp = make([]*ServiceTopologySummary, 0) + downstreamResp = make([]*ServiceTopologySummary, 0) ) // Sort and attach intention data for upstreams and downstreams diff --git a/agent/ui_endpoint_test.go b/agent/ui_endpoint_test.go index 784b6e0db9..966ac12547 100644 --- a/agent/ui_endpoint_test.go +++ b/agent/ui_endpoint_test.go @@ -1369,9 +1369,11 @@ func TestUIServiceTopology(t *testing.T) { Intention: structs.IntentionDecisionSummary{ Allowed: true, HasPermissions: false, + HasExact: true, }, }, }, + Downstreams: []*ServiceTopologySummary{}, FilteredByACLs: false, } result := obj.(ServiceTopology) @@ -1410,6 +1412,7 @@ func TestUIServiceTopology(t *testing.T) { Intention: structs.IntentionDecisionSummary{ Allowed: true, HasPermissions: false, + HasExact: true, }, }, }, @@ -1429,6 +1432,9 @@ func TestUIServiceTopology(t *testing.T) { Allowed: false, HasPermissions: false, ExternalSource: "nomad", + + // From wildcard deny + HasExact: false, }, }, }, @@ -1474,6 +1480,7 @@ func TestUIServiceTopology(t *testing.T) { Intention: structs.IntentionDecisionSummary{ Allowed: false, HasPermissions: true, + HasExact: true, }, }, }, @@ -1491,6 +1498,9 @@ func TestUIServiceTopology(t *testing.T) { Allowed: false, HasPermissions: false, ExternalSource: "nomad", + + // From wildcard deny + HasExact: false, }, }, }, @@ -1521,7 +1531,8 @@ func TestUIServiceTopology(t *testing.T) { require.NoError(r, checkIndex(resp)) expect := ServiceTopology{ - Protocol: "http", + Protocol: "http", + Upstreams: []*ServiceTopologySummary{}, Downstreams: []*ServiceTopologySummary{ { ServiceSummary: ServiceSummary{ @@ -1537,6 +1548,7 @@ func TestUIServiceTopology(t *testing.T) { Intention: structs.IntentionDecisionSummary{ Allowed: false, HasPermissions: true, + HasExact: true, }, }, },