diff --git a/agent/consul/state/catalog.go b/agent/consul/state/catalog.go index 40bd733749..1cb6c59dfb 100644 --- a/agent/consul/state/catalog.go +++ b/agent/consul/state/catalog.go @@ -2869,12 +2869,12 @@ func (s *Store) ServiceTopology( Name: service, } // The given service is a source relative to its upstreams - _, intentions, err := s.IntentionMatchOne(ws, matchEntry, structs.IntentionMatchSource) + _, srcIntentions, err := compatIntentionMatchOneTxn(tx, ws, matchEntry, structs.IntentionMatchSource) if err != nil { return 0, nil, fmt.Errorf("failed to query intentions for %s", sn.String()) } for _, un := range upstreamNames { - decision, err := s.IntentionDecision(un.Name, un.NamespaceOrDefault(), intentions, structs.IntentionMatchDestination, defaultAllow, false) + decision, err := s.IntentionDecision(un.Name, un.NamespaceOrDefault(), srcIntentions, structs.IntentionMatchDestination, defaultAllow, false) if err != nil { return 0, nil, fmt.Errorf("failed to get intention decision from (%s) to (%s): %v", sn.String(), un.String(), err) @@ -2898,13 +2898,13 @@ func (s *Store) ServiceTopology( } // The given service is a destination relative to its downstreams - _, intentions, err = s.IntentionMatchOne(ws, matchEntry, structs.IntentionMatchDestination) + _, dstIntentions, err := compatIntentionMatchOneTxn(tx, ws, matchEntry, structs.IntentionMatchDestination) if err != nil { return 0, nil, fmt.Errorf("failed to query intentions for %s", sn.String()) } downstreamDecisions := make(map[string]structs.IntentionDecisionSummary) for _, dn := range downstreamNames { - decision, err := s.IntentionDecision(dn.Name, dn.NamespaceOrDefault(), intentions, structs.IntentionMatchSource, defaultAllow, false) + decision, err := s.IntentionDecision(dn.Name, dn.NamespaceOrDefault(), dstIntentions, structs.IntentionMatchSource, defaultAllow, false) if err != nil { return 0, nil, fmt.Errorf("failed to get intention decision from (%s) to (%s): %v", dn.String(), sn.String(), err) diff --git a/agent/consul/state/intention.go b/agent/consul/state/intention.go index bedf8be3cd..2d2d87bb9b 100644 --- a/agent/consul/state/intention.go +++ b/agent/consul/state/intention.go @@ -760,8 +760,8 @@ func (s *Store) IntentionDecision( // Intention found, combine action + permissions resp.Allowed = ixnMatch.Action == structs.IntentionActionAllow if len(ixnMatch.Permissions) > 0 { - // If there are L7 permissions, DENY. - // We are only evaluating source and destination, not the request that will be sent. + // If any permissions are present, fall back to allowPermissions. + // We are not evaluating requests so we cannot know whether the L7 permission requirements will be met. resp.Allowed = allowPermissions resp.HasPermissions = true } @@ -837,6 +837,16 @@ func (s *Store) IntentionMatchOne( tx := s.db.Txn(false) defer tx.Abort() + return compatIntentionMatchOneTxn(tx, ws, entry, matchType) +} + +func compatIntentionMatchOneTxn( + tx ReadTxn, + ws memdb.WatchSet, + entry structs.IntentionMatchEntry, + matchType structs.IntentionMatchType, +) (uint64, structs.Intentions, error) { + usingConfigEntries, err := areIntentionsInConfigEntries(tx, ws) if err != nil { return 0, nil, err @@ -926,6 +936,9 @@ func intentionMatchGetParams(entry structs.IntentionMatchEntry) ([][]interface{} // an upstream of the target. func (s *Store) IntentionTopology(ws memdb.WatchSet, target structs.ServiceName, downstreams bool, defaultDecision acl.EnforcementDecision) (uint64, structs.ServiceList, error) { + tx := s.db.ReadTxn() + defer tx.Abort() + var maxIdx uint64 // If querying the upstreams for a service, we first query intentions that apply to the target service as a source. @@ -938,7 +951,7 @@ func (s *Store) IntentionTopology(ws memdb.WatchSet, Namespace: target.NamespaceOrDefault(), Name: target.Name, } - index, intentions, err := s.IntentionMatchOne(ws, entry, matchType) + index, intentions, err := compatIntentionMatchOneTxn(tx, ws, entry, matchType) if err != nil { return 0, nil, fmt.Errorf("failed to query intentions for %s", target.String()) }