diff --git a/Makefile b/Makefile index 866068f2cec..7d7175de3d2 100644 --- a/Makefile +++ b/Makefile @@ -95,10 +95,12 @@ image: # using a local kind cluster. ############################################################################### E2E_FOCUS ?= "sig-network.*Conformance" +ADMINPOLICY_UNSUPPORTED_FEATURES ?= "BaselineAdminNetworkPolicy" e2e-test: $(MAKE) -C e2e build $(MAKE) -C node kind-k8st-setup - KUBECONFIG=$(KIND_KUBECONFIG) ./e2e/bin/e2e.test -ginkgo.focus=$(E2E_FOCUS) + KUBECONFIG=$(KIND_KUBECONFIG) ./e2e/bin/k8s/e2e.test -ginkgo.focus=$(E2E_FOCUS) + KUBECONFIG=$(KIND_KUBECONFIG) ./e2e/bin/adminpolicy/e2e.test -exempt-features=$(ADMINPOLICY_UNSUPPORTED_FEATURES) ############################################################################### # Release logic below diff --git a/api/pkg/apis/projectcalico/v3/tier.go b/api/pkg/apis/projectcalico/v3/tier.go index 34672a997c8..77c6d6cf6ea 100644 --- a/api/pkg/apis/projectcalico/v3/tier.go +++ b/api/pkg/apis/projectcalico/v3/tier.go @@ -37,7 +37,8 @@ type Tier struct { } const ( - DefaultTierOrder = float64(1_000_000) // 1 Million + DefaultTierOrder = float64(1_000_000) // 1Million + AdminNetworkPolicyTierOrder = float64(1_000) // 1K ) // TierSpec contains the specification for a security policy tier resource. diff --git a/apiserver/pkg/storage/calico/policy_storage.go b/apiserver/pkg/storage/calico/policy_storage.go index b68e17565b7..2ec69705282 100644 --- a/apiserver/pkg/storage/calico/policy_storage.go +++ b/apiserver/pkg/storage/calico/policy_storage.go @@ -14,9 +14,9 @@ import ( v3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" - "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" "github.com/projectcalico/calico/libcalico-go/lib/clientv3" cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" "github.com/projectcalico/calico/libcalico-go/lib/watch" ) @@ -27,7 +27,7 @@ func NewNetworkPolicyStorage(opts Options) (registry.DryRunnableStorage, factory createFn := func(ctx context.Context, c clientv3.Interface, obj resourceObject, opts clientOpts) (resourceObject, error) { oso := opts.(options.SetOptions) res := obj.(*v3.NetworkPolicy) - if strings.HasPrefix(res.Name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(res.Name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "create or apply", Identifier: obj, @@ -39,7 +39,7 @@ func NewNetworkPolicyStorage(opts Options) (registry.DryRunnableStorage, factory updateFn := func(ctx context.Context, c clientv3.Interface, obj resourceObject, opts clientOpts) (resourceObject, error) { oso := opts.(options.SetOptions) res := obj.(*v3.NetworkPolicy) - if strings.HasPrefix(res.Name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(res.Name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "update or apply", Identifier: obj, @@ -54,7 +54,7 @@ func NewNetworkPolicyStorage(opts Options) (registry.DryRunnableStorage, factory } deleteFn := func(ctx context.Context, c clientv3.Interface, ns string, name string, opts clientOpts) (resourceObject, error) { odo := opts.(options.DeleteOptions) - if strings.HasPrefix(name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "delete", Identifier: name, diff --git a/apiserver/pkg/storage/calico/tier_storage_test.go b/apiserver/pkg/storage/calico/tier_storage_test.go index 8544191a384..5e9a0af83f8 100644 --- a/apiserver/pkg/storage/calico/tier_storage_test.go +++ b/apiserver/pkg/storage/calico/tier_storage_test.go @@ -29,6 +29,7 @@ import ( "github.com/projectcalico/calico/libcalico-go/lib/apiconfig" "github.com/projectcalico/calico/libcalico-go/lib/clientv3" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" v3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" @@ -522,13 +523,19 @@ func TestTierList(t *testing.T) { } } - defaultTier := makeTier("", "", v3.DefaultTierOrder) opts := storage.GetOptions{IgnoreNotFound: false} + defaultTier := makeTier(names.DefaultTierName, "", v3.DefaultTierOrder) err := store.Get(ctx, "projectcalico.org/tiers/default", opts, defaultTier) if err != nil { t.Fatalf("Get failed: %v", err) } + anpTier := makeTier(names.AdminNetworkPolicyTierName, "", v3.AdminNetworkPolicyTierOrder) + err = store.Get(ctx, "projectcalico.org/tiers/adminnetworkpolicy", opts, anpTier) + if err != nil { + t.Fatalf("Get failed: %v", err) + } + tests := []struct { prefix string pred storage.SelectionPredicate @@ -547,7 +554,7 @@ func TestTierList(t *testing.T) { return nil, fields.Set{"metadata.name": tier.Name}, nil }, }, - expectedOut: []*v3.Tier{preset[1].storedObj, defaultTier}, + expectedOut: []*v3.Tier{anpTier, preset[1].storedObj, defaultTier}, }} for i, tt := range tests { diff --git a/calicoctl/calicoctl/commands/convert.go b/calicoctl/calicoctl/commands/convert.go index db8c513b125..e03c08444ce 100644 --- a/calicoctl/calicoctl/commands/convert.go +++ b/calicoctl/calicoctl/commands/convert.go @@ -32,6 +32,7 @@ import ( "github.com/projectcalico/calico/calicoctl/calicoctl/commands/resourceloader" "github.com/projectcalico/calico/calicoctl/calicoctl/util" "github.com/projectcalico/calico/libcalico-go/lib/apis/v1/unversioned" + "github.com/projectcalico/calico/libcalico-go/lib/names" cconversion "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" "github.com/projectcalico/calico/libcalico-go/lib/upgrade/converters" @@ -217,10 +218,8 @@ func convertK8sResource(convResource unversioned.Resource) (converters.Resource, // Trim K8sNetworkPolicyNamePrefix from the policy name (the K8sNetworkPolicyToCalico // function adds it for when it is used for coexisting calico/k8s policies). - k8snp.Name = strings.TrimPrefix(k8snp.Name, cconversion.K8sNetworkPolicyNamePrefix) - + k8snp.Name = strings.TrimPrefix(k8snp.Name, names.K8sNetworkPolicyNamePrefix) res = k8snp - default: return nil, fmt.Errorf("conversion for the k8s resource type '%s' is not supported", k8sResKind) } diff --git a/calicoctl/calicoctl/commands/datastore/migrate/export.go b/calicoctl/calicoctl/commands/datastore/migrate/export.go index 52ac8f612ab..ed0b9f097fd 100644 --- a/calicoctl/calicoctl/commands/datastore/migrate/export.go +++ b/calicoctl/calicoctl/commands/datastore/migrate/export.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2020-2024 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ import ( "github.com/projectcalico/calico/calicoctl/calicoctl/util" "github.com/projectcalico/calico/libcalico-go/lib/apiconfig" libapiv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" - "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" + "github.com/projectcalico/calico/libcalico-go/lib/names" ) var title = cases.Title(language.English) @@ -221,7 +221,7 @@ Description: if !ok { return fmt.Errorf("Unable to convert Calico network policy for inspection") } - if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), conversion.K8sNetworkPolicyNamePrefix) { + if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), names.K8sNetworkPolicyNamePrefix) { filtered = append(filtered, obj) } } @@ -233,6 +233,31 @@ Description: results.Resources[i] = resource } + // Skip exporting Kubernetes admin network policies. + if r == "globalnetworkpolicies" { + objs, err := meta.ExtractList(resource) + if err != nil { + return fmt.Errorf("Error extracting global network policies for inspection before exporting: %s", err) + } + + filtered := []runtime.Object{} + for _, obj := range objs { + metaObj, ok := obj.(v1.ObjectMetaAccessor) + if !ok { + return fmt.Errorf("Unable to convert Calico gloabal network policy for inspection") + } + if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), names.K8sAdminNetworkPolicyNamePrefix) { + filtered = append(filtered, obj) + } + } + + err = meta.SetList(resource, filtered) + if err != nil { + return fmt.Errorf("Unable to remove Kubernetes admin network policies for export: %s", err) + } + results.Resources[i] = resource + } + // Nodes need to also be modified to move the Orchestrator reference to the name field. if r == "nodes" { err := meta.EachListItem(resource, func(obj runtime.Object) error { diff --git a/calicoctl/calicoctl/commands/datastore/migrate/import.go b/calicoctl/calicoctl/commands/datastore/migrate/import.go index a26a8de32a9..976a078fc32 100644 --- a/calicoctl/calicoctl/commands/datastore/migrate/import.go +++ b/calicoctl/calicoctl/commands/datastore/migrate/import.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2020-2024 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -40,10 +40,10 @@ import ( "github.com/projectcalico/calico/libcalico-go/lib/apiconfig" libapiv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s" - "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" "github.com/projectcalico/calico/libcalico-go/lib/backend/model" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" calicoErrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" ) @@ -246,7 +246,25 @@ func checkCalicoResourcesNotExist(args map[string]interface{}, c client.Interfac } // Make sure that the network policy is a K8s network policy - if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), conversion.K8sNetworkPolicyNamePrefix) { + if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), names.K8sNetworkPolicyNamePrefix) { + return fmt.Errorf("Found existing Calico %s resource", results.SingleKind) + } + } + } else if r == "globalnetworkpolicies" { + // For globalnetworkpolicies, having K8s admin network policies should not throw an error + objs, err := meta.ExtractList(resource) + if err != nil { + return fmt.Errorf("Error extracting global network policies for inspection: %s", err) + } + + for _, obj := range objs { + metaObj, ok := obj.(v1.ObjectMetaAccessor) + if !ok { + return fmt.Errorf("Unable to convert Calico global network policy for inspection") + } + + // Make sure that the global network policy is a K8s admin network policy + if !strings.HasPrefix(metaObj.GetObjectMeta().GetName(), names.K8sAdminNetworkPolicyNamePrefix) { return fmt.Errorf("Found existing Calico %s resource", results.SingleKind) } } diff --git a/calicoctl/calicoctl/resourcemgr/globalnetworkpolicy.go b/calicoctl/calicoctl/resourcemgr/globalnetworkpolicy.go index 07bc93f005e..72b47d0eb7f 100644 --- a/calicoctl/calicoctl/resourcemgr/globalnetworkpolicy.go +++ b/calicoctl/calicoctl/resourcemgr/globalnetworkpolicy.go @@ -16,12 +16,15 @@ package resourcemgr import ( "context" + "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" api "github.com/projectcalico/api/pkg/apis/projectcalico/v3" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" + cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" ) @@ -41,14 +44,35 @@ func init() { }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.GlobalNetworkPolicy) + if strings.HasPrefix(r.Name, names.K8sAdminNetworkPolicyNamePrefix) { + return nil, cerrors.ErrorOperationNotSupported{ + Operation: "create or apply", + Identifier: resource, + Reason: "kubernetes admin network policies must be managed through the kubernetes API", + } + } return client.GlobalNetworkPolicies().Create(ctx, r, options.SetOptions{}) }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.GlobalNetworkPolicy) + if strings.HasPrefix(r.Name, names.K8sAdminNetworkPolicyNamePrefix) { + return nil, cerrors.ErrorOperationNotSupported{ + Operation: "create or apply", + Identifier: resource, + Reason: "kubernetes admin network policies must be managed through the kubernetes API", + } + } return client.GlobalNetworkPolicies().Update(ctx, r, options.SetOptions{}) }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.GlobalNetworkPolicy) + if strings.HasPrefix(r.Name, names.K8sAdminNetworkPolicyNamePrefix) { + return nil, cerrors.ErrorOperationNotSupported{ + Operation: "create or apply", + Identifier: resource, + Reason: "kubernetes admin network policies must be managed through the kubernetes API", + } + } return client.GlobalNetworkPolicies().Delete(ctx, r.Name, options.DeleteOptions{ResourceVersion: r.ResourceVersion}) }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { diff --git a/calicoctl/calicoctl/resourcemgr/networkpolicy.go b/calicoctl/calicoctl/resourcemgr/networkpolicy.go index d374960990a..e23277cd4ea 100644 --- a/calicoctl/calicoctl/resourcemgr/networkpolicy.go +++ b/calicoctl/calicoctl/resourcemgr/networkpolicy.go @@ -21,9 +21,9 @@ import ( api "github.com/projectcalico/api/pkg/apis/projectcalico/v3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" ) @@ -45,7 +45,7 @@ func init() { }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.NetworkPolicy) - if strings.HasPrefix(r.Name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(r.Name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "create or apply", Identifier: resource, @@ -56,7 +56,7 @@ func init() { }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.NetworkPolicy) - if strings.HasPrefix(r.Name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(r.Name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "apply or replace", Identifier: resource, @@ -67,7 +67,7 @@ func init() { }, func(ctx context.Context, client client.Interface, resource ResourceObject) (ResourceObject, error) { r := resource.(*api.NetworkPolicy) - if strings.HasPrefix(r.Name, conversion.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(r.Name, names.K8sNetworkPolicyNamePrefix) { return nil, cerrors.ErrorOperationNotSupported{ Operation: "delete", Identifier: resource, diff --git a/calicoctl/tests/st/calicoctl/test_crud.py b/calicoctl/tests/st/calicoctl/test_crud.py index 6205942f96b..d8bcf039a87 100644 --- a/calicoctl/tests/st/calicoctl/test_crud.py +++ b/calicoctl/tests/st/calicoctl/test_crud.py @@ -1127,10 +1127,12 @@ def test_tier_list_order(self): rc.assert_no_error() tierList = rc.decoded - # Validate the tiers are ordered correctly. Default should have a value of nil and should be placed last. + # Validate the tiers are ordered correctly. Default should have a value of 1M and should be placed last. + # adminnetworkpolicy has a value of 1K, and should be second one. self.assertEqual(tierList['items'][0]['metadata']['name'], name(tier_name2_rev1)) - self.assertEqual(tierList['items'][1]['metadata']['name'], name(tier_name1_rev1)) - self.assertEqual(tierList['items'][2]['metadata']['name'], 'default') + self.assertEqual(tierList['items'][1]['metadata']['name'], 'adminnetworkpolicy') + self.assertEqual(tierList['items'][2]['metadata']['name'], name(tier_name1_rev1)) + self.assertEqual(tierList['items'][3]['metadata']['name'], 'default') # Delete the resources rc = calicoctl("delete", data=resources) diff --git a/calicoctl/tests/st/utils/data.py b/calicoctl/tests/st/utils/data.py index ca389afcd41..1484a92b716 100644 --- a/calicoctl/tests/st/utils/data.py +++ b/calicoctl/tests/st/utils/data.py @@ -336,7 +336,7 @@ 'name': 'admin', }, 'spec': { - 'Order': 1000, + 'Order': 10000, }, } diff --git a/charts/calico/templates/calico-node-rbac.yaml b/charts/calico/templates/calico-node-rbac.yaml index 616c3e08c54..d2c139a61ca 100644 --- a/charts/calico/templates/calico-node-rbac.yaml +++ b/charts/calico/templates/calico-node-rbac.yaml @@ -68,6 +68,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/e2e/Makefile b/e2e/Makefile index 74194f19331..d34b9b1174e 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -3,10 +3,14 @@ include ../metadata.mk PACKAGE_NAME=github.com/projectcalico/calico/e2e include ../lib.Makefile -build: bin/e2e.test -bin/e2e.test: $(SRC_FILES) +build: bin/k8s/e2e.test bin/adminpolicy/e2e.test +bin/k8s/e2e.test: $(SRC_FILES) mkdir -p bin - $(DOCKER_RUN) $(CALICO_BUILD) go test ./cmd -c -o $@ + $(DOCKER_RUN) $(CALICO_BUILD) go test ./cmd/k8s -c -o $@ + +bin/adminpolicy/e2e.test: $(SRC_FILES) + mkdir -p bin + $(DOCKER_RUN) $(CALICO_BUILD) go test ./cmd/adminpolicy -c -o $@ clean: rm -rf bin/ diff --git a/e2e/cmd/adminpolicy/e2e_test.go b/e2e/cmd/adminpolicy/e2e_test.go new file mode 100644 index 00000000000..d5c67dbe709 --- /dev/null +++ b/e2e/cmd/adminpolicy/e2e_test.go @@ -0,0 +1,74 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "testing" + + "k8s.io/client-go/kubernetes" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + + "sigs.k8s.io/network-policy-api/apis/v1alpha1" + "sigs.k8s.io/network-policy-api/conformance/tests" + "sigs.k8s.io/network-policy-api/conformance/utils/flags" + "sigs.k8s.io/network-policy-api/conformance/utils/suite" +) + +func TestConformance(t *testing.T) { + cfg, err := config.GetConfig() + if err != nil { + t.Fatalf("Error loading Kubernetes config: %v", err) + } + c, err := client.New(cfg, client.Options{}) + if err != nil { + t.Fatalf("Error initializing Kubernetes client: %v", err) + } + + kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + t.Fatalf("error building Kube config for client-go: %v", err) + } + clientset, err := kubernetes.NewForConfig(kubeConfig) + if err != nil { + t.Fatalf("error when creating Kubernetes ClientSet: %v", err) + } + + v1alpha1.Install(c.Scheme()) + + supportedFeatures := suite.ParseSupportedFeatures(*flags.SupportedFeatures) + exemptFeatures := suite.ParseSupportedFeatures(*flags.ExemptFeatures) + + t.Logf("Running conformance tests with cleanup: %t\n debug: %t\n enable all features: %t \n supported features: [%v]\n exempt features: [%v]", + *flags.CleanupBaseResources, *flags.ShowDebug, *flags.EnableAllSupportedFeatures, *flags.SupportedFeatures, *flags.ExemptFeatures) + + cSuite := suite.New(suite.Options{ + Client: c, + ClientSet: clientset, + KubeConfig: *cfg, + Debug: *flags.ShowDebug, + CleanupBaseResources: *flags.CleanupBaseResources, + SupportedFeatures: supportedFeatures, + ExemptFeatures: exemptFeatures, + EnableAllSupportedFeatures: *flags.EnableAllSupportedFeatures, + }) + cSuite.Setup(t) + + cSuite.Run(t, tests.ConformanceTests) +} diff --git a/e2e/cmd/e2e_test.go b/e2e/cmd/k8s/e2e_test.go similarity index 100% rename from e2e/cmd/e2e_test.go rename to e2e/cmd/k8s/e2e_test.go diff --git a/felix/dataplane/linux/bpf_ep_mgr.go b/felix/dataplane/linux/bpf_ep_mgr.go index 10fb1ece2d8..9058632d5d5 100644 --- a/felix/dataplane/linux/bpf_ep_mgr.go +++ b/felix/dataplane/linux/bpf_ep_mgr.go @@ -42,6 +42,7 @@ import ( "github.com/projectcalico/calico/felix/ethtool" "github.com/projectcalico/calico/felix/generictables" "github.com/projectcalico/calico/libcalico-go/lib/health" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" @@ -2978,6 +2979,11 @@ func (m *bpfEndpointManager) extractTiers(tiers []*proto.TierInfo, direction Pol polTier.Policies[i] = policy } + // This changes will be replaces by changes in https://github.com/projectcalico/calico/pull/9232 + if tier.Name == names.AdminNetworkPolicyTierName { + endTierDrop = false + } + if endTierDrop { polTier.EndAction = polprog.TierEndDeny } else { diff --git a/felix/fv/infrastructure/infra_k8s.go b/felix/fv/infrastructure/infra_k8s.go index 66771a7606e..50108ec3cce 100644 --- a/felix/fv/infrastructure/infra_k8s.go +++ b/felix/fv/infrastructure/infra_k8s.go @@ -1089,7 +1089,7 @@ func cleanupAllTiers(clientset *kubernetes.Clientset, client client.Interface) { } log.WithField("count", len(tiers.Items)).Info("Tiers present") for _, tier := range tiers.Items { - if tier.Name == "default" { + if tier.Name == names.DefaultTierName || tier.Name == names.AdminNetworkPolicyTierName { continue } diff --git a/felix/rules/endpoints.go b/felix/rules/endpoints.go index 68963b72de6..384d6dd1649 100644 --- a/felix/rules/endpoints.go +++ b/felix/rules/endpoints.go @@ -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 ( @@ -463,6 +464,13 @@ func (r *DefaultRuleRenderer) endpointIptablesChain( Comment: []string{"Start of tier " + tier.Name}, }) + // This changes will be replaces by changes in https://github.com/projectcalico/calico/pull/9232 + endOfTierDrop := true + // For AdminNetworkPolicy Tier the endOfTier action is pass. + if tier.Name == names.AdminNetworkPolicyTierName { + endOfTierDrop = false + } + for _, polGroup := range policyGroups { var chainsToJumpTo []string if polGroup.ShouldBeInlined() { @@ -505,16 +513,18 @@ func (r *DefaultRuleRenderer) endpointIptablesChain( } if chainType == chainTypeNormal || chainType == chainTypeForward { - // When rendering normal and forward rules, if no policy marked the packet as "pass", drop the - // packet. - // - // For untracked and pre-DNAT rules, we don't do that because there may be - // normal rules still to be applied to the packet in the filter table. - rules = append(rules, generictables.Rule{ - Match: r.NewMatch().MarkClear(r.MarkPass), - Action: r.IptablesFilterDenyAction(), - Comment: []string{fmt.Sprintf("%s if no policies passed packet", r.IptablesFilterDenyAction())}, - }) + if endOfTierDrop { + // When rendering normal and forward rules, if no policy marked the packet as "pass", drop the + // packet. + // + // For untracked and pre-DNAT rules, we don't do that because there may be + // normal rules still to be applied to the packet in the filter table. + rules = append(rules, generictables.Rule{ + Match: r.NewMatch().MarkClear(r.MarkPass), + Action: r.IptablesFilterDenyAction(), + Comment: []string{fmt.Sprintf("%s if no policies passed packet", r.IptablesFilterDenyAction())}, + }) + } } } } diff --git a/go.mod b/go.mod index 437c546dc63..90a957c10f7 100644 --- a/go.mod +++ b/go.mod @@ -106,9 +106,10 @@ require ( k8s.io/kubernetes v1.29.7 k8s.io/utils v0.0.0-20240310230437-4693a0247e57 modernc.org/memory v1.7.2 - sigs.k8s.io/controller-runtime v0.15.3 + sigs.k8s.io/controller-runtime v0.17.0 sigs.k8s.io/kind v0.22.0 sigs.k8s.io/knftables v0.0.15 + sigs.k8s.io/network-policy-api v0.1.5 sigs.k8s.io/yaml v1.4.0 ) @@ -168,8 +169,8 @@ require ( github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.8.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect @@ -270,9 +271,8 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.24.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect @@ -300,11 +300,11 @@ require ( k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect k8s.io/kms v0.29.7 // indirect k8s.io/kube-scheduler v0.0.0 // indirect - k8s.io/kubectl v0.0.0 // indirect + k8s.io/kubectl v0.26.0 // indirect k8s.io/kubelet v0.28.9 // indirect k8s.io/legacy-cloud-providers v0.0.0 // indirect k8s.io/mount-utils v0.28.9 // indirect - k8s.io/pod-security-admission v0.0.0 // indirect + k8s.io/pod-security-admission v0.26.0 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index ff1e6c62075..26e74a5bc57 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 h1:cjTRjh700H36MQ8M0LnDn33W3Jmw github.com/aws/aws-sdk-go-v2/service/sts v1.27.0/go.mod h1:nXfOBMWPokIbOY+Gi7a1psWMSvskUCemZzI+SMB7Akc= github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -247,10 +245,11 @@ github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= +github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= @@ -281,8 +280,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -811,14 +810,12 @@ go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeX go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1110,8 +1107,6 @@ golang.zx2c4.com/wireguard v0.0.20200121 h1:vcswa5Q6f+sylDfjqyrVNNrjsFUUbPsgAQTB golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200324154536-ceff61240acf h1:rWUZHukj3poXegPQMZOXgxjTGIBe3mLNHNVvL5DsHus= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200324154536-ceff61240acf/go.mod h1:UdS9frhv65KTfwxME1xE8+rHYoFpbm36gOud1GhBe9c= -gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= -gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1375,8 +1370,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y= -sigs.k8s.io/controller-runtime v0.15.3 h1:L+t5heIaI3zeejoIyyvLQs5vTVu/67IU2FfisVzFlBc= -sigs.k8s.io/controller-runtime v0.15.3/go.mod h1:kp4jckA4vTx281S/0Yk2LFEEQe67mjg+ev/yknv47Ds= +sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s= +sigs.k8s.io/controller-runtime v0.17.0/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.22.0 h1:z/+yr/azoOfzsfooqRsPw1wjJlqT/ukXP0ShkHwNlsI= @@ -1387,6 +1382,8 @@ sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKU sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/network-policy-api v0.1.5 h1:xyS7VAaM9EfyB428oFk7WjWaCK6B129i+ILUF4C8l6E= +sigs.k8s.io/network-policy-api v0.1.5/go.mod h1:D7Nkr43VLNd7iYryemnj8qf0N/WjBzTZDxYA+g4u1/Y= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/kube-controllers/pkg/controllers/networkpolicy/policy_controller.go b/kube-controllers/pkg/controllers/networkpolicy/policy_controller.go index 940c221dfa8..d92ad1ce91a 100644 --- a/kube-controllers/pkg/controllers/networkpolicy/policy_controller.go +++ b/kube-controllers/pkg/controllers/networkpolicy/policy_controller.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2020 Tigera, Inc. All rights reserved. +// Copyright (c) 2017-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,9 +29,9 @@ import ( api "github.com/projectcalico/api/pkg/apis/projectcalico/v3" "github.com/projectcalico/calico/kube-controllers/pkg/converter" - kdd "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" networkingv1 "k8s.io/api/networking/v1" @@ -72,7 +72,7 @@ func NewPolicyController(ctx context.Context, clientset *kubernetes.Clientset, c // Filter in only objects that are written by policy controller. m := make(map[string]interface{}) for _, policy := range calicoPolicies.Items { - if strings.HasPrefix(policy.Name, kdd.K8sNetworkPolicyNamePrefix) { + if strings.HasPrefix(policy.Name, names.K8sNetworkPolicyNamePrefix) { // Update the network policy's ObjectMeta so that it simply contains the name and namespace. // There is other metadata that we might receive (like resource version) that we don't want to // compare in the cache. diff --git a/libcalico-go/Makefile b/libcalico-go/Makefile index 92cd3ad5f6b..16b1510e668 100644 --- a/libcalico-go/Makefile +++ b/libcalico-go/Makefile @@ -6,6 +6,10 @@ LOCAL_CHECKS = goimports check-gen-files KIND_CONFIG = $(KIND_DIR)/kind-single.config +NETPOL_TAG = v0.1.5 +NETPOL_CRD_URL = https://raw.githubusercontent.com/kubernetes-sigs/network-policy-api/refs/tags/$(NETPOL_TAG)/config/crd/standard +NETPOL_ANP_CRD = policy.networking.k8s.io_adminnetworkpolicies.yaml + ############################################################################### # Download and include ../lib.Makefile # Additions to EXTRA_DOCKER_ARGS need to happen before the include since @@ -53,6 +57,8 @@ gen-crds: patch -s -p0 < ./config.patch # The first two lines are a newline and a yaml separator - remove them. $(DOCKER_GO_BUILD) sh -c 'find ./config/crd -name "*.yaml" | xargs sed -i -e 1,2d' + # Add K8S AdminNetworkPolicy CRD + curl $(NETPOL_CRD_URL)/$(NETPOL_ANP_CRD) -o ./config/crd/$(NETPOL_ANP_CRD) ./lib/upgrade/migrator/clients/v1/k8s/custom/zz_generated.deepcopy.go: $(UPGRADE_SRCS) $(DOCKER_GO_BUILD) sh -c 'deepcopy-gen \ diff --git a/libcalico-go/config/crd/policy.networking.k8s.io_adminnetworkpolicies.yaml b/libcalico-go/config/crd/policy.networking.k8s.io_adminnetworkpolicies.yaml new file mode 100644 index 00000000000..9494e478e5f --- /dev/null +++ b/libcalico-go/config/crd/policy.networking.k8s.io_adminnetworkpolicies.yaml @@ -0,0 +1,966 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/libcalico-go/lib/backend/k8s/conversion/adminnetworkpolicy_test.go b/libcalico-go/lib/backend/k8s/conversion/adminnetworkpolicy_test.go new file mode 100644 index 00000000000..f820b81516b --- /dev/null +++ b/libcalico-go/lib/backend/k8s/conversion/adminnetworkpolicy_test.go @@ -0,0 +1,1558 @@ +// Copyright (c) 2024 Tigera, Inc. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package conversion + +import ( + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" + "github.com/projectcalico/api/pkg/lib/numorstring" + kapiv1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" + + "github.com/projectcalico/calico/libcalico-go/lib/backend/model" + cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/names" +) + +var _ = Describe("Test AdminNetworkPolicy conversion", func() { + // Use a single instance of the Converter for these tests. + c := NewConverter() + + convertToGNP := func( + anp *adminpolicy.AdminNetworkPolicy, + order float64, + expectedErr *cerrors.ErrorAdminPolicyConversion, + ) *apiv3.GlobalNetworkPolicy { + // Parse the policy. + pol, err := c.K8sAdminNetworkPolicyToCalico(anp) + + if expectedErr == nil { + Expect(err).To(BeNil()) + } else { + Expect(err).To(Equal(*expectedErr)) + } + + // Assert key fields are correct. + policyName := fmt.Sprintf("%v%v", names.K8sAdminNetworkPolicyNamePrefix, anp.Name) + Expect(pol.Key.(model.ResourceKey).Name).To(Equal(policyName)) + + gnp, ok := pol.Value.(*apiv3.GlobalNetworkPolicy) + Expect(ok).To(BeTrue()) + + // Make sure the type information is correct. + Expect(gnp.Kind).To(Equal(apiv3.KindGlobalNetworkPolicy)) + Expect(gnp.APIVersion).To(Equal(apiv3.GroupVersionCurrent)) + + // Assert value fields are correct. + Expect(*gnp.Spec.Order).To(Equal(order)) + Expect(gnp.Spec.Tier).To(Equal(names.AdminNetworkPolicyTierName)) + + return gnp + } + + It("should parse a basic k8s AdminNetworkPolicy to a GlobalNetworkPolicy", func() { + ports := []adminpolicy.AdminNetworkPolicyPort{{ + PortNumber: &adminpolicy.Port{ + Port: 80, + }, + }} + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 100, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + "label2": "value2", + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "The first ingress rule", + Action: "Allow", + Ports: &ports, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + "k2": "v2", + }, + }, + }, + }, + }, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(100.0), nil) + + // Check the selector is correct, and that the matches are sorted. + Expect(gnp.Spec.NamespaceSelector).To(Equal("label == 'value' && label2 == 'value2'")) + protoTCP := numorstring.ProtocolFromString("TCP") + Expect(gnp.Spec.Ingress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("The first ingress rule"), + Action: "Allow", + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{ + NamespaceSelector: "k == 'v' && k2 == 'v2'", + }, + Destination: apiv3.EntityRule{ + Ports: []numorstring.Port{numorstring.SinglePort(80)}, + }, + }, + )) + + // There should be no Egress rules + Expect(gnp.Spec.Egress).To(HaveLen(0)) + }) + + It("should drop rules with invalid action in a k8s AdminNetworkPolicy", func() { + ports := []adminpolicy.AdminNetworkPolicyPort{ + { + PortNumber: &adminpolicy.Port{Port: 80}, + }, + { + PortRange: &adminpolicy.PortRange{Start: 2000, End: 3000}, + }, + } + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 300, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + "label2": "value2", + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Log", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + "k2": "v2", + }, + }, + }, + }, + }, + { + Name: "A random ingress rule 2", + Action: "Allow", + Ports: &ports, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k10": "v10", + "k20": "v20", + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + Ports: &ports, + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + "k4": "v4", + }, + }, + }, + }, + }, + { + Name: "A random egress rule 2", + Action: "Drop", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k30": "v30", + "k40": "v40", + }, + }, + }, + }, + }, + }, + }, + } + + expectedErr := cerrors.ErrorAdminPolicyConversion{ + PolicyName: "test.policy", + Rules: []cerrors.ErrorAdminPolicyConversionRule{ + { + EgressRule: nil, + IngressRule: &adminpolicy.AdminNetworkPolicyIngressRule{ + Name: "A random ingress rule", + Action: "Log", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{"k2": "v2", "k": "v"}, + MatchExpressions: nil, + }, + Pods: nil, + }, + }, + }, + Reason: "k8s rule couldn't be converted: unsupported admin network policy action Log", + }, + { + IngressRule: nil, + EgressRule: &adminpolicy.AdminNetworkPolicyEgressRule{ + Name: "A random egress rule 2", + Action: "Drop", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{"k30": "v30", "k40": "v40"}, + MatchExpressions: nil, + }, + Pods: nil, + }, + }, + }, + Reason: "k8s rule couldn't be converted: unsupported admin network policy action Drop", + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(300.0), &expectedErr) + + protoTCP := numorstring.ProtocolFromString("TCP") + + Expect(len(gnp.Spec.Ingress)).To(Equal(1)) + Expect(gnp.Spec.Ingress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random ingress rule 2"), + Action: "Allow", + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{ + NamespaceSelector: "k10 == 'v10' && k20 == 'v20'", + }, + Destination: apiv3.EntityRule{ + Ports: []numorstring.Port{numorstring.SinglePort(80), {MinPort: 2000, MaxPort: 3000}}, + }, + }, + )) + + Expect(len(gnp.Spec.Egress)).To(Equal(1)) + Expect(gnp.Spec.Egress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random egress rule"), + Action: "Deny", + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{}, + Destination: apiv3.EntityRule{ + NamespaceSelector: "k3 == 'v3' && k4 == 'v4'", + Ports: []numorstring.Port{numorstring.SinglePort(80), {MinPort: 2000, MaxPort: 3000}}, + }, + }, + )) + }) + + It("should parse a k8s AdminNetworkPolicy with no ports", func() { + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 200, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + "label2": "value2", + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Pass", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + "k2": "v2", + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + "k4": "v4", + }, + }, + }, + }, + }, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(200.0), nil) + + Expect(gnp.Spec.Ingress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random ingress rule"), + Action: "Pass", + Protocol: nil, // We only default to TCP when ports exist + Source: apiv3.EntityRule{NamespaceSelector: "k == 'v' && k2 == 'v2'"}, + Destination: apiv3.EntityRule{}, + }, + )) + Expect(gnp.Spec.Egress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random egress rule"), + Action: "Deny", + Protocol: nil, // We only default to TCP when ports exist + Source: apiv3.EntityRule{}, + Destination: apiv3.EntityRule{NamespaceSelector: "k3 == 'v3' && k4 == 'v4'"}, + }, + )) + }) + + It("should drop rules with invalid ports in a k8s AdminNetworkPolicy", func() { + goodPorts := []adminpolicy.AdminNetworkPolicyPort{ + { + PortNumber: &adminpolicy.Port{Port: 80}, + }, + { + PortRange: &adminpolicy.PortRange{Start: 2000, End: 3000}, + }, + } + badPorts := []adminpolicy.AdminNetworkPolicyPort{ + { + PortNumber: &adminpolicy.Port{Port: 80}, + }, + { + PortRange: &adminpolicy.PortRange{Start: 1000, End: 10}, + }, + } + + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 300, + 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: &badPorts, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + "k2": "v2", + }, + }, + }, + }, + }, + { + Name: "A random ingress rule 2", + Action: "Allow", + Ports: &goodPorts, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k10": "v10", + "k20": "v20", + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + Ports: &goodPorts, + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + "k4": "v4", + }, + }, + }, + }, + }, + { + Name: "A random egress rule 2", + Action: "Pass", + Ports: &badPorts, + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k30": "v30", + "k40": "v40", + }, + }, + }, + }, + }, + }, + }, + } + + expectedErr := cerrors.ErrorAdminPolicyConversion{ + PolicyName: "test.policy", + Rules: []cerrors.ErrorAdminPolicyConversionRule{ + { + EgressRule: nil, + IngressRule: &adminpolicy.AdminNetworkPolicyIngressRule{ + Name: "A random ingress rule", + Action: "Pass", + Ports: &badPorts, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{"k2": "v2", "k": "v"}, + MatchExpressions: nil, + }, + Pods: nil, + }, + }, + }, + Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (1000) is greater than maximum port number (10) in port range", + }, + { + IngressRule: nil, + EgressRule: &adminpolicy.AdminNetworkPolicyEgressRule{ + Name: "A random egress rule 2", + Action: "Pass", + Ports: &badPorts, + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{"k30": "v30", "k40": "v40"}, + MatchExpressions: nil, + }, + Pods: nil, + }, + }, + }, + Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (1000) is greater than maximum port number (10) in port range", + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(300.0), &expectedErr) + + protoTCP := numorstring.ProtocolFromString("TCP") + + Expect(len(gnp.Spec.Ingress)).To(Equal(1)) + Expect(gnp.Spec.Ingress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random ingress rule 2"), + Action: "Allow", + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{ + NamespaceSelector: "k10 == 'v10' && k20 == 'v20'", + }, + Destination: apiv3.EntityRule{ + Ports: []numorstring.Port{numorstring.SinglePort(80), {MinPort: 2000, MaxPort: 3000}}, + }, + }, + )) + + Expect(len(gnp.Spec.Egress)).To(Equal(1)) + Expect(gnp.Spec.Egress).To(ConsistOf( + apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random egress rule"), + Action: "Deny", + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{}, + Destination: apiv3.EntityRule{ + NamespaceSelector: "k3 == 'v3' && k4 == 'v4'", + Ports: []numorstring.Port{numorstring.SinglePort(80), {MinPort: 2000, MaxPort: 3000}}, + }, + }, + )) + }) + + It("should parse an AdminNetworkPolicy with no rules", func() { + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 500, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + "label2": "value2", + }, + }, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(500.0), nil) + + // Assert value fields are correct. + Expect(gnp.Spec.NamespaceSelector).To(Equal("label == 'value' && label2 == 'value2'")) + Expect(gnp.Spec.Ingress).To(HaveLen(0)) + + // There should be no Egress rules + Expect(gnp.Spec.Egress).To(HaveLen(0)) + }) + + It("should parse an AdminNetworkPolicy with Namespaces subject and multiple peers", 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{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + "label2": "value2", + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Pass", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k2": "v2", + }, + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + NamespaceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k4": "v4", + }, + }, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k5": "v5", + }, + }, + }, + }, + }, + }, + }, + }, + } + + gnp := convertToGNP(&anp, float64(600.0), nil) + + Expect(gnp.Spec.NamespaceSelector).To(Equal("label == 'value' && label2 == 'value2'")) + Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s'")) + + Expect(len(gnp.Spec.Ingress)).To(Equal(2)) + Expect(gnp.Spec.Ingress[0].Source.NamespaceSelector).To(Equal("k == 'v'")) + Expect(gnp.Spec.Ingress[1].Source.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress[1].Source.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k2 == 'v2'")) + + Expect(gnp.Spec.Egress).To(HaveLen(2)) + Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(Equal("k3 == 'v3'")) + Expect(gnp.Spec.Egress[1].Destination.NamespaceSelector).To(Equal("k4 == 'v4'")) + Expect(gnp.Spec.Egress[1].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k5 == 'v5'")) + + // 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)) + }) + + It("should parse an AdminNetworkPolicy with Pods subject and multiple peers", 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{ + "label2": "value2", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Pass", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k": "v", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k2": "v2", + }, + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + NamespaceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k4": "v4", + }, + }, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k5": "v5", + }, + }, + }, + }, + }, + }, + }, + }, + } + + gnp := convertToGNP(&anp, float64(600.0), nil) + + Expect(gnp.Spec.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && label2 == 'value2'")) + + Expect(len(gnp.Spec.Ingress)).To(Equal(2)) + Expect(gnp.Spec.Ingress[0].Source.NamespaceSelector).To(Equal("k == 'v'")) + Expect(gnp.Spec.Ingress[1].Source.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress[1].Source.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k2 == 'v2'")) + + Expect(gnp.Spec.Egress).To(HaveLen(2)) + Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(Equal("k3 == 'v3'")) + Expect(gnp.Spec.Egress[1].Destination.NamespaceSelector).To(Equal("k4 == 'v4'")) + Expect(gnp.Spec.Egress[1].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k5 == 'v5'")) + + // 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)) + }) + + It("should parse a k8s AdminNetworkPolicy with a DoesNotExist expression ", func() { + ports := []adminpolicy.AdminNetworkPolicyPort{ + { + PortNumber: &adminpolicy.Port{Port: 80}, + }, + } + 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", + "label2": "value2", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Allow", + Ports: &ports, + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + {Key: "toast", Operator: metav1.LabelSelectorOpDoesNotExist}, + }, + }, + }, + }, + }, + }, + }, + }, + } + + gnp := convertToGNP(&anp, float64(600.0), nil) + + // Check the selector is correct, and that the matches are sorted. + Expect(gnp.Spec.Selector).To(Equal( + "projectcalico.org/orchestrator == 'k8s' && label == 'value' && label2 == 'value2'")) + protoTCP := numorstring.ProtocolFromString("TCP") + Expect(gnp.Spec.Ingress).To(ConsistOf( + apiv3.Rule{ + Action: "Allow", + Metadata: k8sAdminNetworkPolicyToCalicoMetadata("A random ingress rule"), + Protocol: &protoTCP, // Defaulted to TCP. + Source: apiv3.EntityRule{ + NamespaceSelector: "all()", + Selector: "projectcalico.org/orchestrator == 'k8s' && ! has(toast)", + }, + Destination: apiv3.EntityRule{ + Ports: []numorstring.Port{numorstring.SinglePort(80)}, + }, + }, + )) + + // 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 multiple peers and ports", func() { + ports := []adminpolicy.AdminNetworkPolicyPort{ + { + PortNumber: &adminpolicy.Port{Port: 80}, + }, + { + PortRange: &adminpolicy.PortRange{Start: 20, End: 30, 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", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k2": "v2", + }, + }, + }, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Deny", + Ports: &ports, + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k3": "v3", + }, + }, + }, + { + Pods: &adminpolicy.NamespacedPod{ + NamespaceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k4": "v4", + }, + }, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "k5": "v5", + }, + }, + }, + }, + }, + }, + }, + }, + } + + gnp := convertToGNP(&anp, float64(600.0), nil) + + Expect(gnp.Spec.NamespaceSelector).To(Equal("label == 'value' && label2 == 'value2'")) + + Expect(len(gnp.Spec.Ingress)).To(Equal(4)) + 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.Ingress[1].Source.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress[1].Source.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k2 == 'v2'")) + Expect(gnp.Spec.Ingress[1].Destination.Ports).To(Equal([]numorstring.Port{numorstring.SinglePort(80)})) + + Expect(gnp.Spec.Ingress[2].Source.NamespaceSelector).To(Equal("k == 'v'")) + Expect(gnp.Spec.Ingress[2].Destination.Ports).To(Equal([]numorstring.Port{{MinPort: 20, MaxPort: 30}})) + + Expect(gnp.Spec.Ingress[3].Source.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress[3].Source.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k2 == 'v2'")) + Expect(gnp.Spec.Ingress[3].Destination.Ports).To(Equal([]numorstring.Port{{MinPort: 20, MaxPort: 30}})) + + Expect(gnp.Spec.Egress).To(HaveLen(4)) + Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(Equal("k3 == 'v3'")) + Expect(gnp.Spec.Egress[0].Destination.Ports).To(Equal([]numorstring.Port{numorstring.SinglePort(80)})) + + Expect(gnp.Spec.Egress[1].Destination.NamespaceSelector).To(Equal("k4 == 'v4'")) + Expect(gnp.Spec.Egress[1].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k5 == 'v5'")) + Expect(gnp.Spec.Egress[1].Destination.Ports).To(Equal([]numorstring.Port{numorstring.SinglePort(80)})) + + Expect(gnp.Spec.Egress[2].Destination.NamespaceSelector).To(Equal("k3 == 'v3'")) + Expect(gnp.Spec.Egress[2].Destination.Ports).To(Equal([]numorstring.Port{{MinPort: 20, MaxPort: 30}})) + + Expect(gnp.Spec.Egress[3].Destination.NamespaceSelector).To(Equal("k4 == 'v4'")) + Expect(gnp.Spec.Egress[3].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && k5 == 'v5'")) + Expect(gnp.Spec.Egress[3].Destination.Ports).To(Equal([]numorstring.Port{{MinPort: 20, MaxPort: 30}})) + + // 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)) + }) + + It("should parse an AdminNetworkPolicy with empty namespaces in Subject", func() { + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 500, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{}, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(500.0), nil) + + Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s'")) + Expect(gnp.Spec.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress).To(HaveLen(0)) + Expect(gnp.Spec.Egress).To(HaveLen(0)) + }) + + It("should parse an AdminNetworkPolicy with empty podSelector in Subject", 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{}, + }, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(600.0), nil) + + Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s'")) + Expect(gnp.Spec.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Ingress).To(HaveLen(0)) + Expect(gnp.Spec.Egress).To(HaveLen(0)) + }) + + It("should parse an AdminNetworkPolicy with a rule with namespaceSelector", 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", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Allow", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "namespaceRole": "dev", + "namespaceFoo": "bar", + }, + }, + }, + }, + }, + }, + }, + } + + 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(Equal("namespaceFoo == 'bar' && namespaceRole == 'dev'")) + + // 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 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", + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Allow", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "namespaceRole": "dev", + "namespaceFoo": "bar", + }, + }, + }, + }, + }, + }, + }, + }, + } + + 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.Egress)).To(Equal(1)) + Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(Equal("all()")) + Expect(gnp.Spec.Egress[0].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s' && namespaceFoo == 'bar' && namespaceRole == 'dev'")) + + // There should be no Ingress 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)) + }) + + 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", + 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", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Allow", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: nil, + Pods: nil, + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Pass", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: nil, + Pods: nil, + }, + }, + }, + }, + }, + } + + 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.", + }, + { + IngressRule: nil, + EgressRule: &adminpolicy.AdminNetworkPolicyEgressRule{ + Name: "A random egress rule", + Action: "Pass", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: nil, + Pods: nil, + }, + }, + }, + Reason: "k8s rule couldn't be converted: none of supported fields in 'To' is set.", + }, + }, + } + + 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()")) + + // There should be no rules. + Expect(gnp.Spec.Ingress).To(HaveLen(0)) + Expect(gnp.Spec.Egress).To(HaveLen(0)) + }) + + It("should parse an AdminNetworkPolicy with a rule with empty namespaceSelector", 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", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Allow", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{}, + }, + }, + }, + }, + }, + }, + } + + 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(Equal("all()")) + + // 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 empty 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", + }, + }, + }, + }, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Name: "A random egress rule", + Action: "Pass", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Pods: &adminpolicy.NamespacedPod{ + NamespaceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{}, + }, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{}, + }, + }, + }, + }, + }, + }, + }, + } + + 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.Egress)).To(Equal(1)) + Expect(gnp.Spec.Egress[0].Destination.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s'")) + Expect(gnp.Spec.Egress[0].Destination.NamespaceSelector).To(Equal("all()")) + + // There should be no Ingress 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)) + }) + + It("should parse an AdminNetworkPolicy with a rule with a rule with both Namespaces and Pods", func() { + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 1000, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + }, + }, + }, + }, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Name: "A random ingress rule", + Action: "Deny", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Pods: &adminpolicy.NamespacedPod{ + NamespaceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "namespaceRole": "dev", + "namespaceFoo": "bar", + }, + }, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "podA": "B", + "podC": "D", + }, + }, + }, + }, + }, + }, + }, + }, + } + + gnp := convertToGNP(&anp, float64(1000.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(Equal("projectcalico.org/orchestrator == 'k8s' && podA == 'B' && podC == 'D'")) + Expect(gnp.Spec.Ingress[0].Source.NamespaceSelector).To(Equal("namespaceFoo == 'bar' && namespaceRole == 'dev'")) + + // 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 Subject with MatchExpressions", func() { + anp := adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 500, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "k", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"v1", "v2"}, + }, + }, + }, + }, + }, + } + + // Convert the policy + gnp := convertToGNP(&anp, float64(500.0), nil) + + // Assert value fields are correct. + Expect(gnp.Spec.NamespaceSelector).To(Equal("k in { 'v1', 'v2' }")) + Expect(gnp.Spec.Selector).To(Equal("projectcalico.org/orchestrator == 'k8s'")) + Expect(gnp.Spec.Ingress).To(HaveLen(0)) + + // 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)) + }) +}) diff --git a/libcalico-go/lib/backend/k8s/conversion/constants.go b/libcalico-go/lib/backend/k8s/conversion/constants.go index 504f4d4fefa..c7fa01ad0a1 100644 --- a/libcalico-go/lib/backend/k8s/conversion/constants.go +++ b/libcalico-go/lib/backend/k8s/conversion/constants.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2017-2024 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package conversion const ( NamespaceLabelPrefix = "pcns." NamespaceProfileNamePrefix = "kns." - K8sNetworkPolicyNamePrefix = "knp.default." ServiceAccountLabelPrefix = "pcsa." ServiceAccountProfileNamePrefix = "ksa." @@ -44,4 +43,8 @@ const ( // NameLabel is a label that can be used to match a serviceaccount or namespace // name exactly. NameLabel = "projectcalico.org/name" + + // AdminPolicyRuleNameLabel is a label that show a rule's name before conversion to Calico data model. + // As an example, it holds an admin network policy rule name before conversion to GNPs. + AdminPolicyRuleNameLabel = "name" ) diff --git a/libcalico-go/lib/backend/k8s/conversion/conversion.go b/libcalico-go/lib/backend/k8s/conversion/conversion.go index d8eea0e24f5..2c8e44bc4fb 100644 --- a/libcalico-go/lib/backend/k8s/conversion/conversion.go +++ b/libcalico-go/lib/backend/k8s/conversion/conversion.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2024 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,10 +21,12 @@ import ( "strings" "github.com/google/uuid" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" kapiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" discovery "k8s.io/api/discovery/v1" networkingv1 "k8s.io/api/networking/v1" @@ -59,6 +61,7 @@ type Converter interface { HasIPAddress(pod *kapiv1.Pod) bool StagedKubernetesNetworkPolicyToStagedName(stagedK8sName string) string K8sNetworkPolicyToCalico(np *networkingv1.NetworkPolicy) (*model.KVPair, error) + K8sAdminNetworkPolicyToCalico(anp *adminpolicy.AdminNetworkPolicy) (*model.KVPair, error) EndpointSliceToKVP(svc *discovery.EndpointSlice) (*model.KVPair, error) ServiceToKVP(service *kapiv1.Service) (*model.KVPair, error) ProfileNameToNamespace(profileName string) (string, error) @@ -245,7 +248,7 @@ func getPodIPs(pod *kapiv1.Pod) ([]*cnet.IPNet, error) { // StagedKubernetesNetworkPolicyToStagedName converts a StagedKubernetesNetworkPolicy name into a StagedNetworkPolicy name func (c converter) StagedKubernetesNetworkPolicyToStagedName(stagedK8sName string) string { - return fmt.Sprintf(K8sNetworkPolicyNamePrefix + stagedK8sName) + return fmt.Sprintf(names.K8sNetworkPolicyNamePrefix + stagedK8sName) } // EndpointSliceToKVP converts a k8s EndpointSlice to a model.KVPair. @@ -273,10 +276,390 @@ func (c converter) ServiceToKVP(service *kapiv1.Service) (*model.KVPair, error) }, nil } +// K8sAdminNetworkPolicyToCalico converts a k8s AdminNetworkPolicy to a model.KVPair. +func (c converter) K8sAdminNetworkPolicyToCalico(anp *adminpolicy.AdminNetworkPolicy) (*model.KVPair, error) { + // Pull out important fields. + policyName := fmt.Sprintf(names.K8sAdminNetworkPolicyNamePrefix + anp.Name) + order := float64(anp.Spec.Priority) + errorTracker := cerrors.ErrorAdminPolicyConversion{PolicyName: anp.Name} + + // Generate the ingress rules list. + var ingressRules []apiv3.Rule + for _, r := range anp.Spec.Ingress { + rules, err := k8sANPIngressRuleToCalico(r) + if err != nil { + log.WithError(err).Warn("dropping k8s rule that couldn't be converted.") + // Add rule to conversion error slice + errorTracker.BadIngressRule(&r, fmt.Sprintf("k8s rule couldn't be converted: %s", err)) + failClosedRule := k8sANPHandleFailedRules(r.Action) + if failClosedRule != nil { + ingressRules = append(ingressRules, *failClosedRule) + } + } else { + ingressRules = append(ingressRules, rules...) + } + } + + // Generate the egress rules list. + var egressRules []apiv3.Rule + for _, r := range anp.Spec.Egress { + rules, err := k8sANPEgressRuleToCalico(r) + if err != nil { + log.WithError(err).Warn("dropping k8s rule that couldn't be converted.") + // Add rule to conversion error slice + errorTracker.BadEgressRule(&r, fmt.Sprintf("k8s rule couldn't be converted: %s", err)) + failClosedRule := k8sANPHandleFailedRules(r.Action) + if failClosedRule != nil { + egressRules = append(egressRules, *failClosedRule) + } + } else { + egressRules = append(egressRules, rules...) + } + } + + // Calculate Types setting. + policyTypes := []apiv3.PolicyType{} + if len(anp.Spec.Ingress) != 0 { + policyTypes = append(policyTypes, apiv3.PolicyTypeIngress) + } + if len(anp.Spec.Egress) != 0 { + policyTypes = append(policyTypes, apiv3.PolicyTypeEgress) + } + + // Either Namespaces or Pods is set. Use one of them to populate the selectors. + var nsSelector, podSelector string + if anp.Spec.Subject.Namespaces != nil { + nsSelector = k8sSelectorToCalico(anp.Spec.Subject.Namespaces, SelectorNamespace) + // Make sure projectcalico.org/orchestrator == 'k8s' label is added to exclude heps. + podSelector = k8sSelectorToCalico(nil, SelectorPod) + } else { + nsSelector = k8sSelectorToCalico(&anp.Spec.Subject.Pods.NamespaceSelector, SelectorNamespace) + podSelector = k8sSelectorToCalico(&anp.Spec.Subject.Pods.PodSelector, SelectorPod) + } + + var uid types.UID + var err error + if anp.UID != "" { + uid, err = ConvertUID(anp.UID) + if err != nil { + return nil, err + } + } + + gnp := apiv3.NewGlobalNetworkPolicy() + gnp.ObjectMeta = metav1.ObjectMeta{ + Name: policyName, + CreationTimestamp: anp.CreationTimestamp, + UID: uid, + ResourceVersion: anp.ResourceVersion, + } + gnp.Spec = apiv3.GlobalNetworkPolicySpec{ + Tier: names.AdminNetworkPolicyTierName, + Order: &order, + NamespaceSelector: nsSelector, + Selector: podSelector, + Ingress: ingressRules, + Egress: egressRules, + Types: policyTypes, + } + + // Build the KVPair. + kvp := &model.KVPair{ + Key: model.ResourceKey{ + Name: policyName, + Kind: apiv3.KindGlobalNetworkPolicy, + }, + Value: gnp, + Revision: anp.ResourceVersion, + } + + // Return the KVPair with conversion errors if applicable + return kvp, errorTracker.GetError() +} + +func k8sANPHandleFailedRules(action adminpolicy.AdminNetworkPolicyRuleAction) *apiv3.Rule { + if action == adminpolicy.AdminNetworkPolicyRuleActionDeny { + logrus.Warn("replacing failed rule with a deny-all one.") + return &apiv3.Rule{ + Action: apiv3.Deny, + } + } + return nil +} + +func k8sANPIngressRuleToCalico(rule adminpolicy.AdminNetworkPolicyIngressRule) ([]apiv3.Rule, error) { + rules := []apiv3.Rule{} + + action, err := K8sAdminNetworkPolicyActionToCalico(rule.Action) + if err != nil { + return nil, err + } + + // If there no ports, represent that as zero struct. + ports := []adminpolicy.AdminNetworkPolicyPort{{}} + if rule.Ports != nil && len(*rule.Ports) != 0 { + ports = *rule.Ports + } + + protocolPorts := map[string][]numorstring.Port{} + + for _, port := range ports { + protocol, calicoPort, err := k8sAdminPolicyPortToCalicoFields(&port) + if err != nil { + return nil, fmt.Errorf("failed to parse k8s port: %s", err) + } + + if protocol == nil && calicoPort == nil { + // If nil, no ports were specified, or an empty port struct was provided, which we translate to allowing all. + // We want to use a nil protocol and a nil list of ports, which will allow any destination (for ingress). + // Given we're gonna allow all, we may as well break here and keep only this rule + protocolPorts = map[string][]numorstring.Port{"": nil} + break + } + + pStr := protocol.String() + // treat nil as 'all ports' + if calicoPort == nil { + protocolPorts[pStr] = nil + } else if _, ok := protocolPorts[pStr]; !ok || len(protocolPorts[pStr]) > 0 { + // don't overwrite a nil (allow all ports) if present; if no ports yet for this protocol + // or 1+ ports which aren't 'all ports', then add the present ports + protocolPorts[pStr] = append(protocolPorts[pStr], *calicoPort) + } + } + + protocols := make([]string, 0, len(protocolPorts)) + for k := range protocolPorts { + protocols = append(protocols, k) + } + // Ensure deterministic output + sort.Strings(protocols) + + // Combine destinations with sources to generate rules. We generate one rule per protocol, + // with each rule containing all the allowed ports. + for _, protocolStr := range protocols { + calicoPorts := protocolPorts[protocolStr] + calicoPorts = SimplifyPorts(calicoPorts) + + var protocol *numorstring.Protocol + if protocolStr != "" { + p := numorstring.ProtocolFromString(protocolStr) + protocol = &p + } + + // Based on specifications at least one Peer is set. + var selector, nsSelector string + for _, peer := range rule.From { + var found bool + if peer.Namespaces != nil { + selector = "" + nsSelector = k8sSelectorToCalico(peer.Namespaces, SelectorNamespace) + found = true + } + if peer.Pods != nil { + selector = k8sSelectorToCalico(&peer.Pods.PodSelector, SelectorPod) + nsSelector = k8sSelectorToCalico(&peer.Pods.NamespaceSelector, SelectorNamespace) + found = true + } + if !found { + return nil, fmt.Errorf("none of supported fields in 'From' is set.") + } + + // Build inbound rule and append to list. + rules = append(rules, apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata(rule.Name), + Action: action, + Protocol: protocol, + Source: apiv3.EntityRule{ + Selector: selector, + NamespaceSelector: nsSelector, + }, + Destination: apiv3.EntityRule{ + Ports: calicoPorts, + }, + }) + } + } + + return rules, nil +} + +func k8sANPEgressRuleToCalico(rule adminpolicy.AdminNetworkPolicyEgressRule) ([]apiv3.Rule, error) { + rules := []apiv3.Rule{} + + action, err := K8sAdminNetworkPolicyActionToCalico(rule.Action) + if err != nil { + return nil, err + } + + // If there no ports, represent that as zero struct. + ports := []adminpolicy.AdminNetworkPolicyPort{{}} + if rule.Ports != nil && len(*rule.Ports) != 0 { + ports = *rule.Ports + } + + protocolPorts := map[string][]numorstring.Port{} + + for _, port := range ports { + protocol, calicoPort, err := k8sAdminPolicyPortToCalicoFields(&port) + if err != nil { + return nil, fmt.Errorf("failed to parse k8s port: %s", err) + } + + if protocol == nil && calicoPort == nil { + // If nil, no ports were specified, or an empty port struct was provided, which we translate to allowing all. + // We want to use a nil protocol and a nil list of ports, which will allow any destination (for ingress). + // Given we're gonna allow all, we may as well break here and keep only this rule + protocolPorts = map[string][]numorstring.Port{"": nil} + break + } + + pStr := protocol.String() + // treat nil as 'all ports' + if calicoPort == nil { + protocolPorts[pStr] = nil + } else if _, ok := protocolPorts[pStr]; !ok || len(protocolPorts[pStr]) > 0 { + // don't overwrite a nil (allow all ports) if present; if no ports yet for this protocol + // or 1+ ports which aren't 'all ports', then add the present ports + protocolPorts[pStr] = append(protocolPorts[pStr], *calicoPort) + } + } + + protocols := make([]string, 0, len(protocolPorts)) + for k := range protocolPorts { + protocols = append(protocols, k) + } + // Ensure deterministic output + sort.Strings(protocols) + + // Combine destinations with sources to generate rules. We generate one rule per protocol, + // with each rule containing all the allowed ports. + for _, protocolStr := range protocols { + calicoPorts := protocolPorts[protocolStr] + calicoPorts = SimplifyPorts(calicoPorts) + + var protocol *numorstring.Protocol + if protocolStr != "" { + p := numorstring.ProtocolFromString(protocolStr) + protocol = &p + } + + // Based on specifications at least one Peer is set. + var selector, nsSelector string + for _, peer := range rule.To { + var found bool + if peer.Namespaces != nil { + selector = "" + nsSelector = k8sSelectorToCalico(peer.Namespaces, SelectorNamespace) + found = true + } + if peer.Pods != nil { + selector = k8sSelectorToCalico(&peer.Pods.PodSelector, SelectorPod) + nsSelector = k8sSelectorToCalico(&peer.Pods.NamespaceSelector, SelectorNamespace) + found = true + } + if !found { + return nil, fmt.Errorf("none of supported fields in 'To' is set.") + } + + // Build outbound rule and append to list. + rules = append(rules, apiv3.Rule{ + Metadata: k8sAdminNetworkPolicyToCalicoMetadata(rule.Name), + Action: action, + Protocol: protocol, + Destination: apiv3.EntityRule{ + Ports: calicoPorts, + Selector: selector, + NamespaceSelector: nsSelector, + }, + }) + } + } + + return rules, nil +} + +func K8sAdminNetworkPolicyActionToCalico(action adminpolicy.AdminNetworkPolicyRuleAction) (apiv3.Action, error) { + switch action { + case adminpolicy.AdminNetworkPolicyRuleActionAllow, + adminpolicy.AdminNetworkPolicyRuleActionDeny, + adminpolicy.AdminNetworkPolicyRuleActionPass: + return apiv3.Action(action), nil + default: + return "", fmt.Errorf("unsupported admin network policy action %v", action) + } +} + +func k8sAdminNetworkPolicyToCalicoMetadata(ruleName string) *apiv3.RuleMetadata { + if ruleName == "" { + return nil + } + return &apiv3.RuleMetadata{ + Annotations: map[string]string{ + AdminPolicyRuleNameLabel: ruleName, + }, + } +} + +func ensureProtocol(proto kapiv1.Protocol) kapiv1.Protocol { + if proto != "" { + return proto + } + return kapiv1.ProtocolTCP +} + +func k8sAdminPolicyPortToCalicoFields(port *adminpolicy.AdminNetworkPolicyPort) ( + protocol *numorstring.Protocol, + dstPort *numorstring.Port, + err error, +) { + // If no port info, return zero values for all fields (protocol, dstPorts). + if port == nil { + return + } + // Only one of the PortNumber or PortRange is set. + if port.PortNumber != nil { + dstPort = k8sAdminPolicyPortToCalico(port.PortNumber) + proto := ensureProtocol(port.PortNumber.Protocol) + protocol = k8sProtocolToCalico(&proto) + return + } + if port.PortRange != nil { + dstPort, err = k8sAdminPolicyPortRangeToCalico(port.PortRange) + if err != nil { + return + } + proto := ensureProtocol(port.PortRange.Protocol) + protocol = k8sProtocolToCalico(&proto) + return + } + // TODO: Add support for NamedPorts + return +} + +func k8sAdminPolicyPortToCalico(port *adminpolicy.Port) *numorstring.Port { + if port == nil { + return nil + } + p := numorstring.SinglePort(uint16(port.Port)) + return &p +} + +func k8sAdminPolicyPortRangeToCalico(port *adminpolicy.PortRange) (*numorstring.Port, error) { + if port == nil { + return nil, nil + } + p, err := numorstring.PortFromRange(uint16(port.Start), uint16(port.End)) + if err != nil { + return nil, err + } + return &p, nil +} + // K8sNetworkPolicyToCalico converts a k8s NetworkPolicy to a model.KVPair. func (c converter) K8sNetworkPolicyToCalico(np *networkingv1.NetworkPolicy) (*model.KVPair, error) { // Pull out important fields. - policyName := fmt.Sprintf(K8sNetworkPolicyNamePrefix + np.Name) + policyName := fmt.Sprintf(names.K8sNetworkPolicyNamePrefix + np.Name) // We insert all the NetworkPolicy Policies at order 1000.0 after conversion. // This order might change in future. @@ -361,7 +744,7 @@ func (c converter) K8sNetworkPolicyToCalico(np *networkingv1.NetworkPolicy) (*mo } policy.Spec = apiv3.NetworkPolicySpec{ Order: &order, - Selector: c.k8sSelectorToCalico(&np.Spec.PodSelector, SelectorPod), + Selector: k8sSelectorToCalico(&np.Spec.PodSelector, SelectorPod), Ingress: ingressRules, Egress: egressRules, Types: policyTypes, @@ -384,7 +767,7 @@ func (c converter) K8sNetworkPolicyToCalico(np *networkingv1.NetworkPolicy) (*mo // k8sSelectorToCalico takes a namespaced k8s label selector and returns the Calico // equivalent. -func (c converter) k8sSelectorToCalico(s *metav1.LabelSelector, selectorType selectorType) string { +func k8sSelectorToCalico(s *metav1.LabelSelector, selectorType selectorType) string { // Only prefix pod selectors - this won't work for namespace selectors. selectors := []string{} if selectorType == SelectorPod { @@ -643,11 +1026,11 @@ func (c converter) k8sPortToCalicoFields(port *networkingv1.NetworkPolicyPort) ( if err != nil { return } - protocol = c.k8sProtocolToCalico(port.Protocol) + protocol = k8sProtocolToCalico(port.Protocol) return } -func (c converter) k8sProtocolToCalico(protocol *kapiv1.Protocol) *numorstring.Protocol { +func k8sProtocolToCalico(protocol *kapiv1.Protocol) *numorstring.Protocol { if protocol != nil { p := numorstring.ProtocolFromString(string(*protocol)) return &p @@ -686,8 +1069,8 @@ func (c converter) k8sPeerToCalicoFields(peer *networkingv1.NetworkPolicyPeer, n // IPBlock is not set to get here. // Note that k8sSelectorToCalico() accepts nil values of the selector. - selector = c.k8sSelectorToCalico(peer.PodSelector, SelectorPod) - nsSelector = c.k8sSelectorToCalico(peer.NamespaceSelector, SelectorNamespace) + selector = k8sSelectorToCalico(peer.PodSelector, SelectorPod) + nsSelector = k8sSelectorToCalico(peer.NamespaceSelector, SelectorNamespace) return } diff --git a/libcalico-go/lib/backend/k8s/conversion/conversion_test.go b/libcalico-go/lib/backend/k8s/conversion/conversion_test.go index b485d60275b..6203a8842c5 100644 --- a/libcalico-go/lib/backend/k8s/conversion/conversion_test.go +++ b/libcalico-go/lib/backend/k8s/conversion/conversion_test.go @@ -111,9 +111,7 @@ var _ = Describe("Test selector conversion", func() { DescribeTable("selector conversion table", func(inSelector *metav1.LabelSelector, selectorType selectorType, expected string) { // First, convert the NetworkPolicy using the k8s conversion logic. - c := converter{} - - converted := c.k8sSelectorToCalico(inSelector, selectorType) + converted := k8sSelectorToCalico(inSelector, selectorType) // Finally, assert the expected result. Expect(converted).To(Equal(expected)) diff --git a/libcalico-go/lib/backend/k8s/k8s.go b/libcalico-go/lib/backend/k8s/k8s.go index 12c81a3108d..40ee065f727 100644 --- a/libcalico-go/lib/backend/k8s/k8s.go +++ b/libcalico-go/lib/backend/k8s/k8s.go @@ -47,6 +47,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + adminpolicyclient "sigs.k8s.io/network-policy-api/pkg/client/clientset/versioned/typed/apis/v1alpha1" ) var ( @@ -61,6 +62,9 @@ type KubeClient struct { // Client for interacting with CustomResourceDefinition. crdClientV1 *rest.RESTClient + // Client for interacting with K8S Admin Network Policy, and BaselineAdminNetworkPolicy. + k8sAdminPolicyClient *adminpolicyclient.PolicyV1alpha1Client + disableNodePoll bool // Contains methods for converting Kubernetes resources to @@ -88,9 +92,15 @@ func NewKubeClient(ca *apiconfig.CalicoAPIConfigSpec) (api.Client, error) { return nil, fmt.Errorf("Failed to build V1 CRD client: %v", err) } + k8sAdminPolicyClient, err := buildK8SAdminPolicyClient(config) + if err != nil { + return nil, fmt.Errorf("Failed to build K8S Admin Network Policy client: %v", err) + } + kubeClient := &KubeClient{ ClientSet: cs, crdClientV1: crdClientV1, + k8sAdminPolicyClient: k8sAdminPolicyClient, disableNodePoll: ca.K8sDisableNodePoll, clientsByResourceKind: make(map[string]resources.K8sResourceClient), clientsByKeyType: make(map[reflect.Type]resources.K8sResourceClient), @@ -116,6 +126,12 @@ func NewKubeClient(ca *apiconfig.CalicoAPIConfigSpec) (api.Client, error) { apiv3.KindGlobalNetworkPolicy, resources.NewGlobalNetworkPolicyClient(cs, crdClientV1), ) + kubeClient.registerResourceClient( + reflect.TypeOf(model.ResourceKey{}), + reflect.TypeOf(model.ResourceListOptions{}), + model.KindKubernetesAdminNetworkPolicy, + resources.NewKubernetesAdminNetworkPolicyClient(k8sAdminPolicyClient), + ) kubeClient.registerResourceClient( reflect.TypeOf(model.ResourceKey{}), reflect.TypeOf(model.ResourceListOptions{}), @@ -500,6 +516,11 @@ func (c *KubeClient) Close() error { var addToSchemeOnce sync.Once +// buildK8SAdminPolicyClient builds a RESTClient configured to interact (Baseline) Admin Network Policy. +func buildK8SAdminPolicyClient(cfg *rest.Config) (*adminpolicyclient.PolicyV1alpha1Client, error) { + return adminpolicyclient.NewForConfig(cfg) +} + // buildCRDClientV1 builds a RESTClient configured to interact with Calico CustomResourceDefinitions func buildCRDClientV1(cfg rest.Config) (*rest.RESTClient, error) { // Generate config using the base config. diff --git a/libcalico-go/lib/backend/k8s/k8s_test.go b/libcalico-go/lib/backend/k8s/k8s_test.go index 6f6504a4a3c..301a8aa0daa 100644 --- a/libcalico-go/lib/backend/k8s/k8s_test.go +++ b/libcalico-go/lib/backend/k8s/k8s_test.go @@ -35,6 +35,8 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" + adminpolicyclient "sigs.k8s.io/network-policy-api/pkg/client/clientset/versioned/typed/apis/v1alpha1" apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" "github.com/projectcalico/api/pkg/lib/numorstring" @@ -2729,8 +2731,9 @@ var _ = testutils.E2eDatastoreDescribe("Test Syncer API for Kubernetes backend", var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.DatastoreK8s, func(cfg apiconfig.CalicoAPIConfig) { var ( - c *KubeClient - ctx context.Context + c *KubeClient + anpClient *adminpolicyclient.PolicyV1alpha1Client + ctx context.Context ) BeforeEach(func() { @@ -2739,6 +2742,12 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore Expect(err).NotTo(HaveOccurred()) c = client.(*KubeClient) + config, _, err := CreateKubernetesClientset(&cfg.Spec) + Expect(err).NotTo(HaveOccurred()) + config.ContentType = runtime.ContentTypeJSON + anpClient, err = buildK8SAdminPolicyClient(config) + Expect(err).NotTo(HaveOccurred()) + ctx = context.Background() }) @@ -2791,6 +2800,69 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore }) }) + Describe("watching AdminNetworkPolicies", func() { + createTestAdminNetworkPolicy := func(name string) { + anp := &adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 100, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + }, + }, + }, + }, + } + _, err := anpClient.AdminNetworkPolicies().Create(ctx, anp, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + } + deleteAllAdminNetworkPolicies := func() { + var zero int64 + err := anpClient.AdminNetworkPolicies().DeleteCollection( + ctx, + metav1.DeleteOptions{GracePeriodSeconds: &zero}, + metav1.ListOptions{}, + ) + Expect(err).NotTo(HaveOccurred()) + } + BeforeEach(func() { + createTestAdminNetworkPolicy("test-admin-net-policy-1") + createTestAdminNetworkPolicy("test-admin-net-policy-2") + }) + AfterEach(func() { + deleteAllAdminNetworkPolicies() + }) + It("supports watching all adminnetworkpolicies", func() { + watch, err := c.Watch(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, "") + Expect(err).NotTo(HaveOccurred()) + defer watch.Stop() + ExpectAddedEvent(watch.ResultChan()) + }) + It("supports resuming watch from previous revision", func() { + watch, err := c.Watch(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, "") + Expect(err).NotTo(HaveOccurred()) + event := ExpectAddedEvent(watch.ResultChan()) + watch.Stop() + + watch, err = c.Watch(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, event.New.Revision) + Expect(err).NotTo(HaveOccurred()) + watch.Stop() + }) + It("should handle a list for many network policies with a revision", func() { + for i := 3; i < 1000; i++ { + createTestAdminNetworkPolicy(fmt.Sprintf("test-admin-net-policy-%d", i)) + } + kvs, err := c.List(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, "") + Expect(err).NotTo(HaveOccurred()) + _, err = c.List(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, kvs.Revision) + Expect(err).NotTo(HaveOccurred()) + }) + }) + Describe("watching NetworkPolicies (native)", func() { createTestNetworkPolicy := func(name string) { np := networkingv1.NetworkPolicy{ @@ -2893,7 +2965,35 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore }) }) - Describe("watching / listing network polices (k8s and Calico)", func() { + Describe("watching / listing network polices (k8s and Calico) and admin network policies", func() { + createTestAdminNetworkPolicy := func(name string) { + anp := &adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Priority: 100, + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "label": "value", + }, + }, + }, + }, + } + _, err := anpClient.AdminNetworkPolicies().Create(ctx, anp, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + } + deleteAllAdminNetworkPolicies := func() { + var zero int64 + err := anpClient.AdminNetworkPolicies().DeleteCollection( + ctx, + metav1.DeleteOptions{GracePeriodSeconds: &zero}, + metav1.ListOptions{}, + ) + Expect(err).NotTo(HaveOccurred()) + } createCalicoNetworkPolicy := func(name string) { np := &model.KVPair{ Key: model.ResourceKey{ @@ -2932,7 +3032,9 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore Expect(err).NotTo(HaveOccurred()) } BeforeEach(func() { - // Create 2x Calico NP and 2x k8s NP + // Create 2x Calico NP and 2x k8s NP and 2x k8s ANP + createTestAdminNetworkPolicy("test-admin-net-policy-1") + createTestAdminNetworkPolicy("test-admin-net-policy-2") createCalicoNetworkPolicy("test-net-policy-1") createCalicoNetworkPolicy("test-net-policy-2") createK8sNetworkPolicy("test-net-policy-3") @@ -2942,6 +3044,7 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore AfterEach(func() { log.Info("[Test] Beginning Cleanup ----") deleteAllNetworkPolicies() + deleteAllAdminNetworkPolicies() }) It("supports resuming watch from previous revision (calico)", func() { @@ -3070,6 +3173,72 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore watch.Stop() }) + It("supports resuming watch from previous revision k8s admin network policy", func() { + // Should only return k8s ANPs + l, err := c.List(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, "") + Expect(err).NotTo(HaveOccurred()) + Expect(l.KVPairs).To(HaveLen(2)) + + // Now, modify all the policies. It's important to do this with + // multiple policies of each type, because we want to test that revision + // numbers come out in a sensible order. We're going to resume the watch + // from the "last" event to come out of the watch, and if it doesn't + // really represent the latest update, when we resume watching, we + // will get duplicate events. Worse, if the "last" event from a watch + // doesn't represent the latest state, this implies some earlier + // event from the watch did, and if we happened to have stopped the + // watch at that point we would have missed some data! + + // Modify the kubernetes policies + found := 0 + for _, kvp := range l.KVPairs { + name := strings.TrimPrefix(kvp.Value.(*apiv3.GlobalNetworkPolicy).Name, "kanp.adminnetworkpolicy.") + p, err := anpClient.AdminNetworkPolicies().Get(ctx, name, metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) + p.SetLabels(map[string]string{"test": "00"}) + _, err = anpClient.AdminNetworkPolicies().Update(ctx, p, metav1.UpdateOptions{}) + Expect(err).ToNot(HaveOccurred()) + found++ + } + Expect(found).To(Equal(2)) + + log.WithField("revision", l.Revision).Info("[TEST] first watch") + watch, err := c.Watch(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, l.Revision) + Expect(err).NotTo(HaveOccurred()) + + event := ExpectModifiedEvent(watch.ResultChan()) + log.WithField("revision", event.New.Revision).Info("[TEST] first k8s event") + event = ExpectModifiedEvent(watch.ResultChan()) + log.WithField("revision", event.New.Revision).Info("[TEST] second k8s event") + + // There should be no more events + Expect(watch.ResultChan()).ToNot(Receive()) + watch.Stop() + + // Make a second change to one of the NPs + for _, kvp := range l.KVPairs { + name := strings.TrimPrefix(kvp.Value.(*apiv3.GlobalNetworkPolicy).Name, "kanp.adminnetworkpolicy.") + p, err := anpClient.AdminNetworkPolicies().Get(ctx, name, metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) + p.SetLabels(map[string]string{"test": "01"}) + _, err = anpClient.AdminNetworkPolicies().Update(ctx, p, metav1.UpdateOptions{}) + Expect(err).ToNot(HaveOccurred()) + break + } + + // Resume watching at the revision of the event we got + log.WithField("revision", event.New.Revision).Info("second watch") + watch, err = c.Watch(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, event.New.Revision) + Expect(err).NotTo(HaveOccurred()) + + // We should only get 1 update, because the event from the previous watch should have been "latest" + ExpectModifiedEvent(watch.ResultChan()) + + // There should be no more events + Expect(watch.ResultChan()).ToNot(Receive()) + watch.Stop() + }) + It("supports watching from part way through a list (calico)", func() { // Only 2 Calico NPs l, err := c.List(ctx, model.ResourceListOptions{Kind: apiv3.KindNetworkPolicy}, "") @@ -3093,7 +3262,7 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore }) It("supports watching from part way through a list (k8s)", func() { - // Only 2 Calico NPs + // Only 2 k8s NPs l, err := c.List(ctx, model.ResourceListOptions{Kind: model.KindKubernetesNetworkPolicy}, "") Expect(err).ToNot(HaveOccurred()) Expect(l.KVPairs).To(HaveLen(2)) @@ -3113,6 +3282,28 @@ var _ = testutils.E2eDatastoreDescribe("Test Watch support", testutils.Datastore watch.Stop() } }) + + It("supports watching from part way through a list of Admin Network Policies", func() { + // Only 2 k8s ANPs + l, err := c.List(ctx, model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, "") + Expect(err).ToNot(HaveOccurred()) + Expect(l.KVPairs).To(HaveLen(2)) + + // Watch from part way + for i := 0; i < 2; i++ { + revision := l.KVPairs[i].Revision + log.WithFields(log.Fields{ + "revision": revision, + "key": l.KVPairs[i].Key.String(), + }).Info("[Test] starting watch") + watch, err := c.Watch(ctx, model.ResourceListOptions{Kind: apiv3.KindGlobalNetworkPolicy}, revision) + Expect(err).ToNot(HaveOccurred()) + // Since the items in the list aren't guaranteed to be in any specific order, we + // can't assert anything useful about what you should get out of this watch, so we + // just confirm that there is no error. + watch.Stop() + } + }) }) Describe("watching Custom Resources", func() { diff --git a/libcalico-go/lib/backend/k8s/resources/kubeadminnetworkpolicy.go b/libcalico-go/lib/backend/k8s/resources/kubeadminnetworkpolicy.go new file mode 100644 index 00000000000..8c79a8e013d --- /dev/null +++ b/libcalico-go/lib/backend/k8s/resources/kubeadminnetworkpolicy.go @@ -0,0 +1,139 @@ +// Copyright (c) 2024 Tigera, Inc. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resources + +import ( + "context" + "errors" + "fmt" + + log "github.com/sirupsen/logrus" + + "github.com/projectcalico/calico/libcalico-go/lib/backend/api" + "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" + "github.com/projectcalico/calico/libcalico-go/lib/backend/model" + cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" + adminpolicyclient "sigs.k8s.io/network-policy-api/pkg/client/clientset/versioned/typed/apis/v1alpha1" +) + +// NewKubernetesAdminNetworkPolicyClient returns a new client for interacting with Kubernetes AdminNetworkPolicy objects. +// Note that this client is only intended for use by the felix syncer in KDD mode, and as such is largely unimplemented +// except for the functions required by the syncer. +func NewKubernetesAdminNetworkPolicyClient( + anpClient *adminpolicyclient.PolicyV1alpha1Client, +) K8sResourceClient { + return &adminNetworkPolicyClient{ + Converter: conversion.NewConverter(), + adminPolicyClient: anpClient, + } +} + +// Implements the api.Client interface for Kubernetes NetworkPolicy. +type adminNetworkPolicyClient struct { + conversion.Converter + adminPolicyClient *adminpolicyclient.PolicyV1alpha1Client +} + +func (c *adminNetworkPolicyClient) Create(ctx context.Context, kvp *model.KVPair) (*model.KVPair, error) { + log.Debug("Received Create request on AdminNetworkPolicy type") + return nil, cerrors.ErrorOperationNotSupported{ + Identifier: kvp.Key, + Operation: "Create", + } +} + +func (c *adminNetworkPolicyClient) Update(ctx context.Context, kvp *model.KVPair) (*model.KVPair, error) { + log.Debug("Received Update request on AdminNetworkPolicy type") + return nil, cerrors.ErrorOperationNotSupported{ + Identifier: kvp.Key, + Operation: "Update", + } +} + +func (c *adminNetworkPolicyClient) DeleteKVP(ctx context.Context, kvp *model.KVPair) (*model.KVPair, error) { + return c.Delete(ctx, kvp.Key, kvp.Revision, kvp.UID) +} + +func (c *adminNetworkPolicyClient) Delete(ctx context.Context, key model.Key, revision string, uid *types.UID) (*model.KVPair, error) { + log.Debug("Received Delete request on AdminNetworkPolicy type") + return nil, cerrors.ErrorOperationNotSupported{ + Identifier: key, + Operation: "Delete", + } +} + +func (c *adminNetworkPolicyClient) Get(ctx context.Context, key model.Key, revision string) (*model.KVPair, error) { + log.Debug("Received Get request on AdminNetworkPolicy type") + return nil, cerrors.ErrorOperationNotSupported{ + Identifier: key, + Operation: "Get", + } +} + +func (c *adminNetworkPolicyClient) List(ctx context.Context, list model.ListInterface, revision string) (*model.KVPairList, error) { + logContext := log.WithField("Resource", "AdminNetworkPolicy") + logContext.Debug("Received List request") + + listFunc := func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { + return c.adminPolicyClient.AdminNetworkPolicies().List(ctx, opts) + } + convertFunc := func(r Resource) ([]*model.KVPair, error) { + anp := r.(*adminpolicy.AdminNetworkPolicy) + kvp, err := c.K8sAdminNetworkPolicyToCalico(anp) + // Silently ignore rule conversion errors. We don't expect any conversion errors + // since the data given to us here is validated by the Kubernetes API. The conversion + // code ignores any rules that it cannot parse, and we will pass the valid ones to Felix. + var e *cerrors.ErrorAdminPolicyConversion + if err != nil && !errors.As(err, &e) { + return nil, err + } + return []*model.KVPair{kvp}, nil + } + return pagedList(ctx, logContext, revision, list, convertFunc, listFunc) +} + +func (c *adminNetworkPolicyClient) Watch(ctx context.Context, list model.ListInterface, revision string) (api.WatchInterface, error) { + // Build watch options to pass to k8s. + opts := metav1.ListOptions{Watch: true, AllowWatchBookmarks: false} + _, ok := list.(model.ResourceListOptions) + if !ok { + return nil, fmt.Errorf("ListInterface is not a ResourceListOptions: %s", list) + } + + opts.ResourceVersion = revision + log.Debugf("Watching Kubernetes AdminNetworkPolicy at revision %q", revision) + k8sRawWatch, err := c.adminPolicyClient.AdminNetworkPolicies().Watch(ctx, opts) + if err != nil { + return nil, K8sErrorToCalico(err, list) + } + converter := func(r Resource) (*model.KVPair, error) { + anp, ok := r.(*adminpolicy.AdminNetworkPolicy) + if !ok { + return nil, errors.New("Kubernetes AdminNetworkPolicy conversion with incorrect k8s resource type") + } + + return c.K8sAdminNetworkPolicyToCalico(anp) + } + return newK8sWatcherConverter(ctx, "Kubernetes AdminNetworkPolicy", converter, k8sRawWatch), nil +} + +func (c *adminNetworkPolicyClient) EnsureInitialized() error { + return nil +} diff --git a/libcalico-go/lib/backend/model/kubeadminnetworkpolicy.go b/libcalico-go/lib/backend/model/kubeadminnetworkpolicy.go new file mode 100644 index 00000000000..899b3511d65 --- /dev/null +++ b/libcalico-go/lib/backend/model/kubeadminnetworkpolicy.go @@ -0,0 +1,19 @@ +// Copyright (c) 2024 Tigera, Inc. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +const ( + KindKubernetesAdminNetworkPolicy = "KubernetesAdminNetworkPolicy" +) diff --git a/libcalico-go/lib/backend/model/resource.go b/libcalico-go/lib/backend/model/resource.go index 95dcd3cb2a9..ba1a67c3166 100644 --- a/libcalico-go/lib/backend/model/resource.go +++ b/libcalico-go/lib/backend/model/resource.go @@ -95,6 +95,11 @@ func init() { "globalnetworksets", reflect.TypeOf(apiv3.GlobalNetworkSet{}), ) + registerResourceInfo( + KindKubernetesAdminNetworkPolicy, + "kubernetesadminnetworkpolicies", + reflect.TypeOf(apiv3.GlobalNetworkPolicy{}), + ) registerResourceInfo( apiv3.KindIPPool, "ippools", diff --git a/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncer_e2e_test.go b/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncer_e2e_test.go index 3dcf02d351a..892d8f35df4 100644 --- a/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncer_e2e_test.go +++ b/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncer_e2e_test.go @@ -38,6 +38,7 @@ import ( "github.com/projectcalico/calico/libcalico-go/lib/backend/syncersv1/felixsyncer" "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/ipam" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/net" "github.com/projectcalico/calico/libcalico-go/lib/options" "github.com/projectcalico/calico/libcalico-go/lib/resources" @@ -408,12 +409,17 @@ var _ = testutils.E2eDatastoreDescribe("Felix syncer tests", testutils.Datastore model.GlobalConfigKey{Name: "ClusterGUID"}, MatchRegexp("[a-f0-9]{32}"), ) - // Creating the node also creates default tier. + // Creating the node also creates default and adminnetworkpolicy tiers. order := apiv3.DefaultTierOrder syncTester.ExpectData(model.KVPair{ - Key: model.TierKey{Name: "default"}, + Key: model.TierKey{Name: names.DefaultTierName}, Value: &model.Tier{Order: &order}, }) + anpOrder := apiv3.AdminNetworkPolicyTierOrder + syncTester.ExpectData(model.KVPair{ + Key: model.TierKey{Name: names.AdminNetworkPolicyTierName}, + Value: &model.Tier{Order: &anpOrder}, + }) syncTester.ExpectData(model.KVPair{ Key: model.HostConfigKey{Hostname: "127.0.0.1", Name: "IpInIpTunnelAddr"}, Value: "192.168.0.1", @@ -427,7 +433,7 @@ var _ = testutils.E2eDatastoreDescribe("Felix syncer tests", testutils.Datastore Value: &model.Wireguard{InterfaceIPv4Addr: &wip, PublicKey: "jlkVyQYooZYzI2wFfNhSZez5eWh44yfq1wKVjLvSXgY="}, }) // add one for the node resource - expectedCacheSize += 6 + expectedCacheSize += 7 } // The HostIP will be added for the IPv4 address diff --git a/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncerv1.go b/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncerv1.go index d99f60920a3..19f7595f909 100644 --- a/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncerv1.go +++ b/libcalico-go/lib/backend/syncersv1/felixsyncer/felixsyncerv1.go @@ -94,6 +94,10 @@ func New(client api.Client, cfg apiconfig.CalicoAPIConfigSpec, callbacks api.Syn ListInterface: model.ResourceListOptions{Kind: model.KindKubernetesNetworkPolicy}, UpdateProcessor: updateprocessors.NewNetworkPolicyUpdateProcessor(), }) + additionalTypes = append(additionalTypes, watchersyncer.ResourceType{ + ListInterface: model.ResourceListOptions{Kind: model.KindKubernetesAdminNetworkPolicy}, + UpdateProcessor: updateprocessors.NewGlobalNetworkPolicyUpdateProcessor(), + }) additionalTypes = append(additionalTypes, watchersyncer.ResourceType{ ListInterface: model.ResourceListOptions{Kind: model.KindKubernetesEndpointSlice}, }) diff --git a/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go b/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go index 2cfc739ad9e..66c566685a4 100644 --- a/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go +++ b/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go @@ -16,10 +16,17 @@ package updateprocessors_test import ( . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" + apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" + "github.com/projectcalico/api/pkg/lib/numorstring" + "github.com/projectcalico/calico/libcalico-go/lib/backend/k8s/conversion" "github.com/projectcalico/calico/libcalico-go/lib/backend/model" "github.com/projectcalico/calico/libcalico-go/lib/backend/syncersv1/updateprocessors" cnet "github.com/projectcalico/calico/libcalico-go/lib/net" @@ -247,3 +254,137 @@ var _ = Describe("Test the GlobalNetworkPolicy update processor", func() { }) }) }) + +// Define AdminNetworkPolicies and the corresponding expected v1 KVPairs. +// +// anp1 is an AdminNetworkPolicy with a single Egress rule, which contains ports only, +// and no selectors. +var ( + anpOrder = float64(1000.0) + ports = []adminpolicy.AdminNetworkPolicyPort{{ + PortNumber: &adminpolicy.Port{ + Port: 80, + }, + }} + anp1 = adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Subject: adminpolicy.AdminNetworkPolicySubject{ + Namespaces: &metav1.LabelSelector{}, + }, + Priority: 1000, + Egress: []adminpolicy.AdminNetworkPolicyEgressRule{ + { + Action: "Allow", + To: []adminpolicy.AdminNetworkPolicyEgressPeer{ + { + Namespaces: &metav1.LabelSelector{}, + }, + }, + Ports: &ports, + }, + }, + }, + } +) + +// expected1 is the expected v1 KVPair representation of np1 from above. +var ( + expectedModel1 = []*model.KVPair{ + { + Key: model.PolicyKey{Tier: "adminnetworkpolicy", Name: "kanp.adminnetworkpolicy.test.policy"}, + Value: &model.Policy{ + Order: &anpOrder, + Selector: "(projectcalico.org/orchestrator == 'k8s') && has(projectcalico.org/namespace)", + Types: []string{"egress"}, + ApplyOnForward: false, + OutboundRules: []model.Rule{ + { + Action: "allow", + Protocol: &tcp, + SrcSelector: "", + DstSelector: "has(projectcalico.org/namespace)", + OriginalDstNamespaceSelector: "all()", + DstPorts: []numorstring.Port{port80}, + }, + }, + }, + }, + } +) + +// np2 is a NetworkPolicy with a single Ingress rule which allows from all namespaces. +var anp2 = adminpolicy.AdminNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test.policy", + UID: types.UID("30316465-6365-4463-ad63-3564622d3638"), + }, + Spec: adminpolicy.AdminNetworkPolicySpec{ + Subject: adminpolicy.AdminNetworkPolicySubject{ + Pods: &adminpolicy.NamespacedPod{ + PodSelector: metav1.LabelSelector{}, + }, + }, + Priority: 1000, + Ingress: []adminpolicy.AdminNetworkPolicyIngressRule{ + { + Action: "Allow", + From: []adminpolicy.AdminNetworkPolicyIngressPeer{ + { + Namespaces: &metav1.LabelSelector{}, + }, + }, + }, + }, + }, +} + +var expectedModel2 = []*model.KVPair{ + { + Key: model.PolicyKey{ + Name: "kanp.adminnetworkpolicy.test.policy", + Tier: "adminnetworkpolicy", + }, + Value: &model.Policy{ + Order: &anpOrder, + Selector: "(projectcalico.org/orchestrator == 'k8s') && has(projectcalico.org/namespace)", + Types: []string{"ingress"}, + ApplyOnForward: false, + InboundRules: []model.Rule{ + { + Action: "allow", + SrcSelector: "has(projectcalico.org/namespace)", + DstSelector: "", + OriginalSrcSelector: "", + OriginalSrcNamespaceSelector: "all()", + }, + }, + }, + }, +} + +var _ = Describe("Test the AdminNetworkPolicy update processor + conversion", func() { + up := updateprocessors.NewGlobalNetworkPolicyUpdateProcessor() + + DescribeTable("GlobalNetworkPolicy update processor + conversion tests", + func(anp adminpolicy.AdminNetworkPolicy, expected []*model.KVPair) { + // First, convert the NetworkPolicy using the k8s conversion logic. + c := conversion.NewConverter() + kvp, err := c.K8sAdminNetworkPolicyToCalico(&anp) + Expect(err).NotTo(HaveOccurred()) + + // Next, run the policy through the update processor. + out, err := up.Process(kvp) + Expect(err).NotTo(HaveOccurred()) + + // Finally, assert the expected result. + Expect(out).To(Equal(expected)) + }, + + Entry("should handle an AdminNetworkPolicy with no rule selectors", anp1, expectedModel1), + Entry("should handle an AdminNetworkPolicy with an empty ns selector", anp2, expectedModel2), + ) +}) diff --git a/libcalico-go/lib/backend/syncersv1/updateprocessors/networkpolicyprocessor_test.go b/libcalico-go/lib/backend/syncersv1/updateprocessors/networkpolicyprocessor_test.go index 048f5e4596f..5ecbaad8c1a 100644 --- a/libcalico-go/lib/backend/syncersv1/updateprocessors/networkpolicyprocessor_test.go +++ b/libcalico-go/lib/backend/syncersv1/updateprocessors/networkpolicyprocessor_test.go @@ -255,35 +255,6 @@ var expected2 = []*model.KVPair{ }, } -// np3 is a NetworkPolicy set to allow to a selection of security groups. -var np3 = networkingv1.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test.policy", - Namespace: "default", - Annotations: map[string]string{ - "rules.networkpolicy.tigera.io/match-security-groups": "true", - }, - }, - Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Egress: []networkingv1.NetworkPolicyEgressRule{ - { - To: []networkingv1.NetworkPolicyPeer{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "sg.aws.tigera.io/sg-12345": "", - "sg.aws.tigera.io/sg-other": "", - }, - }, - }, - }, - }, - }, - PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress}, - }, -} - var _ = Describe("Test the NetworkPolicy update processor + conversion", func() { up := updateprocessors.NewNetworkPolicyUpdateProcessor() diff --git a/libcalico-go/lib/clientv3/client.go b/libcalico-go/lib/clientv3/client.go index 8a42ee129d5..2f4d8e5b3e8 100644 --- a/libcalico-go/lib/clientv3/client.go +++ b/libcalico-go/lib/clientv3/client.go @@ -254,6 +254,11 @@ func (c client) EnsureInitialized(ctx context.Context, calicoVersion, clusterTyp errs = append(errs, err) } + if err := c.ensureAdminNetworkPolicyTierExists(ctx); err != nil { + log.WithError(err).Info("Unable to initialize adminnetworkpolicy Tier") + errs = append(errs, err) + } + // If there are any errors return the first error. We could combine the error text here and return // a generic error, but an application may be expecting a certain error code, so best just return // the original error. @@ -409,6 +414,25 @@ func (c client) ensureDefaultTierExists(ctx context.Context) error { return nil } +// ensureAdminNetworkPolicyTierExists ensures that the "adminnetworkpolicy" Tier exits in the datastore. +// This is done by trying to create the adminnetworkpolicy tier. If it doesn't exists, it +// is created. A error is returned if there is any error other than when the +// tier resource already exists. +func (c client) ensureAdminNetworkPolicyTierExists(ctx context.Context) error { + order := v3.AdminNetworkPolicyTierOrder + anpTier := v3.NewTier() + anpTier.ObjectMeta = metav1.ObjectMeta{Name: names.AdminNetworkPolicyTierName} + anpTier.Spec = v3.TierSpec{ + Order: &order, + } + if _, err := c.Tiers().Create(ctx, anpTier, options.SetOptions{}); err != nil { + if _, ok := err.(cerrors.ErrorResourceAlreadyExists); !ok { + return err + } + } + return nil +} + // Backend returns the backend client used by the v3 client. Not exposed on the main // client API, but available publicly for consumers that require access to the backend // client (e.g. for syncer support). diff --git a/libcalico-go/lib/clientv3/tier.go b/libcalico-go/lib/clientv3/tier.go index cf61600b5bb..0945945d80d 100644 --- a/libcalico-go/lib/clientv3/tier.go +++ b/libcalico-go/lib/clientv3/tier.go @@ -16,6 +16,7 @@ package clientv3 import ( "context" + "fmt" log "github.com/sirupsen/logrus" @@ -86,11 +87,11 @@ func (r tiers) Update(ctx context.Context, res *apiv3.Tier, opts options.SetOpti // Delete takes name of the Tier and deletes it. Returns an error if one occurs. func (r tiers) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.Tier, error) { - if name == names.DefaultTierName { + if name == names.DefaultTierName || name == names.AdminNetworkPolicyTierName { return nil, cerrors.ErrorOperationNotSupported{ - Identifier: names.DefaultTierName, + Identifier: name, Operation: "Delete", - Reason: "Cannot delete default tier", + Reason: fmt.Sprintf("Cannot delete %v tier", name), } } diff --git a/libcalico-go/lib/clientv3/tier_e2e_test.go b/libcalico-go/lib/clientv3/tier_e2e_test.go index 4d30bd0d8ff..c84dfc18208 100644 --- a/libcalico-go/lib/clientv3/tier_e2e_test.go +++ b/libcalico-go/lib/clientv3/tier_e2e_test.go @@ -28,6 +28,7 @@ import ( "github.com/projectcalico/calico/libcalico-go/lib/apiconfig" "github.com/projectcalico/calico/libcalico-go/lib/backend" "github.com/projectcalico/calico/libcalico-go/lib/clientv3" + "github.com/projectcalico/calico/libcalico-go/lib/names" "github.com/projectcalico/calico/libcalico-go/lib/options" "github.com/projectcalico/calico/libcalico-go/lib/testutils" "github.com/projectcalico/calico/libcalico-go/lib/watch" @@ -52,6 +53,10 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun defaultSpec := apiv3.TierSpec{ Order: &defaultOrder, } + anpOrder := apiv3.AdminNetworkPolicyTierOrder + anpSpec := apiv3.TierSpec{ + Order: &anpOrder, + } npName1 := name1 + ".networkp-1" npSpec1 := apiv3.NetworkPolicySpec{ @@ -159,6 +164,31 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun Expect(outError).To(HaveOccurred()) Expect(outError.Error()).Should(ContainSubstring("default tier order must be 1e+06")) + By("Creating the adminnetworkpolicy tier with an invalid order") + res, outError = c.Tiers().Create(ctx, &apiv3.Tier{ + ObjectMeta: metav1.ObjectMeta{Name: names.AdminNetworkPolicyTierName}, + Spec: spec1, + }, options.SetOptions{}) + Expect(res).To(BeNil()) + Expect(outError).To(HaveOccurred()) + Expect(outError.Error()).Should(ContainSubstring("adminnetworkpolicy tier order must be 1000")) + + By("Cannot delete the adminnetworkpolicy Tier") + _, outError = c.Tiers().Delete(ctx, names.AdminNetworkPolicyTierName, options.DeleteOptions{}) + Expect(outError).To(HaveOccurred()) + Expect(outError.Error()).To(Equal("operation Delete is not supported on adminnetworkpolicy: Cannot delete adminnetworkpolicy tier")) + + By("Getting adminnetworkpolicy Tier") + defRes, outError = c.Tiers().Get(ctx, names.AdminNetworkPolicyTierName, options.GetOptions{}) + Expect(outError).NotTo(HaveOccurred()) + Expect(defRes).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, names.AdminNetworkPolicyTierName, anpSpec)) + + By("Cannot update the adminnetworkpolicy Tier") + defRes.Spec = spec1 + _, outError = c.Tiers().Update(ctx, defRes, options.SetOptions{}) + Expect(outError).To(HaveOccurred()) + Expect(outError.Error()).Should(ContainSubstring("adminnetworkpolicy tier order must be 1000")) + By("Updating the Tier before it is created") res, outError = c.Tiers().Update(ctx, &apiv3.Tier{ ObjectMeta: metav1.ObjectMeta{Name: name1, ResourceVersion: "1234", CreationTimestamp: metav1.Now(), UID: uid}, @@ -220,9 +250,10 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun By("Listing all the Tiers, expecting a single result with name1/spec1") outList, outError := c.Tiers().List(ctx, options.ListOptions{}) Expect(outError).NotTo(HaveOccurred()) - Expect(outList.Items).To(HaveLen(2)) - Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) - Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) + Expect(outList.Items).To(HaveLen(3)) + Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, names.AdminNetworkPolicyTierName, anpSpec)) + Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) + Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) By("Creating a new Tier with name2/spec2") res2, outError := c.Tiers().Create(ctx, &apiv3.Tier{ @@ -241,10 +272,11 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun By("Listing all the Tiers, expecting a two results with name1/spec1 and name2/spec2") outList, outError = c.Tiers().List(ctx, options.ListOptions{}) Expect(outError).NotTo(HaveOccurred()) - Expect(outList.Items).To(HaveLen(3)) - Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) - Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) - Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name2, spec2UpdatedOrder)) + Expect(outList.Items).To(HaveLen(4)) + Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, names.AdminNetworkPolicyTierName, anpSpec)) + Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) + Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) + Expect(&outList.Items[3]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name2, spec2UpdatedOrder)) By("Updating Tier name1 with spec2") res1.Spec = spec2 @@ -287,17 +319,18 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun By("Listing Tiers with the original resource version and checking for a single result with name1/spec1") outList, outError = c.Tiers().List(ctx, options.ListOptions{ResourceVersion: rv1_1}) Expect(outError).NotTo(HaveOccurred()) - Expect(outList.Items).To(HaveLen(2)) - Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) + Expect(outList.Items).To(HaveLen(3)) + Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec1)) } By("Listing Tiers with the latest resource version and checking for two results with name1/spec2 and name2/spec2") outList, outError = c.Tiers().List(ctx, options.ListOptions{}) Expect(outError).NotTo(HaveOccurred()) - Expect(outList.Items).To(HaveLen(3)) - Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) - Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec2UpdatedOrder)) - Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name2, spec2UpdatedOrder)) + Expect(outList.Items).To(HaveLen(4)) + Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, names.AdminNetworkPolicyTierName, anpSpec)) + Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) + Expect(&outList.Items[2]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name1, spec2UpdatedOrder)) + Expect(&outList.Items[3]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, name2, spec2UpdatedOrder)) if config.Spec.DatastoreType != apiconfig.Kubernetes { By("Deleting Tier (name1) with the old resource version") @@ -401,11 +434,12 @@ var _ = testutils.E2eDatastoreDescribe("Tier tests", testutils.DatastoreAll, fun Expect(outError).To(HaveOccurred()) Expect(outError.Error()).To(ContainSubstring("resource does not exist: Tier(" + name2 + ") with error:")) - By("Listing all Tiers and expecting only the default tier") + By("Listing all Tiers and expecting only the default and adminnetworkpolicy tiers") outList, outError = c.Tiers().List(ctx, options.ListOptions{}) Expect(outError).NotTo(HaveOccurred()) - Expect(outList.Items).To(HaveLen(1)) - Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) + Expect(outList.Items).To(HaveLen(2)) + Expect(&outList.Items[0]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, names.AdminNetworkPolicyTierName, anpSpec)) + Expect(&outList.Items[1]).To(MatchResource(apiv3.KindTier, testutils.ExpectNoNamespace, defaultName, defaultSpec)) By("Getting Tier (name2) and expecting an error") res, outError = c.Tiers().Get(ctx, name2, options.GetOptions{}) diff --git a/libcalico-go/lib/errors/errors.go b/libcalico-go/lib/errors/errors.go index 5cfecf9d7d7..4072a9c7b25 100644 --- a/libcalico-go/lib/errors/errors.go +++ b/libcalico-go/lib/errors/errors.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Tigera, Inc. All rights reserved. +// Copyright (c) 2020-2024 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import ( networkingv1 "k8s.io/api/networking/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + adminpolicy "sigs.k8s.io/network-policy-api/apis/v1alpha1" ) // Error indicating a problem connecting to the backend. @@ -228,13 +229,68 @@ func (e ErrorParsingDatastoreEntry) Error() string { return fmt.Sprintf("failed to parse datastore entry key=%s; value=%s: %v", e.RawKey, e.RawValue, e.Err) } -type ErrorPolicyConversionRule struct { - EgressRule *networkingv1.NetworkPolicyEgressRule - IngressRule *networkingv1.NetworkPolicyIngressRule +type ErrorAdminPolicyConversion struct { + PolicyName string + Rules []ErrorAdminPolicyConversionRule +} + +func (e *ErrorAdminPolicyConversion) BadEgressRule(rule *adminpolicy.AdminNetworkPolicyEgressRule, reason string) { + // Copy rule + badRule := *rule + + e.Rules = append(e.Rules, ErrorAdminPolicyConversionRule{ + EgressRule: &badRule, + IngressRule: nil, + Reason: reason, + }) +} + +func (e *ErrorAdminPolicyConversion) BadIngressRule(rule *adminpolicy.AdminNetworkPolicyIngressRule, reason string) { + // Copy rule + badRule := *rule + + e.Rules = append(e.Rules, ErrorAdminPolicyConversionRule{ + EgressRule: nil, + IngressRule: &badRule, + Reason: reason, + }) +} + +func (e ErrorAdminPolicyConversion) Error() string { + s := fmt.Sprintf("policy: %s", e.PolicyName) + + switch { + case len(e.Rules) == 0: + s += ": unknown policy conversion error" + case len(e.Rules) == 1: + f := e.Rules[0] + + s += fmt.Sprintf(": error with rule %s", f) + default: + s += ": error with the following rules:\n" + for _, f := range e.Rules { + s += fmt.Sprintf("- %s\n", f) + } + } + + return s +} + +func (e ErrorAdminPolicyConversion) GetError() error { + if len(e.Rules) == 0 { + return nil + } + + return e +} + +type ErrorAdminPolicyConversionRule struct { + EgressRule *adminpolicy.AdminNetworkPolicyEgressRule + IngressRule *adminpolicy.AdminNetworkPolicyIngressRule Reason string } -func (e ErrorPolicyConversionRule) String() string { +func (e ErrorAdminPolicyConversionRule) String() string { var fieldString string switch { @@ -258,6 +314,31 @@ type ErrorPolicyConversion struct { Rules []ErrorPolicyConversionRule } +type ErrorPolicyConversionRule struct { + EgressRule *networkingv1.NetworkPolicyEgressRule + IngressRule *networkingv1.NetworkPolicyIngressRule + Reason string +} + +func (e ErrorPolicyConversionRule) String() string { + var fieldString string + + switch { + case e.EgressRule != nil: + fieldString = fmt.Sprintf("%+v", e.EgressRule) + case e.IngressRule != nil: + fieldString = fmt.Sprintf("%+v", e.IngressRule) + default: + fieldString = "unknown rule" + } + + if e.Reason != "" { + fieldString = fmt.Sprintf("%s (%s)", fieldString, e.Reason) + } + + return fieldString +} + func (e *ErrorPolicyConversion) BadEgressRule(rule *networkingv1.NetworkPolicyEgressRule, reason string) { // Copy rule badRule := *rule diff --git a/libcalico-go/lib/names/policy.go b/libcalico-go/lib/names/policy.go index 1cac49d36de..a7561dc03b7 100644 --- a/libcalico-go/lib/names/policy.go +++ b/libcalico-go/lib/names/policy.go @@ -22,8 +22,11 @@ import ( const ( DefaultTierName = "default" - K8sNetworkPolicyNamePrefix = "knp.default" - OssNetworkPolicyNamePrefix = "ossg." + AdminNetworkPolicyTierName = "adminnetworkpolicy" + + K8sNetworkPolicyNamePrefix = "knp.default." + K8sAdminNetworkPolicyNamePrefix = "kanp.adminnetworkpolicy." + OssNetworkPolicyNamePrefix = "ossg." ) // TierFromPolicyName extracts the tier from a tiered policy name. @@ -36,10 +39,13 @@ func TierFromPolicyName(name string) (string, error) { if name == "" { return "", errors.New("Tiered policy name is empty") } - // If it is a K8s network policy, then simply return the policy name as is. + // If it is a K8s (admin) network policy, then simply return the policy name as is. if strings.HasPrefix(name, K8sNetworkPolicyNamePrefix) { return DefaultTierName, nil } + if strings.HasPrefix(name, K8sAdminNetworkPolicyNamePrefix) { + return AdminNetworkPolicyTierName, nil + } parts := strings.SplitN(name, ".", 2) if len(parts) < 2 { // A name without a prefix. @@ -62,9 +68,7 @@ func validateBackendTieredPolicyName(policy, tier string) error { if policy == "" { return errors.New("Policy name is empty") } - // If it is a K8s network policy, then simply return the policy name as is. - // We expect K8s network policies to be formatted properly in the first place. - if strings.HasPrefix(policy, K8sNetworkPolicyNamePrefix) || strings.HasPrefix(policy, OssNetworkPolicyNamePrefix) { + if policyNameIsFormatted(policy) { return nil } @@ -80,8 +84,7 @@ func TieredPolicyName(policy string) string { if policy == "" { return "" } - // If it is a K8s network policy or OSSG, then simply return the policy name as is. - if strings.HasPrefix(policy, K8sNetworkPolicyNamePrefix) || strings.HasPrefix(policy, OssNetworkPolicyNamePrefix) { + if policyNameIsFormatted(policy) { return policy } @@ -103,8 +106,7 @@ func ClientTieredPolicyName(policy string) (string, error) { if policy == "" { return "", errors.New("Policy name is empty") } - // If it is a K8s network policy or OSSG, then simply return the policy name as is. - if strings.HasPrefix(policy, K8sNetworkPolicyNamePrefix) || strings.HasPrefix(policy, OssNetworkPolicyNamePrefix) { + if policyNameIsFormatted(policy) { return policy, nil } parts := strings.SplitN(policy, ".", 2) @@ -116,6 +118,12 @@ func ClientTieredPolicyName(policy string) (string, error) { return policy, nil } +func policyNameIsFormatted(policy string) bool { + // If it is a K8s (admin) network policy or OSSG, we expect the policy name to be formatted properly in the first place. + return strings.HasPrefix(policy, K8sNetworkPolicyNamePrefix) || strings.HasPrefix(policy, K8sAdminNetworkPolicyNamePrefix) || + strings.HasPrefix(policy, OssNetworkPolicyNamePrefix) +} + // TierOrDefault returns the tier name, or the default if blank. func TierOrDefault(tier string) string { if len(tier) == 0 { diff --git a/libcalico-go/lib/names/policy_test.go b/libcalico-go/lib/names/policy_test.go index b6599568422..277bb5dd859 100644 --- a/libcalico-go/lib/names/policy_test.go +++ b/libcalico-go/lib/names/policy_test.go @@ -33,6 +33,7 @@ var _ = DescribeTable("Parse Tiered policy name", }, Entry("Empty policy name", "", true, ""), Entry("K8s network policy", "knp.default.foopolicy", false, "default"), + Entry("K8s admin network policy", "kanp.adminnetworkpolicy.barpolicy", false, "adminnetworkpolicy"), Entry("Policy name without tier", "foopolicy", false, "default"), Entry("Correct tiered policy name", "baztier.foopolicy", false, "baztier"), ) @@ -52,6 +53,7 @@ var _ = DescribeTable("Backend Tiered policy name", Entry("Tier spec present with incorrectly formatted name", "bazpolicy", "footier", true, ""), Entry("Correcty formatted tiered policy name but not matching tier spec", "footier.bazpolicy", "baztier", true, ""), Entry("K8s Network Policy and empty tier", "knp.default.foobar", "", false, "knp.default.foobar"), + Entry("K8s Admin Network Policy and empty tier", "kanp.adminnetworkpolicy.foobar", "", false, "kanp.adminnetworkpolicy.foobar"), Entry("Network Policy and empty tier", "foobar", "", false, "default.foobar"), Entry("Matching tier spec and correctly formatted tiered policy name", "footier.bazpolicy", "footier", false, "footier.bazpolicy"), ) @@ -65,6 +67,8 @@ var _ = DescribeTable("Tiered policy name", Entry("Correctly formatted name", "footier.bazpolicy", "footier.bazpolicy"), Entry("Policy in default tier", "bazpolicy", "default.bazpolicy"), Entry("Policy in default tier with prefix", "default.bazpolicy", "default.bazpolicy"), + Entry("K8s network policy", "knp.default.bazpolicy", "knp.default.bazpolicy"), + Entry("K8s admin network policy", "kanp.adminnetworkpolicy.foopolicy", "kanp.adminnetworkpolicy.foopolicy"), ) var _ = DescribeTable("Client Tiered policy name", @@ -82,4 +86,5 @@ var _ = DescribeTable("Client Tiered policy name", Entry("Correctly formatted name", "footier.bazpolicy", false, "footier.bazpolicy"), Entry("Default tier", "default.bazpolicy", false, "bazpolicy"), Entry("K8s Network Policy", "knp.default.bazpolicy", false, "knp.default.bazpolicy"), + Entry("K8s Admin Network Policy", "kanp.adminnetworkpolicy.bazpolicy", false, "kanp.adminnetworkpolicy.bazpolicy"), ) diff --git a/libcalico-go/lib/validator/v3/validator.go b/libcalico-go/lib/validator/v3/validator.go index 5b0d301dbdc..95bad004a02 100644 --- a/libcalico-go/lib/validator/v3/validator.go +++ b/libcalico-go/lib/validator/v3/validator.go @@ -1567,6 +1567,18 @@ func validateTier(structLevel validator.StructLevel) { } } + if tier.Name == names.AdminNetworkPolicyTierName { + if tier.Spec.Order == nil || *tier.Spec.Order != api.AdminNetworkPolicyTierOrder { + structLevel.ReportError( + reflect.ValueOf(tier.Spec.Order), + "TierSpec.Order", + "", + reason(fmt.Sprintf("adminnetworkpolicy tier order must be %v", api.AdminNetworkPolicyTierOrder)), + "", + ) + } + } + validateObjectMetaAnnotations(structLevel, tier.Annotations) validateObjectMetaLabels(structLevel, tier.Labels) } diff --git a/libcalico-go/lib/validator/v3/validator_test.go b/libcalico-go/lib/validator/v3/validator_test.go index b41a68c4bf6..c2f399a5076 100644 --- a/libcalico-go/lib/validator/v3/validator_test.go +++ b/libcalico-go/lib/validator/v3/validator_test.go @@ -27,6 +27,7 @@ import ( libapiv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/projectcalico/calico/libcalico-go/lib/backend/encap" + "github.com/projectcalico/calico/libcalico-go/lib/names" v3 "github.com/projectcalico/calico/libcalico-go/lib/validator/v3" ) @@ -44,6 +45,7 @@ func init() { var V100000000 = 0x100000000 var tierOrder = float64(100.0) var defaultTierOrder = api.DefaultTierOrder + var anpTierOrder = api.AdminNetworkPolicyTierOrder var defaultTierBadOrder = float64(10.0) // We need pointers to bools, so define the values here. @@ -2397,15 +2399,25 @@ func init() { Order: &tierOrder, }}, false), Entry("Tier: disallow default tier with an invalid order", &api.Tier{ - ObjectMeta: v1.ObjectMeta{Name: "default"}, + ObjectMeta: v1.ObjectMeta{Name: names.DefaultTierName}, Spec: api.TierSpec{ Order: &defaultTierBadOrder, }}, false), Entry("Tier: allow default tier with the predefined order", &api.Tier{ - ObjectMeta: v1.ObjectMeta{Name: "default"}, + ObjectMeta: v1.ObjectMeta{Name: names.DefaultTierName}, Spec: api.TierSpec{ Order: &defaultTierOrder, }}, true), + Entry("Tier: disallow adminnetworkpolicy tier with an invalid order", &api.Tier{ + ObjectMeta: v1.ObjectMeta{Name: names.AdminNetworkPolicyTierName}, + Spec: api.TierSpec{ + Order: &defaultTierBadOrder, + }}, false), + Entry("Tier: allow adminnetworkpolicy tier with the predefined order", &api.Tier{ + ObjectMeta: v1.ObjectMeta{Name: names.AdminNetworkPolicyTierName}, + Spec: api.TierSpec{ + Order: &anpTierOrder, + }}, true), Entry("Tier: allow a tier with a valid order", &api.Tier{ ObjectMeta: v1.ObjectMeta{Name: "platform"}, Spec: api.TierSpec{ diff --git a/manifests/calico-bpf.yaml b/manifests/calico-bpf.yaml index 2a4e253e184..d618c135414 100644 --- a/manifests/calico-bpf.yaml +++ b/manifests/calico-bpf.yaml @@ -4614,6 +4614,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4761,6 +5729,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/calico-policy-only.yaml b/manifests/calico-policy-only.yaml index 9115a7a1842..d7c5df14da6 100644 --- a/manifests/calico-policy-only.yaml +++ b/manifests/calico-policy-only.yaml @@ -4624,6 +4624,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4771,6 +5739,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/calico-typha.yaml b/manifests/calico-typha.yaml index a349cf50941..1fddb6b9957 100644 --- a/manifests/calico-typha.yaml +++ b/manifests/calico-typha.yaml @@ -4625,6 +4625,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4772,6 +5740,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/calico-vxlan.yaml b/manifests/calico-vxlan.yaml index 59b0e2f341b..34694f39af5 100644 --- a/manifests/calico-vxlan.yaml +++ b/manifests/calico-vxlan.yaml @@ -4609,6 +4609,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4756,6 +5724,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/calico.yaml b/manifests/calico.yaml index a8641ba756e..7266496ef50 100644 --- a/manifests/calico.yaml +++ b/manifests/calico.yaml @@ -4609,6 +4609,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4756,6 +5724,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/canal.yaml b/manifests/canal.yaml index 55ff4e28d8a..8bb8cba8828 100644 --- a/manifests/canal.yaml +++ b/manifests/canal.yaml @@ -4626,6 +4626,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4774,6 +5742,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/crds.yaml b/manifests/crds.yaml index 541748c5ddb..4d8c3d526a8 100644 --- a/manifests/crds.yaml +++ b/manifests/crds.yaml @@ -4518,3 +4518,971 @@ status: plural: "" conditions: [] storedVersions: [] +--- +# Source: crds/policy.networking.k8s.io_adminnetworkpolicies.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/manifests/flannel-migration/calico.yaml b/manifests/flannel-migration/calico.yaml index c2fed495f0d..2dd872055b1 100644 --- a/manifests/flannel-migration/calico.yaml +++ b/manifests/flannel-migration/calico.yaml @@ -4609,6 +4609,974 @@ status: conditions: [] storedVersions: [] --- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- # Source: calico/templates/calico-kube-controllers-rbac.yaml # Include a clusterrole for the kube-controllers component, # and bind it to the calico-kube-controllers serviceaccount. @@ -4756,6 +5724,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/manifests/ocp/policy.networking.k8s.io_adminnetworkpolicies.yaml b/manifests/ocp/policy.networking.k8s.io_adminnetworkpolicies.yaml new file mode 100644 index 00000000000..1e3119f07c3 --- /dev/null +++ b/manifests/ocp/policy.networking.k8s.io_adminnetworkpolicies.yaml @@ -0,0 +1,967 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null + diff --git a/manifests/operator-crds.yaml b/manifests/operator-crds.yaml index 90afead586a..e23583c6f0d 100644 --- a/manifests/operator-crds.yaml +++ b/manifests/operator-crds.yaml @@ -21047,3 +21047,971 @@ status: plural: "" conditions: [] storedVersions: [] +--- +# Source: crds/policy.networking.k8s.io_adminnetworkpolicies.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/manifests/tigera-operator.yaml b/manifests/tigera-operator.yaml index 2063f517c5b..59bd5774ef7 100644 --- a/manifests/tigera-operator.yaml +++ b/manifests/tigera-operator.yaml @@ -4543,6 +4543,975 @@ status: conditions: [] storedVersions: [] +--- +# Source: crds/calico/policy.networking.k8s.io_adminnetworkpolicies.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: standard + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + 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. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null + --- # Source: crds/operator.tigera.io_apiservers_crd.yaml apiVersion: apiextensions.k8s.io/v1 diff --git a/node/tests/k8st/infra/calico-kdd.yaml b/node/tests/k8st/infra/calico-kdd.yaml index 68780c87db7..4f56e86ce69 100644 --- a/node/tests/k8st/infra/calico-kdd.yaml +++ b/node/tests/k8st/infra/calico-kdd.yaml @@ -237,6 +237,13 @@ rules: verbs: - watch - list + # Watch for changes to Kubernetes AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + verbs: + - watch + - list # Used by Calico for policy information. - apiGroups: [""] resources: diff --git a/node/tests/st/policy/test_tiered_policy.py b/node/tests/st/policy/test_tiered_policy.py index 3b063b9ae69..6844e821518 100644 --- a/node/tests/st/policy/test_tiered_policy.py +++ b/node/tests/st/policy/test_tiered_policy.py @@ -111,7 +111,7 @@ def delete_all(self, resource): objects['items'] = [x for x in objects['items'] if (x.get('kind', '') != 'Tier' or 'metadata' not in x or - x['metadata'].get('name', '') != 'default')] + x['metadata'].get('name', '') not in ['default', 'adminnetworkpolicy'])] if 'items' in objects and len(objects['items']) == 0: pass else: