Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AdminNetworkPolicy #9206

Merged
merged 21 commits into from
Sep 17, 2024
Merged

Conversation

mazdakn
Copy link
Member

@mazdakn mazdakn commented Sep 3, 2024

Description

Add support for the new k8s AdminNetworkPolicy API. This PR only adds the core functionalities.

Related issues/PRs

Tier support: #9085
Default action in tiers: #9232
Operator: tigera/operator#3501
AdminNetworkPolicy egress networks: #9276
AdminNetworkPolicy named port: #9254

Todos

  • Tests
  • Documentation
  • Release note

Release Note

Add support for the core functionalities of the new k8s AdminNetworkPolicy API.

Reminder for the reviewer

Make sure that this PR has the correct labels and milestone set.

Every PR needs one docs-* label.

  • docs-pr-required: This change requires a change to the documentation that has not been completed yet.
  • docs-completed: This change has all necessary documentation completed.
  • docs-not-required: This change has no user-facing impact and requires no docs.

Every PR needs one release-note-* label.

  • release-note-required: This PR has user-facing changes. Most PRs should have this label.
  • release-note-not-required: This PR has no user-facing changes.

Other optional labels:

  • cherry-pick-candidate: This PR should be cherry-picked to an earlier release. For bug fixes only.
  • needs-operator-pr: This PR is related to install and requires a corresponding change to the operator.

@mazdakn mazdakn requested a review from a team as a code owner September 3, 2024 16:44
@marvin-tigera marvin-tigera added this to the Calico v3.29.0 milestone Sep 3, 2024
@marvin-tigera marvin-tigera added release-note-required Change has user-facing impact (no matter how small) docs-pr-required Change is not yet documented labels Sep 3, 2024
Copy link
Member

@fasaxc fasaxc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a first pass. Mostly looks good but I think there are a few details of the spec for ANP that differ from the other policy that we support, mainly to allow for future enhancements to ANP. We should try to follow those behaviours, even if they're no-ops right now.

I think we should include support for CIDR matches and named ports in the first release. They should both be trivial to do and, to be correct according to the spec, I think if you don't support them, the behaviour needs to change (you should drop allow rules/convert deny rules to deny all).

api/pkg/apis/projectcalico/v3/policy_common.go Outdated Show resolved Hide resolved
libcalico-go/Makefile Outdated Show resolved Hide resolved
for _, r := range rule.To {
// We need to add a copy of the peer so all the rules don't
// point to the same location.
peer := &adminpolicy.AdminNetworkPolicyEgressPeer{Namespaces: r.Namespaces}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Egress peers also have Networks (list of CIDRs).

Do we need the copy step in recent golang? I think loop variables are now unique per loop so you may not need to copy anything.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also "Nodes". I suppose we could translate that to something that would match the right auto-HEPs (but if we're not going to support it, should we validate against it?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note https://github.com/kubernetes-sigs/network-policy-api/blob/v0.1.5/apis/v1alpha1/shared_types.go#L148C1-L150C46 for forwards compatibility, we should check that something is set in the rule and fail closed if we see nothing.

// Exactly one of the selector pointers must be set for a given peer. If a
// consumer observes none of its fields are set, they must assume an unknown
// option has been specified and fail closed.

@@ -1567,6 +1567,18 @@ func validateTier(structLevel validator.StructLevel) {
}
}

if tier.Name == names.AdminNetworkPolicyTierName {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to validate this on read? If Felix reads a bad value it'll drop the resource and that'll break policy. I feel like we only want to check this on write so that, if bad data gets into the datastore, we still do something sensible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't validate this on read. In the Tier implementation of Clientv3, we only call validator on create and update.

func (r tiers) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.Tier, error) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Felix/Typha both validate in their calc graphs, I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. It seems in Typha we also validate in reads:

if err := validatorFunc(elem.Interface()); err != nil {

Also in Felix:
if err := validatorFunc(elem.Interface()); err != nil {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally the check was like this: https://github.com/tigera/calico-private/blame/d7f58624426ef41c64b6981b6017cf2956b50a25/libcalico-go/lib/clientv3/tier.go#L51

However, we changed it to v3 validator since the return error code, Operation not supported, is not technically correct, as the create/update operations are supported. It just feels the right place for these type of checks is in validator.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be an issue if create and update does not allow the incorrect value for AdminNeworkPolicy tier in first place?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, we create adminneworkpolicy tier ourselves at the beginning of the day here:

func (c client) ensureAdminNetworkPolicyTierExists(ctx context.Context) error {

for _, r := range anp.Spec.Ingress {
rules, err := c.k8sANPIngressRuleToCalico(r)
if err != nil {
log.WithError(err).Warn("dropping k8s rule that couldn't be converted.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the intent in the NPEP is to "fail closed" when we don't understand a rule in order to deal with forwards compatibility more cleanly. I take that to mean:

  • If we can't understand an Allow rule, we should log a warning and drop it.
  • If we can't understand a Deny rule, we should log a warning and convert that to a "Deny all" rule.

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense for a fail closed system. For allow & pass action it's clear that we should drop the rule.
For deny action, I think we should only add the Deny all for the direction of failed rule, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only add the Deny all for the direction of failed rule, right?

Yes, exactly, just that one rule gets converted to deny all (or at least, that's my interpretation).

libcalico-go/lib/names/policy.go Outdated Show resolved Hide resolved
libcalico-go/lib/names/policy.go Outdated Show resolved Hide resolved
protocol = c.k8sProtocolToCalico(&port.PortRange.Protocol)
return
}
return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NamedPort is "Extended" but we support named ports in Felix so I think that's best to do now.

libcalico-go/lib/backend/k8s/conversion/conversion.go Outdated Show resolved Hide resolved
}
}

// If there no peers, or no ports, represent that as nil.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the spec requires there to be at least one peer (although that means it's hard to do basic things like allow all/deny all!). I filed an issue upstream for that: kubernetes-sigs/network-policy-api#248

felix/rules/endpoints.go Outdated Show resolved Hide resolved
@@ -0,0 +1,72 @@
// Copyright (c) 2024 Tigera, Inc. All rights reserved.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this file from here: https://github.com/kubernetes-sigs/network-policy-api/blob/main/conformance/conformance_test.go
I believe I should use their copy right clause, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, always keep external copyright notices intact. We can also add ours as and when we make changes (but best to make changes in a second file where possible to make it easier to unpick what's ours and what's theirs).

@mazdakn mazdakn requested a review from fasaxc September 16, 2024 21:42
libcalico-go/lib/backend/k8s/conversion/conversion.go Outdated Show resolved Hide resolved
libcalico-go/lib/backend/k8s/conversion/constants.go Outdated Show resolved Hide resolved
libcalico-go/lib/backend/k8s/conversion/conversion.go Outdated Show resolved Hide resolved
libcalico-go/lib/names/policy.go Outdated Show resolved Hide resolved
Copy link
Member

@fasaxc fasaxc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved as an increment but, as discussed, you're planning to:

  • Solve the end of tier ACTION PROPERLY.
  • Add tiers to Dikastes.

@caseydavenport caseydavenport merged commit 800b96f into projectcalico:master Sep 17, 2024
2 of 3 checks passed
@mazdakn mazdakn deleted the adminnetworkpolicy branch September 17, 2024 21:02
@coutinhop coutinhop added docs-completed Docs PR has been merged for this change and removed docs-pr-required Change is not yet documented labels Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs-completed Docs PR has been merged for this change release-note-required Change has user-facing impact (no matter how small)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants