Skip to content

Commit 121f96a

Browse files
authored
consider ANP/BANP in policy deconstructor (#9994)
1 parent 9a6f257 commit 121f96a

File tree

5 files changed

+135
-67
lines changed

5 files changed

+135
-67
lines changed

felix/calc/endpoint_lookup_cache.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
v3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3"
3232
"github.com/projectcalico/calico/libcalico-go/lib/backend/api"
3333
"github.com/projectcalico/calico/libcalico-go/lib/backend/model"
34+
"github.com/projectcalico/calico/libcalico-go/lib/names"
3435
"github.com/projectcalico/calico/libcalico-go/lib/set"
3536
)
3637

@@ -232,7 +233,7 @@ func (ec *EndpointLookupsCache) CreateEndpointData(key model.EndpointKey, ep mod
232233
tdEgress := &TierData{}
233234
var hasIngress, hasEgress bool
234235
for _, pol := range ti.OrderedPolicies {
235-
namespace, tier, name, err := deconstructPolicyName(pol.Key.Name)
236+
namespace, tier, name, err := names.DeconstructPolicyName(pol.Key.Name)
236237
if err != nil {
237238
log.WithError(err).Error("Unable to parse policy name")
238239
continue

felix/calc/policy_lookup_cache.go

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func (pc *PolicyLookupsCache) updatePolicyRulesNFLOGPrefixes(key model.PolicyKey
164164
}
165165
pc.tierRefs[key.Tier] = count + 1
166166

167-
namespace, tier, name, err := deconstructPolicyName(key.Name)
167+
namespace, tier, name, err := names.DeconstructPolicyName(key.Name)
168168
if err != nil {
169169
log.WithError(err).Error("Unable to parse policy name")
170170
return
@@ -567,61 +567,6 @@ func (r *RuleID) GetFlowLogPolicyName() string {
567567
return r.fpName
568568
}
569569

570-
// deconstructPolicyName deconstructs the v1 policy name that is constructed by the SyncerUpdateProcessors in
571-
// libcalico-go and extracts the v3 fields: namespace, tier, name.
572-
//
573-
// The v1 policy name is of the format:
574-
// - <namespace>/<tier>.<name> for a namespaced NetworkPolicies
575-
// - <tier>.<name> for GlobalNetworkPolicies.
576-
// - <namespace>/knp.default.<name> for a k8s NetworkPolicies
577-
// and for the staged counterparts, respectively:
578-
// - <namespace>/staged:<tier>.<name>
579-
// - staged:<tier>.<name>
580-
// - <namespace>/staged:knp.default.<name>
581-
//
582-
// The namespace is returned blank for GlobalNetworkPolicies.
583-
// For k8s network policies, the tier is always "default" and the name will be returned including the
584-
// knp.default prefix.
585-
//
586-
// Staged policies will have the simplified name prefixed with "staged:", eg:
587-
// - <namespace>/staged:<tier>.<name> => Name=staged:<name>, Namespace=<namespace>, Tier=<tier>
588-
// - staged:<tier>.<name> => Name=staged:<name>, Namespace=<namespace>, Tier=<tier>
589-
// - <namespace>/staged:knp.default.<name> => Name=staged:knp.default.<name>, Namespace=<name>, Tier=default
590-
func deconstructPolicyName(name string) (string, string, string, error) {
591-
var namespace string
592-
593-
// Split the name to extract the namespace.
594-
parts := strings.Split(name, "/")
595-
switch len(parts) {
596-
case 1: // GlobalNetworkPolicy
597-
name = parts[0]
598-
case 2: // NetworkPolicy (Calico or Kubernetes)
599-
namespace = parts[0]
600-
name = parts[1]
601-
default:
602-
return "", "", "", fmt.Errorf("could not parse policy %s", name)
603-
}
604-
605-
// Remove the staged prefix if present so we can extract the tier.
606-
var stagedPrefix string
607-
if model.PolicyIsStaged(name) {
608-
stagedPrefix = model.PolicyNamePrefixStaged
609-
name = name[len(model.PolicyNamePrefixStaged):]
610-
}
611-
612-
// If the policy name starts with "knp.default" then this is a kubernetes network policy.
613-
if strings.HasPrefix(name, "knp.default.") {
614-
return namespace, "default", stagedPrefix + name, nil
615-
}
616-
617-
// This is a non-kubernetes policy, so extract the tier name from the policy name.
618-
if parts = strings.SplitN(name, ".", 2); len(parts) == 2 {
619-
return namespace, parts[0], stagedPrefix + parts[1], nil
620-
}
621-
622-
return "", "", "", fmt.Errorf("could not parse policy %s", name)
623-
}
624-
625570
// Dump returns the contents of important structures in the LookupManager used for
626571
// logging purposes in the test code. This should not be used in any mainline code.
627572
func (pc *PolicyLookupsCache) Dump() string {

felix/calc/policy_lookups_cache_test.go

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,46 @@ var (
102102
prefix_knp1_t1_i0D = toprefix("DPI0|namespace-1/knp.default.policy-1.1.1.1")
103103
ruleID_knp1_t1_i0D = NewRuleID("default", "knp.default.policy-1.1.1.1", "namespace-1", 0, rules.RuleDirIngress, rules.RuleActionDeny)
104104

105+
// K8s AdminNetworkPolicy kanp.adminnetworkpolicy.policy-1.1
106+
kanp1_t1_1i0e_key = model.PolicyKey{
107+
Tier: "adminnetworkpolicy",
108+
Name: "kanp.adminnetworkpolicy.policy-1.1.1.1",
109+
}
110+
kanp1_t1_1i0e = &model.Policy{
111+
InboundRules: []model.Rule{
112+
{Action: "deny"},
113+
},
114+
}
115+
prefix_kanp1_t1_i0D = toprefix("DPI0|kanp.adminnetworkpolicy.policy-1.1.1.1")
116+
ruleID_kanp1_t1_i0D = NewRuleID(
117+
"adminnetworkpolicy",
118+
"kanp.adminnetworkpolicy.policy-1.1.1.1",
119+
"",
120+
0,
121+
rules.RuleDirIngress,
122+
rules.RuleActionDeny,
123+
)
124+
125+
// K8s BaselineAdminNetworkPolicy kbanp.baselineadminnetworkpolicy.policy-1.1
126+
kbanp1_t1_1i0e_key = model.PolicyKey{
127+
Tier: "baselineadminnetworkpolicy",
128+
Name: "kbanp.baselineadminnetworkpolicy.policy-1.1.1.1",
129+
}
130+
kbanp1_t1_1i0e = &model.Policy{
131+
InboundRules: []model.Rule{
132+
{Action: "deny"},
133+
},
134+
}
135+
prefix_kbanp1_t1_i0D = toprefix("DPI0|kbanp.baselineadminnetworkpolicy.policy-1.1.1.1")
136+
ruleID_kbanp1_t1_i0D = NewRuleID(
137+
"baselineadminnetworkpolicy",
138+
"kbanp.baselineadminnetworkpolicy.policy-1.1.1.1",
139+
"",
140+
0,
141+
rules.RuleDirIngress,
142+
rules.RuleActionDeny,
143+
)
144+
105145
// Profile profile-1
106146
pr1_1i1e_key = model.ProfileRulesKey{
107147
ProfileKey: model.ProfileKey{Name: "profile-1"},
@@ -120,14 +160,22 @@ var (
120160
ruleID_prof_e0D = NewRuleID("", "profile-1", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
121161

122162
// Tier no-matches
123-
prefix_nomatch_t1_i = toprefix("DPI|tier-1")
124-
ruleID_nomatch_t1_i = NewRuleID("tier-1", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
125-
prefix_nomatch_t1_e = toprefix("DPE|tier-1")
126-
ruleID_nomatch_t1_e = NewRuleID("tier-1", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
127-
prefix_nomatch_td_i = toprefix("DPI|default")
128-
ruleID_nomatch_td_i = NewRuleID("default", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
129-
prefix_nomatch_td_e = toprefix("DPE|default")
130-
ruleID_nomatch_td_e = NewRuleID("default", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
163+
prefix_nomatch_t1_i = toprefix("DPI|tier-1")
164+
ruleID_nomatch_t1_i = NewRuleID("tier-1", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
165+
prefix_nomatch_t1_e = toprefix("DPE|tier-1")
166+
ruleID_nomatch_t1_e = NewRuleID("tier-1", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
167+
prefix_nomatch_td_i = toprefix("DPI|default")
168+
ruleID_nomatch_td_i = NewRuleID("default", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
169+
prefix_nomatch_td_e = toprefix("DPE|default")
170+
ruleID_nomatch_td_e = NewRuleID("default", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
171+
prefix_nomatch_tanp_i = toprefix("DPI|adminnetworkpolicy")
172+
ruleID_nomatch_tanp_i = NewRuleID("adminnetworkpolicy", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
173+
prefix_nomatch_tanp_e = toprefix("DPE|adminnetworkpolicy")
174+
ruleID_nomatch_tanp_e = NewRuleID("adminnetworkpolicy", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
175+
prefix_nomatch_tbanp_i = toprefix("DPI|baselineadminnetworkpolicy")
176+
ruleID_nomatch_tbanp_i = NewRuleID("baselineadminnetworkpolicy", "", "", 0, rules.RuleDirIngress, rules.RuleActionDeny)
177+
prefix_nomatch_tbanp_e = toprefix("DPE|baselineadminnetworkpolicy")
178+
ruleID_nomatch_tbanp_e = NewRuleID("baselineadminnetworkpolicy", "", "", 0, rules.RuleDirEgress, rules.RuleActionDeny)
131179

132180
// Profile no-matches
133181
prefix_nomatch_prof_i = toprefix("DRI")
@@ -181,6 +229,12 @@ var _ = Describe("PolicyLookupsCache tests", func() {
181229
Entry("KNP1 (1i0e) no match default ingress", knp1_t1_1i0e_key, knp1_t1_1i0e, prefix_nomatch_td_i, ruleID_nomatch_td_i),
182230
Entry("KNP1 (1i0e) no match default egress", knp1_t1_1i0e_key, knp1_t1_1i0e, prefix_nomatch_td_e, ruleID_nomatch_td_e),
183231
Entry("KNP1 (1i0e) i0", knp1_t1_1i0e_key, knp1_t1_1i0e, prefix_knp1_t1_i0D, ruleID_knp1_t1_i0D),
232+
Entry("KANP1 (1i0e) no match default ingress", kanp1_t1_1i0e_key, kanp1_t1_1i0e, prefix_nomatch_tanp_i, ruleID_nomatch_tanp_i),
233+
Entry("KANP1 (1i0e) no match default egress", kanp1_t1_1i0e_key, kanp1_t1_1i0e, prefix_nomatch_tanp_e, ruleID_nomatch_tanp_e),
234+
Entry("KANP1 (1i0e) i0", kanp1_t1_1i0e_key, kanp1_t1_1i0e, prefix_kanp1_t1_i0D, ruleID_kanp1_t1_i0D),
235+
Entry("KBANP1 (1i0e) no match default ingress", kbanp1_t1_1i0e_key, kbanp1_t1_1i0e, prefix_nomatch_tbanp_i, ruleID_nomatch_tbanp_i),
236+
Entry("KBANP1 (1i0e) no match default egress", kbanp1_t1_1i0e_key, kbanp1_t1_1i0e, prefix_nomatch_tbanp_e, ruleID_nomatch_tbanp_e),
237+
Entry("KBANP1 (1i0e) i0", kbanp1_t1_1i0e_key, kbanp1_t1_1i0e, prefix_kbanp1_t1_i0D, ruleID_kbanp1_t1_i0D),
184238
)
185239

186240
DescribeTable(

libcalico-go/lib/names/policy.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"errors"
1919
"fmt"
2020
"strings"
21+
22+
"github.com/projectcalico/calico/libcalico-go/lib/backend/model"
2123
)
2224

2325
const (
@@ -155,3 +157,68 @@ func TierOrDefault(tier string) string {
155157
return tier
156158
}
157159
}
160+
161+
// deconstructPolicyName deconstructs the v1 policy name that is constructed by the SyncerUpdateProcessors in
162+
// libcalico-go and extracts the v3 fields: namespace, tier, name.
163+
//
164+
// The v1 policy name is of the format:
165+
// - <namespace>/<tier>.<name> for a namespaced NetworkPolicies
166+
// - <tier>.<name> for GlobalNetworkPolicies.
167+
// - <namespace>/knp.default.<name> for a k8s NetworkPolicies
168+
// - kanp.adminnetworkpolicy.<name> for a k8s AdminNetworkPolicies
169+
// - kbanp.baselineadminnetworkpolicy.<name> for a k8s BaselineAdminNetworkPolicies
170+
// and for the staged counterparts, respectively:
171+
// - <namespace>/staged:<tier>.<name>
172+
// - staged:<tier>.<name>
173+
// - <namespace>/staged:knp.default.<name>
174+
//
175+
// The namespace is returned blank for GlobalNetworkPolicies.
176+
// For k8s network policies, the tier is always "default" and the name will be returned including the
177+
// knp.default prefix.
178+
//
179+
// Staged policies will have the simplified name prefixed with "staged:", eg:
180+
// - <namespace>/staged:<tier>.<name> => Name=staged:<name>, Namespace=<namespace>, Tier=<tier>
181+
// - staged:<tier>.<name> => Name=staged:<name>, Namespace=<namespace>, Tier=<tier>
182+
// - <namespace>/staged:knp.default.<name> => Name=staged:knp.default.<name>, Namespace=<name>, Tier=default
183+
func DeconstructPolicyName(name string) (string, string, string, error) {
184+
var namespace string
185+
186+
// Split the name to extract the namespace.
187+
parts := strings.Split(name, "/")
188+
switch len(parts) {
189+
case 1: // GlobalNetworkPolicy
190+
name = parts[0]
191+
case 2: // NetworkPolicy (Calico or Kubernetes)
192+
namespace = parts[0]
193+
name = parts[1]
194+
default:
195+
return "", "", "", fmt.Errorf("could not parse policy %s", name)
196+
}
197+
198+
// Remove the staged prefix if present so we can extract the tier.
199+
var stagedPrefix string
200+
if model.PolicyIsStaged(name) {
201+
stagedPrefix = model.PolicyNamePrefixStaged
202+
name = name[len(model.PolicyNamePrefixStaged):]
203+
}
204+
205+
// If policy name starts with "knp.default" then this is k8s network policy.
206+
if strings.HasPrefix(name, K8sNetworkPolicyNamePrefix) {
207+
return namespace, DefaultTierName, stagedPrefix + name, nil
208+
}
209+
// If policy name starts with "kanp.adminnetworkpolicy" then this is k8s admin network policy.
210+
if strings.HasPrefix(name, K8sAdminNetworkPolicyNamePrefix) {
211+
return namespace, AdminNetworkPolicyTierName, stagedPrefix + name, nil
212+
}
213+
// If policy name starts with "kbanp.baselineadminnetworkpolicy" then this is k8s baseline admin network policy.
214+
if strings.HasPrefix(name, K8sBaselineAdminNetworkPolicyNamePrefix) {
215+
return namespace, BaselineAdminNetworkPolicyTierName, stagedPrefix + name, nil
216+
}
217+
218+
// This is a non-kubernetes policy, so extract the tier name from the policy name.
219+
if parts = strings.SplitN(name, ".", 2); len(parts) == 2 {
220+
return namespace, parts[0], stagedPrefix + parts[1], nil
221+
}
222+
223+
return "", "", "", fmt.Errorf("could not parse policy %s", name)
224+
}

libcalico-go/lib/upgrade/migrator/migrate.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2017-2018 Tigera, Inc. All rights reserved.
1+
// Copyright (c) 2017-2025 Tigera, Inc. All rights reserved.
22

33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import (
3434
"github.com/projectcalico/calico/libcalico-go/lib/backend/model"
3535
"github.com/projectcalico/calico/libcalico-go/lib/clientv3"
3636
cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors"
37+
"github.com/projectcalico/calico/libcalico-go/lib/names"
3738
"github.com/projectcalico/calico/libcalico-go/lib/options"
3839
"github.com/projectcalico/calico/libcalico-go/lib/upgrade/converters"
3940
"github.com/projectcalico/calico/libcalico-go/lib/upgrade/migrator/clients"
@@ -372,7 +373,7 @@ var noFilter = func(_ model.Key) bool { return false }
372373
// Filter to filter out K8s backed network policies
373374
var filterGNP = func(k model.Key) bool {
374375
gk := k.(model.PolicyKey)
375-
return strings.HasPrefix(gk.Name, "knp.default.")
376+
return strings.HasPrefix(gk.Name, names.K8sNetworkPolicyNamePrefix)
376377
}
377378

378379
// Filter to filter out K8s (namespace) and OpenStack backed profiles

0 commit comments

Comments
 (0)