Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
mazdakn committed Sep 13, 2024
1 parent ccfd4b8 commit 43d804b
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 175 deletions.
6 changes: 6 additions & 0 deletions felix/bpf/polprog/pol_prog_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/projectcalico/calico/felix/bpf/ipsets"
"github.com/projectcalico/calico/felix/bpf/maps"
"github.com/projectcalico/calico/libcalico-go/lib/names"

log "github.com/sirupsen/logrus"

Expand Down Expand Up @@ -484,6 +485,7 @@ func (p *Builder) writeTiers(tiers []Tier, destLeg matchLeg, allowLabel string)
actionLabels := map[string]string{
"allow": allowLabel,
"deny": "deny",
"pass": "pass",
}
for _, tier := range tiers {
endOfTierLabel := fmt.Sprint("end_of_tier_", p.tierID)
Expand All @@ -502,6 +504,10 @@ func (p *Builder) writeTiers(tiers []Tier, destLeg matchLeg, allowLabel string)
action = TierEndDeny
}
p.b.AddCommentF("End of tier %s", tier.Name)
// For AdminNetworkPolicy Tier the endOfTier action is pass.
if tier.Name != names.AdminNetworkPolicyTierName {
action = TierEndPass
}
log.Debugf("End of tier %d %q: %s", p.tierID, tier.Name, action)
p.writeRule(Rule{
Rule: &proto.Rule{},
Expand Down
6 changes: 3 additions & 3 deletions felix/rules/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/projectcalico/calico/felix/hashutils"
"github.com/projectcalico/calico/felix/iptables"
"github.com/projectcalico/calico/felix/proto"
"github.com/projectcalico/calico/libcalico-go/lib/names"
)

const (
Expand Down Expand Up @@ -463,10 +464,9 @@ func (r *DefaultRuleRenderer) endpointIptablesChain(
Comment: []string{"Start of tier " + tier.Name},
})

// Track if any of the policies are not staged. If all of the policies in a tier are staged
// then the default end of tier behavior should be pass rather than drop.
endOfTierDrop := true
if tier.Name == "adminnetworkpolicy" {
// For AdminNetworkPolicy Tier the endOfTier action is pass.
if tier.Name == names.AdminNetworkPolicyTierName {
endOfTierDrop = false
}

Expand Down
232 changes: 188 additions & 44 deletions libcalico-go/lib/backend/k8s/conversion/adminnetworkpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ var _ = Describe("Test AdminNetworkPolicy conversion", func() {
Expect(gnp.Spec.Types[0]).To(Equal(apiv3.PolicyTypeEgress))
})

It("should parse an AdminNetworkPolicy with a rule with nil namespaceSelector", func() {
It("should faild parsing an AdminNetworkPolicy with a rule with neither namespaces or pods set", func() {
anp := adminpolicy.AdminNetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "test.policy",
Expand All @@ -1140,76 +1140,68 @@ var _ = Describe("Test AdminNetworkPolicy conversion", func() {
From: []adminpolicy.AdminNetworkPolicyIngressPeer{
{
Namespaces: nil,
Pods: nil,
},
},
},
},
Egress: []adminpolicy.AdminNetworkPolicyEgressRule{
{
Name: "A random egress rule",
Action: "Pass",
To: []adminpolicy.AdminNetworkPolicyEgressPeer{
{
Namespaces: nil,
Pods: nil,
},
},
},
},
},
}

gnp := convertToGNP(&anp, float64(600.0), nil)

Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && label == 'value'"))
Expect(gnp.Spec.NamespaceSelector).To(Equal("all()"))

Expect(len(gnp.Spec.Ingress)).To(Equal(1))
Expect(gnp.Spec.Ingress[0].Source.Selector).To(BeZero())
Expect(gnp.Spec.Ingress[0].Source.NamespaceSelector).To(BeZero())

// There should be no Egress rules.
Expect(gnp.Spec.Egress).To(HaveLen(0))

// Check that Types field exists and has only 'ingress'
Expect(len(gnp.Spec.Types)).To(Equal(1))
Expect(gnp.Spec.Types[0]).To(Equal(apiv3.PolicyTypeIngress))
})

It("should parse an AdminNetworkPolicy with a rule with nil podSelector", func() {
anp := adminpolicy.AdminNetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "test.policy",
UID: types.UID("30316465-6365-4463-ad63-3564622d3638"),
},
Spec: adminpolicy.AdminNetworkPolicySpec{
Priority: 600,
Subject: adminpolicy.AdminNetworkPolicySubject{
Pods: &adminpolicy.NamespacedPod{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
expectedErr := cerrors.ErrorAdminPolicyConversion{
PolicyName: "test.policy",
Rules: []cerrors.ErrorAdminPolicyConversionRule{
{
EgressRule: nil,
IngressRule: &adminpolicy.AdminNetworkPolicyIngressRule{
Name: "A random ingress rule",
Action: "Allow",
From: []adminpolicy.AdminNetworkPolicyIngressPeer{
{
Namespaces: nil,
Pods: nil,
},
},
},
Reason: "k8s rule couldn't be converted: none of supported fields in 'From' is set.",
},
Egress: []adminpolicy.AdminNetworkPolicyEgressRule{
{
{
IngressRule: nil,
EgressRule: &adminpolicy.AdminNetworkPolicyEgressRule{
Name: "A random egress rule",
Action: "Pass",
To: []adminpolicy.AdminNetworkPolicyEgressPeer{
{
Pods: nil,
Namespaces: nil,
Pods: nil,
},
},
},
Reason: "k8s rule couldn't be converted: none of supported fields in 'From' is set.",
},
},
}

gnp := convertToGNP(&anp, float64(600.0), nil)
gnp := convertToGNP(&anp, float64(600.0), &expectedErr)

Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && label == 'value'"))
Expect(gnp.Spec.NamespaceSelector).To(Equal("all()"))

Expect(len(gnp.Spec.Egress)).To(Equal(1))
Expect(gnp.Spec.Egress[0].Destination.Selector).To(BeZero())
Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(BeZero())

// There should be no Ingress rules.
// There should be no rules.
Expect(gnp.Spec.Ingress).To(HaveLen(0))

// Check that Types field exists and has only 'ingress'
Expect(len(gnp.Spec.Types)).To(Equal(1))
Expect(gnp.Spec.Types[0]).To(Equal(apiv3.PolicyTypeEgress))
Expect(gnp.Spec.Egress).To(HaveLen(0))
})

It("should parse an AdminNetworkPolicy with a rule with empty namespaceSelector", func() {
Expand Down Expand Up @@ -1411,4 +1403,156 @@ var _ = Describe("Test AdminNetworkPolicy conversion", func() {
// There should be no Egress rules
Expect(gnp.Spec.Egress).To(HaveLen(0))
})

It("should replace an unsupported AdminNeworkPolicy rule with Deny action with a deny-all one", func() {
ports := []adminpolicy.AdminNetworkPolicyPort{{
PortNumber: &adminpolicy.Port{Port: 80},
}}

badPorts := []adminpolicy.AdminNetworkPolicyPort{{
PortRange: &adminpolicy.PortRange{Start: 40, End: 20, Protocol: kapiv1.ProtocolUDP},
}}
anp := adminpolicy.AdminNetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "test.policy",
UID: types.UID("30316465-6365-4463-ad63-3564622d3638"),
},
Spec: adminpolicy.AdminNetworkPolicySpec{
Priority: 600,
Subject: adminpolicy.AdminNetworkPolicySubject{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
"label2": "value2",
},
},
},
Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{
{
Name: "A random ingress rule",
Action: "Pass",
Ports: &ports,
From: []adminpolicy.AdminNetworkPolicyIngressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{
"k": "v",
},
},
},
},
},
{
Name: "A random ingress rule 2",
Action: "Pass",
Ports: &badPorts,
From: []adminpolicy.AdminNetworkPolicyIngressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{
"k": "v",
},
},
},
},
},
},
Egress: []adminpolicy.AdminNetworkPolicyEgressRule{
{
Name: "A random egress rule",
Action: "Deny",
Ports: &badPorts,
To: []adminpolicy.AdminNetworkPolicyEgressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{
"k3": "v3",
},
},
},
},
},
{
Name: "A random egress rule 2",
Action: "Deny",
Ports: &ports,
To: []adminpolicy.AdminNetworkPolicyEgressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{
"k4": "v4",
},
},
},
},
},
},
},
}

expectedErr := cerrors.ErrorAdminPolicyConversion{
PolicyName: "test.policy",
Rules: []cerrors.ErrorAdminPolicyConversionRule{
{
EgressRule: nil,
IngressRule: &adminpolicy.AdminNetworkPolicyIngressRule{
Name: "A random ingress rule 2",
Action: "Pass",
Ports: &badPorts,
From: []adminpolicy.AdminNetworkPolicyIngressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{"k": "v"},
MatchExpressions: nil,
},
Pods: nil,
},
},
},
Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (40) is greater than maximum port number (20) in port range",
},
{
IngressRule: nil,
EgressRule: &adminpolicy.AdminNetworkPolicyEgressRule{
Name: "A random egress rule",
Action: "Deny",
Ports: &badPorts,
To: []adminpolicy.AdminNetworkPolicyEgressPeer{
{
Namespaces: &metav1.LabelSelector{
MatchLabels: map[string]string{"k3": "v3"},
MatchExpressions: nil,
},
Pods: nil,
},
},
},
Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (40) is greater than maximum port number (20) in port range",
},
},
}

gnp := convertToGNP(&anp, float64(600.0), &expectedErr)

Expect(gnp.Spec.NamespaceSelector).To(Equal("label == 'value' && label2 == 'value2'"))

Expect(len(gnp.Spec.Ingress)).To(Equal(1))
Expect(gnp.Spec.Ingress[0].Source.NamespaceSelector).To(Equal("k == 'v'"))
Expect(gnp.Spec.Ingress[0].Destination.Ports).To(Equal([]numorstring.Port{numorstring.SinglePort(80)}))

Expect(gnp.Spec.Egress).To(HaveLen(2))
Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(BeZero())
Expect(gnp.Spec.Egress[0]).To(Equal(apiv3.Rule{
Action: apiv3.Deny,
}))

Expect(gnp.Spec.Egress[1].Destination.NamespaceSelector).To(Equal("k4 == 'v4'"))
Expect(gnp.Spec.Egress[1].Destination.Selector).To(BeZero())
Expect(gnp.Spec.Egress[1].Destination.Ports).To(Equal([]numorstring.Port{numorstring.SinglePort(80)}))

// Check that Types field exists and has only 'ingress'
Expect(len(gnp.Spec.Types)).To(Equal(2))
Expect(gnp.Spec.Types[0]).To(Equal(apiv3.PolicyTypeIngress))
Expect(gnp.Spec.Types[1]).To(Equal(apiv3.PolicyTypeEgress))
})
})
Loading

0 comments on commit 43d804b

Please sign in to comment.