From 1e7938ffc9ff22f924180532e028578b544c2f2b Mon Sep 17 00:00:00 2001 From: viktor-kurchenko Date: Wed, 21 Feb 2024 12:34:27 +0200 Subject: [PATCH] Connectivity test factory component. Signed-off-by: viktor-kurchenko --- connectivity/check/context.go | 41 +- connectivity/check/test.go | 19 + connectivity/factory/all_egress_deny.go | 34 + connectivity/factory/all_egress_deny_knp.go | 34 + connectivity/factory/all_entities_deny.go | 34 + connectivity/factory/all_ingress_deny.go | 35 + .../factory/all_ingress_deny_from_outside.go | 32 + connectivity/factory/all_ingress_deny_knp.go | 44 + .../factory/allow_all_except_world.go | 39 + .../factory/allow_all_with_metrics_check.go | 24 + connectivity/factory/check_log_errors.go | 26 + connectivity/factory/client_egress.go | 28 + .../factory/client_egress_expression.go | 28 + .../factory/client_egress_expression_knp.go | 28 + connectivity/factory/client_egress_knp.go | 28 + connectivity/factory/client_egress_l7.go | 45 + .../factory/client_egress_l7_method.go | 50 + .../factory/client_egress_l7_named_port.go | 45 + .../factory/client_egress_l7_set_header.go | 45 + ...ient_egress_l7_tls_deny_without_headers.go | 30 + .../factory/client_egress_l7_tls_headers.go | 29 + .../factory/client_egress_to_cidr_deny.go | 34 + .../client_egress_to_cidr_deny_default.go | 32 + .../factory/client_egress_to_echo_deny.go | 41 + .../client_egress_to_echo_expression_deny.go | 40 + .../client_egress_to_echo_service_account.go | 36 + ...ent_egress_to_echo_service_account_deny.go | 38 + connectivity/factory/client_ingress.go | 34 + ...ent_ingress_from_other_client_icmp_deny.go | 42 + connectivity/factory/client_ingress_icmp.go | 36 + connectivity/factory/client_ingress_knp.go | 34 + .../client_ingress_to_echo_named_port_deny.go | 39 + ...ent_with_service_account_egress_to_echo.go | 30 + ...ith_service_account_egress_to_echo_deny.go | 39 + connectivity/factory/cluster_entity.go | 28 + .../factory/cluster_entity_multi_cluster.go | 27 + connectivity/factory/dns_only.go | 29 + connectivity/factory/echo_ingress.go | 29 + .../factory/echo_ingress_auth_always_fail.go | 35 + .../echo_ingress_from_other_client_deny.go | 40 + .../factory/echo_ingress_from_outside.go | 33 + connectivity/factory/echo_ingress_knp.go | 36 + connectivity/factory/echo_ingress_l7.go | 46 + .../factory/echo_ingress_l7_named_port.go | 46 + .../echo_ingress_mutual_auth_spiffe.go | 30 + connectivity/factory/egress_gateway.go | 35 + .../factory/egress_gateway_excluded_cidrs.go | 35 + connectivity/factory/factory.go | 243 ++++ connectivity/factory/from_cidr_host_netns.go | 28 + connectivity/factory/health.go | 22 + connectivity/factory/host_entity_egress.go | 31 + connectivity/factory/host_entity_ingress.go | 28 + .../manifests/allow-all-egress.yaml | 0 .../manifests/allow-all-except-world.yaml | 0 .../manifests/allow-all-ingress.yaml | 0 .../manifests/allow-cluster-entity.yaml | 0 .../manifests/allow-host-entity-egress.yaml | 0 .../manifests/allow-host-entity-ingress.yaml | 0 .../manifests/allow-ingress-identity.yaml | 0 ...ent-egress-l7-http-matchheader-secret.yaml | 0 .../client-egress-l7-http-method.yaml | 0 .../client-egress-l7-http-named-port.yaml | 0 .../manifests/client-egress-l7-http.yaml | 0 .../manifests/client-egress-l7-tls.yaml | 0 .../manifests/client-egress-only-dns.yaml | 0 .../client-egress-to-cidr-cp-host-knp.yaml | 0 .../client-egress-to-cidr-external-deny.yaml | 0 .../client-egress-to-cidr-external-knp.yaml | 0 .../client-egress-to-cidr-external.yaml | 0 .../manifests/client-egress-to-cidr-k8s.yaml | 0 .../client-egress-to-cidr-node-knp.yaml | 0 .../manifests/client-egress-to-echo-deny.yaml | 0 ...client-egress-to-echo-expression-deny.yaml | 0 .../client-egress-to-echo-expression-knp.yaml | 0 .../client-egress-to-echo-expression.yaml | 0 .../manifests/client-egress-to-echo-knp.yaml | 0 ...client-egress-to-echo-named-port-deny.yaml | 0 ...t-egress-to-echo-service-account-deny.yaml | 0 ...client-egress-to-echo-service-account.yaml | 0 .../manifests/client-egress-to-echo.yaml | 0 .../client-egress-to-entities-host.yaml | 0 .../client-egress-to-entities-k8s.yaml | 0 .../client-egress-to-entities-world.yaml | 0 ...lient-egress-to-fqdns-one-one-one-one.yaml | 0 .../client-ingress-from-client2-knp.yaml | 0 .../client-ingress-from-client2.yaml | 0 ...h-service-account-egress-to-echo-deny.yaml | 0 ...t-with-service-account-egress-to-echo.yaml | 0 .../manifests/deny-all-egress-knp.yaml | 0 .../manifests/deny-all-egress.yaml | 0 .../manifests/deny-all-entities.yaml | 0 .../manifests/deny-all-ingress-knp.yaml | 0 .../manifests/deny-all-ingress.yaml | 0 .../{ => factory}/manifests/deny-cidr.yaml | 0 .../manifests/deny-ingress-backend.yaml | 0 .../manifests/deny-ingress-entity.yaml | 0 .../manifests/deny-world-entity.yaml | 0 .../manifests/echo-ingress-from-cidr.yaml | 0 .../echo-ingress-from-other-client-deny.yaml | 0 .../echo-ingress-from-other-client-knp.yaml | 0 .../echo-ingress-from-other-client.yaml | 0 .../manifests/echo-ingress-icmp-deny.yaml | 0 .../manifests/echo-ingress-icmp.yaml | 0 .../echo-ingress-l7-http-from-anywhere.yaml | 0 .../echo-ingress-l7-http-named-port.yaml | 0 .../manifests/echo-ingress-l7-http.yaml | 0 ...ho-ingress-mutual-authentication-fail.yaml | 0 .../echo-ingress-mutual-authentication.yaml | 0 .../manifests/template/template.go | 0 connectivity/factory/network_perf.go | 21 + .../factory/no_interrupted_connections.go | 21 + connectivity/factory/no_ipsec_xfrm_errors.go | 23 + connectivity/factory/no_policies.go | 29 + connectivity/factory/no_policies_extra.go | 23 + .../factory/no_policies_from_outside.go | 24 + .../factory/no_unexpected_packet_drops.go | 19 + .../factory/node_to_node_encryption.go | 29 + .../factory/north_south_loadbalancing.go | 23 + ...orth_south_loadbalancing_with_l7_policy.go | 35 + .../factory/outside_to_ingress_service.go | 23 + ...ide_to_ingress_service_deny_all_ingress.go | 28 + .../outside_to_ingress_service_deny_cidr.go | 28 + ..._to_ingress_service_deny_world_identity.go | 35 + .../factory/pod_to_controlplane_host.go | 29 + .../factory/pod_to_controlplane_host_cidr.go | 26 + .../factory/pod_to_ingress_service.go | 22 + ..._ingress_service_allow_ingress_identity.go | 30 + .../pod_to_ingress_service_deny_all.go | 25 + ...to_ingress_service_deny_backend_service.go | 32 + ...o_ingress_service_deny_ingress_identity.go | 32 + .../factory/pod_to_k8s_on_controlplane.go | 29 + .../pod_to_k8s_on_controlplane_cidr.go | 24 + .../factory/pod_to_node_cidrpolicy.go | 24 + connectivity/factory/pod_to_pod_encryption.go | 26 + connectivity/factory/to_cidr_external.go | 32 + connectivity/factory/to_cidr_external_knp.go | 32 + connectivity/factory/to_entities_world.go | 35 + connectivity/factory/to_fqdns.go | 59 + connectivity/suite.go | 1223 +---------------- 139 files changed, 2780 insertions(+), 1255 deletions(-) create mode 100644 connectivity/factory/all_egress_deny.go create mode 100644 connectivity/factory/all_egress_deny_knp.go create mode 100644 connectivity/factory/all_entities_deny.go create mode 100644 connectivity/factory/all_ingress_deny.go create mode 100644 connectivity/factory/all_ingress_deny_from_outside.go create mode 100644 connectivity/factory/all_ingress_deny_knp.go create mode 100644 connectivity/factory/allow_all_except_world.go create mode 100644 connectivity/factory/allow_all_with_metrics_check.go create mode 100644 connectivity/factory/check_log_errors.go create mode 100644 connectivity/factory/client_egress.go create mode 100644 connectivity/factory/client_egress_expression.go create mode 100644 connectivity/factory/client_egress_expression_knp.go create mode 100644 connectivity/factory/client_egress_knp.go create mode 100644 connectivity/factory/client_egress_l7.go create mode 100644 connectivity/factory/client_egress_l7_method.go create mode 100644 connectivity/factory/client_egress_l7_named_port.go create mode 100644 connectivity/factory/client_egress_l7_set_header.go create mode 100644 connectivity/factory/client_egress_l7_tls_deny_without_headers.go create mode 100644 connectivity/factory/client_egress_l7_tls_headers.go create mode 100644 connectivity/factory/client_egress_to_cidr_deny.go create mode 100644 connectivity/factory/client_egress_to_cidr_deny_default.go create mode 100644 connectivity/factory/client_egress_to_echo_deny.go create mode 100644 connectivity/factory/client_egress_to_echo_expression_deny.go create mode 100644 connectivity/factory/client_egress_to_echo_service_account.go create mode 100644 connectivity/factory/client_egress_to_echo_service_account_deny.go create mode 100644 connectivity/factory/client_ingress.go create mode 100644 connectivity/factory/client_ingress_from_other_client_icmp_deny.go create mode 100644 connectivity/factory/client_ingress_icmp.go create mode 100644 connectivity/factory/client_ingress_knp.go create mode 100644 connectivity/factory/client_ingress_to_echo_named_port_deny.go create mode 100644 connectivity/factory/client_with_service_account_egress_to_echo.go create mode 100644 connectivity/factory/client_with_service_account_egress_to_echo_deny.go create mode 100644 connectivity/factory/cluster_entity.go create mode 100644 connectivity/factory/cluster_entity_multi_cluster.go create mode 100644 connectivity/factory/dns_only.go create mode 100644 connectivity/factory/echo_ingress.go create mode 100644 connectivity/factory/echo_ingress_auth_always_fail.go create mode 100644 connectivity/factory/echo_ingress_from_other_client_deny.go create mode 100644 connectivity/factory/echo_ingress_from_outside.go create mode 100644 connectivity/factory/echo_ingress_knp.go create mode 100644 connectivity/factory/echo_ingress_l7.go create mode 100644 connectivity/factory/echo_ingress_l7_named_port.go create mode 100644 connectivity/factory/echo_ingress_mutual_auth_spiffe.go create mode 100644 connectivity/factory/egress_gateway.go create mode 100644 connectivity/factory/egress_gateway_excluded_cidrs.go create mode 100644 connectivity/factory/factory.go create mode 100644 connectivity/factory/from_cidr_host_netns.go create mode 100644 connectivity/factory/health.go create mode 100644 connectivity/factory/host_entity_egress.go create mode 100644 connectivity/factory/host_entity_ingress.go rename connectivity/{ => factory}/manifests/allow-all-egress.yaml (100%) rename connectivity/{ => factory}/manifests/allow-all-except-world.yaml (100%) rename connectivity/{ => factory}/manifests/allow-all-ingress.yaml (100%) rename connectivity/{ => factory}/manifests/allow-cluster-entity.yaml (100%) rename connectivity/{ => factory}/manifests/allow-host-entity-egress.yaml (100%) rename connectivity/{ => factory}/manifests/allow-host-entity-ingress.yaml (100%) rename connectivity/{ => factory}/manifests/allow-ingress-identity.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-l7-http-matchheader-secret.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-l7-http-method.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-l7-http-named-port.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-l7-http.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-l7-tls.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-only-dns.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-cp-host-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-external-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-external-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-external.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-k8s.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-cidr-node-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-expression-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-expression-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-expression.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-named-port-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-service-account-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo-service-account.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-echo.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-entities-host.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-entities-k8s.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-entities-world.yaml (100%) rename connectivity/{ => factory}/manifests/client-egress-to-fqdns-one-one-one-one.yaml (100%) rename connectivity/{ => factory}/manifests/client-ingress-from-client2-knp.yaml (100%) rename connectivity/{ => factory}/manifests/client-ingress-from-client2.yaml (100%) rename connectivity/{ => factory}/manifests/client-with-service-account-egress-to-echo-deny.yaml (100%) rename connectivity/{ => factory}/manifests/client-with-service-account-egress-to-echo.yaml (100%) rename connectivity/{ => factory}/manifests/deny-all-egress-knp.yaml (100%) rename connectivity/{ => factory}/manifests/deny-all-egress.yaml (100%) rename connectivity/{ => factory}/manifests/deny-all-entities.yaml (100%) rename connectivity/{ => factory}/manifests/deny-all-ingress-knp.yaml (100%) rename connectivity/{ => factory}/manifests/deny-all-ingress.yaml (100%) rename connectivity/{ => factory}/manifests/deny-cidr.yaml (100%) rename connectivity/{ => factory}/manifests/deny-ingress-backend.yaml (100%) rename connectivity/{ => factory}/manifests/deny-ingress-entity.yaml (100%) rename connectivity/{ => factory}/manifests/deny-world-entity.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-from-cidr.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-from-other-client-deny.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-from-other-client-knp.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-from-other-client.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-icmp-deny.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-icmp.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-l7-http-from-anywhere.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-l7-http-named-port.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-l7-http.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-mutual-authentication-fail.yaml (100%) rename connectivity/{ => factory}/manifests/echo-ingress-mutual-authentication.yaml (100%) rename connectivity/{ => factory}/manifests/template/template.go (100%) create mode 100644 connectivity/factory/network_perf.go create mode 100644 connectivity/factory/no_interrupted_connections.go create mode 100644 connectivity/factory/no_ipsec_xfrm_errors.go create mode 100644 connectivity/factory/no_policies.go create mode 100644 connectivity/factory/no_policies_extra.go create mode 100644 connectivity/factory/no_policies_from_outside.go create mode 100644 connectivity/factory/no_unexpected_packet_drops.go create mode 100644 connectivity/factory/node_to_node_encryption.go create mode 100644 connectivity/factory/north_south_loadbalancing.go create mode 100644 connectivity/factory/north_south_loadbalancing_with_l7_policy.go create mode 100644 connectivity/factory/outside_to_ingress_service.go create mode 100644 connectivity/factory/outside_to_ingress_service_deny_all_ingress.go create mode 100644 connectivity/factory/outside_to_ingress_service_deny_cidr.go create mode 100644 connectivity/factory/outside_to_ingress_service_deny_world_identity.go create mode 100644 connectivity/factory/pod_to_controlplane_host.go create mode 100644 connectivity/factory/pod_to_controlplane_host_cidr.go create mode 100644 connectivity/factory/pod_to_ingress_service.go create mode 100644 connectivity/factory/pod_to_ingress_service_allow_ingress_identity.go create mode 100644 connectivity/factory/pod_to_ingress_service_deny_all.go create mode 100644 connectivity/factory/pod_to_ingress_service_deny_backend_service.go create mode 100644 connectivity/factory/pod_to_ingress_service_deny_ingress_identity.go create mode 100644 connectivity/factory/pod_to_k8s_on_controlplane.go create mode 100644 connectivity/factory/pod_to_k8s_on_controlplane_cidr.go create mode 100644 connectivity/factory/pod_to_node_cidrpolicy.go create mode 100644 connectivity/factory/pod_to_pod_encryption.go create mode 100644 connectivity/factory/to_cidr_external.go create mode 100644 connectivity/factory/to_cidr_external_knp.go create mode 100644 connectivity/factory/to_entities_world.go create mode 100644 connectivity/factory/to_fqdns.go diff --git a/connectivity/check/context.go b/connectivity/check/context.go index 3be662bd4c..5bdbb534ce 100644 --- a/connectivity/check/context.go +++ b/connectivity/check/context.go @@ -4,7 +4,6 @@ package check import ( - "bytes" "context" "errors" "fmt" @@ -22,7 +21,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/cilium/cilium/api/v1/observer" @@ -231,41 +229,14 @@ func NewConnectivityTest(client *k8s.Client, p Parameters, version string) (*Con return k, nil } -// NewTest creates a new test scope within the ConnectivityTest and returns -// a new Test. This object can be used to set up the environment to execute -// different Scenarios within. -func (ct *ConnectivityTest) NewTest(name string) *Test { - var member struct{} - - if name == "" { - panic("empty test name") - } - - if _, ok := ct.testNames[name]; ok { - ct.Fatalf("test %s exists in suite", name) - } - - t := &Test{ - ctx: ct, - name: name, - scenarios: make(map[Scenario][]*Action), - cnps: make(map[string]*ciliumv2.CiliumNetworkPolicy), - knps: make(map[string]*networkingv1.NetworkPolicy), - cegps: make(map[string]*ciliumv2.CiliumEgressGatewayPolicy), - verbose: ct.verbose(), - logBuf: &bytes.Buffer{}, // maintain internal buffer by default - warnBuf: &bytes.Buffer{}, +// AddTest adds a new test scope within the ConnectivityTest. +func (ct *ConnectivityTest) AddTest(t *Test) *Test { + if _, ok := ct.testNames[t.name]; ok { + ct.Fatalf("test %s exists in suite", t.name) } - - // Setting the internal buffer to nil causes the logger to - // write directly to stdout in verbose or debug mode. - if ct.verbose() || ct.debug() { - t.logBuf = nil - } - + t.ctx = ct ct.tests = append(ct.tests, t) - ct.testNames[name] = member - + ct.testNames[t.name] = struct{}{} return t } diff --git a/connectivity/check/test.go b/connectivity/check/test.go index 115027baff..f7092f2dcd 100644 --- a/connectivity/check/test.go +++ b/connectivity/check/test.go @@ -57,6 +57,25 @@ var ( egressGatewayPolicyYAML string ) +func NewTest(name string, verbose bool, debug bool) *Test { + logBuf := &bytes.Buffer{} + // Setting the internal buffer to nil causes the logger to + // write directly to stdout in verbose or debug mode. + if verbose || debug { + logBuf = nil + } + return &Test{ + name: name, + scenarios: make(map[Scenario][]*Action), + cnps: make(map[string]*ciliumv2.CiliumNetworkPolicy), + knps: make(map[string]*networkingv1.NetworkPolicy), + cegps: make(map[string]*ciliumv2.CiliumEgressGatewayPolicy), + verbose: verbose, + logBuf: logBuf, // maintain internal buffer by default + warnBuf: &bytes.Buffer{}, + } +} + type Test struct { // Reference to the enclosing test suite for logging etc. ctx *ConnectivityTest diff --git a/connectivity/factory/all_egress_deny.go b/connectivity/factory/all_egress_deny.go new file mode 100644 index 0000000000..5e951a46e7 --- /dev/null +++ b/connectivity/factory/all_egress_deny.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/deny-all-egress.yaml + denyAllEgressPolicyYAML string + + allEgressDeny = factory{ + name: "all-egress-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies all egresses by default + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(denyAllEgressPolicyYAML). + WithScenarios( + tests.PodToPod(), + tests.PodToPodWithEndpoints(), + ). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/all_egress_deny_knp.go b/connectivity/factory/all_egress_deny_knp.go new file mode 100644 index 0000000000..d225b17449 --- /dev/null +++ b/connectivity/factory/all_egress_deny_knp.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/deny-all-egress-knp.yaml + denyAllEgressPolicyKNPYAML string + + allEgressDenyKnp = factory{ + name: "all-egress-deny-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies all egresses by default using KNP. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(denyAllEgressPolicyKNPYAML). + WithScenarios( + tests.PodToPod(), + tests.PodToPodWithEndpoints(), + ). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/all_entities_deny.go b/connectivity/factory/all_entities_deny.go new file mode 100644 index 0000000000..55b65414dd --- /dev/null +++ b/connectivity/factory/all_entities_deny.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/deny-all-entities.yaml + denyAllEntitiesPolicyYAML string + + allEntitiesDeny = factory{ + name: "all-entities-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies all entities by default + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(denyAllEntitiesPolicyYAML). + WithScenarios( + tests.PodToPod(), + tests.PodToCIDR(), + ). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/all_ingress_deny.go b/connectivity/factory/all_ingress_deny.go new file mode 100644 index 0000000000..105b4c954a --- /dev/null +++ b/connectivity/factory/all_ingress_deny.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var allIngressDeny = factory{ + name: "all-ingress-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies all ingresses by default. + // + // 1. Pod to Pod fails because there is no egress policy (so egress traffic originating from a pod is allowed), + // but then at the destination there is ingress policy that denies the traffic. + // 2. Egress to world works because there is no egress policy (so egress traffic originating from a pod is allowed), + // then when replies come back, they are considered as "replies" to the outbound connection. + // so they are not subject to ingress policy. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithScenarios(tests.PodToPod(), tests.PodToCIDR(tests.WithRetryAll())). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || + a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { + return check.ResultOK, check.ResultNone + } + return check.ResultDrop, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/all_ingress_deny_from_outside.go b/connectivity/factory/all_ingress_deny_from_outside.go new file mode 100644 index 0000000000..cd44bdc065 --- /dev/null +++ b/connectivity/factory/all_ingress_deny_from_outside.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var allIngressDenyFromOutside = factory{ + name: "all-ingress-deny-from-outside", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). + WithIPRoutesFromOutsideToPodCIDRs(). + WithScenarios(tests.FromCIDRToPod()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || + a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { + return check.ResultOK, check.ResultNone + } + return check.ResultDrop, check.ResultDefaultDenyIngressDrop + }) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeUnsafeTests }, +} diff --git a/connectivity/factory/all_ingress_deny_knp.go b/connectivity/factory/all_ingress_deny_knp.go new file mode 100644 index 0000000000..6119abb1c9 --- /dev/null +++ b/connectivity/factory/all_ingress_deny_knp.go @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/deny-all-ingress-knp.yaml + denyAllIngressPolicyKNPYAML string + + allIngressDenyKnp = factory{ + name: "all-ingress-deny-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies all ingresses by default + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(denyAllIngressPolicyKNPYAML). + WithScenarios( + // Pod to Pod fails because there is no egress policy (so egress traffic originating from a pod is allowed), + // but then at the destination there is ingress policy that denies the traffic. + tests.PodToPod(), + // Egress to world works because there is no egress policy (so egress traffic originating from a pod is allowed), + // then when replies come back, they are considered as "replies" to the outbound connection. + // so they are not subject to ingress policy. + tests.PodToCIDR(tests.WithRetryAll()), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || + a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { + return check.ResultOK, check.ResultNone + } + return check.ResultDrop, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/allow_all_except_world.go b/connectivity/factory/allow_all_except_world.go new file mode 100644 index 0000000000..9f5a89922b --- /dev/null +++ b/connectivity/factory/allow_all_except_world.go @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/allow-all-except-world.yaml + allowAllExceptWorldPolicyYAML string + + allowAllExceptWorld = factory{ + name: "allow-all-except-world", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test with an allow-all-except-world (and unmanaged) policy. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllExceptWorldPolicyYAML). + WithScenarios( + tests.PodToPod(), + tests.ClientToClient(), + tests.PodToService(), + // We are skipping the following checks because NodePort is + // intended to be used for N-S traffic, which conflicts with + // policies. See GH-17144. + // tests.PodToRemoteNodePort(), + // tests.PodToLocalNodePort(), + tests.PodToHost(), + tests.PodToExternalWorkload(), + ) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/allow_all_with_metrics_check.go b/connectivity/factory/allow_all_with_metrics_check.go new file mode 100644 index 0000000000..efe9ee61df --- /dev/null +++ b/connectivity/factory/allow_all_with_metrics_check.go @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var allowAllWithMetricsCheck = factory{ + name: "allow-all-with-metrics-check", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows traffic pod to pod and checks if the metric cilium_forward_count_total increases on cilium agent. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios(tests.PodToPod()). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK.ExpectMetricsIncrease(ct.CiliumAgentMetrics(), "cilium_forward_count_total"), + check.ResultOK.ExpectMetricsIncrease(ct.CiliumAgentMetrics(), "cilium_forward_count_total") + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/check_log_errors.go b/connectivity/factory/check_log_errors.go new file mode 100644 index 0000000000..ccac4a2a91 --- /dev/null +++ b/connectivity/factory/check_log_errors.go @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium/pkg/versioncheck" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var checkLogErrors = factory{ + name: "check-log-errors", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithSysdumpPolicy(check.SysdumpPolicyOnce). + WithScenarios(tests.NoErrorsInLogs(ct.CiliumVersion)) + }, + condition: func(version semver.Version, params check.Parameters) bool { + return versioncheck.MustCompile(">=1.14.0")(version) || params.IncludeUnsafeTests + }, +} diff --git a/connectivity/factory/client_egress.go b/connectivity/factory/client_egress.go new file mode 100644 index 0000000000..960238703c --- /dev/null +++ b/connectivity/factory/client_egress.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo.yaml + clientEgressToEchoPolicyYAML string + + clientEgress = factory{ + name: "client-egress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client to echo, so this should succeed + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEchoPolicyYAML). + WithScenarios(tests.PodToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_expression.go b/connectivity/factory/client_egress_expression.go new file mode 100644 index 0000000000..878d6c3a52 --- /dev/null +++ b/connectivity/factory/client_egress_expression.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-expression.yaml + clientEgressToEchoExpressionPolicyYAML string + + clientEgressExpression = factory{ + name: "client-egress-expression", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client to echo (using label match expression, so this should succeed + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEchoExpressionPolicyYAML). + WithScenarios(tests.PodToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_expression_knp.go b/connectivity/factory/client_egress_expression_knp.go new file mode 100644 index 0000000000..d37e3d93dc --- /dev/null +++ b/connectivity/factory/client_egress_expression_knp.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-expression-knp.yaml + clientEgressToEchoExpressionPolicyKNPYAML string + + clientEgressExpressionKnp = factory{ + name: "client-egress-expression-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client to echo (using label match expression, so this should succeed + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(clientEgressToEchoExpressionPolicyKNPYAML). + WithScenarios(tests.PodToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_knp.go b/connectivity/factory/client_egress_knp.go new file mode 100644 index 0000000000..78f38c64f5 --- /dev/null +++ b/connectivity/factory/client_egress_knp.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-knp.yaml + clientEgressToEchoPolicyKNPYAML string + + clientEgressKnp = factory{ + name: "client-egress-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client to echo, so this should succeed + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(clientEgressToEchoPolicyKNPYAML). + WithScenarios(tests.PodToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_l7.go b/connectivity/factory/client_egress_l7.go new file mode 100644 index 0000000000..b7e41af079 --- /dev/null +++ b/connectivity/factory/client_egress_l7.go @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressL7 = factory{ + name: "client-egress-l7", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Test L7 HTTP introspection using an egress policy on the clients. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only + WithCiliumPolicy(templates["clientEgressL7HTTPPolicyYAML"]). // L7 allow policy with HTTP introspection + WithScenarios( + tests.PodToPod(), + tests.PodToWorld(tests.WithRetryDestPort(80), tests.WithRetryPodLabel("other", "client")), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. + // Outbound HTTP to set domain-name defaults to one.one.one.one is L7-introspected and allowed. + (a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(ct.Params().ExternalTarget)) == ct.Params().ExternalTarget || + a.Destination().Port() == 8080) { // 8080 is traffic to echo Pod. + if a.Destination().Path() == "/" || a.Destination().Path() == "" { + egress = check.ResultOK + // Expect all curls from client2 to be proxied and to be GET calls. + egress.HTTP = check.HTTP{ + Method: "GET", + } + return egress, check.ResultNone + } + // Else expect HTTP drop by proxy + return check.ResultDNSOKDropCurlHTTPError, check.ResultNone + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_l7_method.go b/connectivity/factory/client_egress_l7_method.go new file mode 100644 index 0000000000..e99dd7dfe2 --- /dev/null +++ b/connectivity/factory/client_egress_l7_method.go @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/client-egress-l7-http-method.yaml + clientEgressL7HTTPMethodPolicyYAML string + + clientEgressL7Method = factory{ + name: "client-egress-l7-method", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test L7 HTTP with different methods introspection using an egress policy on the clients. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only + WithCiliumPolicy(clientEgressL7HTTPMethodPolicyYAML). // L7 allow policy with HTTP introspection (POST only) + WithScenarios( + tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithDestinationLabelsOption(map[string]string{"other": "echo"})), + tests.PodToPodWithEndpoints(tests.WithDestinationLabelsOption(map[string]string{"first": "echo"})), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. + (a.Destination().Port() == 8080) { // port 8080 is traffic to echo Pod. + if a.Destination().HasLabel("other", "echo") { //we are POSTing only other echo + egress = check.ResultOK + + egress.HTTP = check.HTTP{ + Method: "POST", + } + return egress, check.ResultNone + } + // Else expect HTTP drop by proxy + return check.ResultDropCurlHTTPError, check.ResultNone + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_l7_named_port.go b/connectivity/factory/client_egress_l7_named_port.go new file mode 100644 index 0000000000..a5c4329746 --- /dev/null +++ b/connectivity/factory/client_egress_l7_named_port.go @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressL7NamedPort = factory{ + name: "client-egress-l7-named-port", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Test L7 HTTP named port introspection using an egress policy on the clients. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only + WithCiliumPolicy(templates["clientEgressL7HTTPNamedPortPolicyYAML"]). // L7 allow policy with HTTP introspection (named port) + WithScenarios( + tests.PodToPod(), + tests.PodToWorld(tests.WithRetryDestPort(80), tests.WithRetryPodLabel("other", "client")), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. + // Outbound HTTP to domain-name, default one.one.one.one, is L7-introspected and allowed. + (a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(ct.Params().ExternalTarget)) == ct.Params().ExternalTarget || + a.Destination().Port() == 8080) { // named port http-8080 is traffic to echo Pod. + if a.Destination().Path() == "/" || a.Destination().Path() == "" { + egress = check.ResultOK + // Expect all curls from client2 to be proxied and to be GET calls. + egress.HTTP = check.HTTP{ + Method: "GET", + } + return egress, check.ResultNone + } + // Else expect HTTP drop by proxy + return check.ResultDNSOKDropCurlHTTPError, check.ResultNone + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_l7_set_header.go b/connectivity/factory/client_egress_l7_set_header.go new file mode 100644 index 0000000000..e84ade42c6 --- /dev/null +++ b/connectivity/factory/client_egress_l7_set_header.go @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressL7SetHeader = factory{ + name: "client-egress-l7-set-header", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Test L7 HTTP with a header replace set in the policy + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). + WithSecret(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "header-match", + }, + Data: map[string][]byte{ + "value": []byte("Bearer 123456"), + }, + }). + WithCiliumPolicy(templates["clientEgressL7HTTPMatchheaderSecretYAML"]). // L7 allow policy with HTTP introspection (POST only) + WithScenarios( + tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"other": "echo"})), + tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"first": "echo"})), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && // Only client2 has the header policy. + (a.Destination().Port() == 8080) { // port 8080 is traffic to echo Pod. + return check.ResultOK, check.ResultNone + } + return check.ResultCurlHTTPError, check.ResultNone // if the header is not set the request will get a 401 + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_l7_tls_deny_without_headers.go b/connectivity/factory/client_egress_l7_tls_deny_without_headers.go new file mode 100644 index 0000000000..b95e3e55ab --- /dev/null +++ b/connectivity/factory/client_egress_l7_tls_deny_without_headers.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressL7TlsDenyWithoutHeaders = factory{ + name: "client-egress-l7-tls-deny-without-headers", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Test L7 HTTPS interception using an egress policy on the clients. + // Fail to load site due to missing headers. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). + WithCABundleSecret(). + WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). + WithCiliumPolicy(templates["clientEgressL7TLSPolicyYAML"]). // L7 allow policy with TLS interception + WithScenarios(tests.PodToWorldWithTLSIntercept()). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultDropCurlHTTPError, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_l7_tls_headers.go b/connectivity/factory/client_egress_l7_tls_headers.go new file mode 100644 index 0000000000..fe1267bf72 --- /dev/null +++ b/connectivity/factory/client_egress_l7_tls_headers.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressL7TlsHeaders = factory{ + name: "client-egress-l7-tls-headers", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Test L7 HTTPS interception using an egress policy on the clients. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). + WithCABundleSecret(). + WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). + WithCiliumPolicy(templates["clientEgressL7TLSPolicyYAML"]). // L7 allow policy with TLS interception + WithScenarios(tests.PodToWorldWithTLSIntercept("-H", "X-Very-Secret-Token: 42")). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_to_cidr_deny.go b/connectivity/factory/client_egress_to_cidr_deny.go new file mode 100644 index 0000000000..67f21ece92 --- /dev/null +++ b/connectivity/factory/client_egress_to_cidr_deny.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressToCidrDeny = factory{ + name: "client-egress-to-cidr-deny", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // This policy denies L3 traffic to ExternalCIDR except ExternalIP/32 + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(templates["clientEgressToCIDRExternalDenyPolicyYAML"]). + WithScenarios( + tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), // Denies all traffic to ExternalOtherIP, but allow ExternalIP + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { + return check.ResultOK, check.ResultNone + } + return check.ResultDrop, check.ResultDrop + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_to_cidr_deny_default.go b/connectivity/factory/client_egress_to_cidr_deny_default.go new file mode 100644 index 0000000000..8946673b1b --- /dev/null +++ b/connectivity/factory/client_egress_to_cidr_deny_default.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var clientEgressToCidrDenyDefault = factory{ + name: "client-egress-to-cidr-deny-default", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // This test is same as the previous one, but there is no allowed policy. + // The goal is to test default deny policy + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(templates["clientEgressToCIDRExternalDenyPolicyYAML"]). + WithScenarios(tests.PodToCIDR()). // Denies all traffic to ExternalOtherIP, but allow ExternalIP + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + } + return check.ResultDrop, check.ResultDrop + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/client_egress_to_echo_deny.go b/connectivity/factory/client_egress_to_echo_deny.go new file mode 100644 index 0000000000..7f7612242f --- /dev/null +++ b/connectivity/factory/client_egress_to_echo_deny.go @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-deny.yaml + clientEgressToEchoDenyPolicyYAML string + + clientEgressToEchoDeny = factory{ + name: "client-egress-to-echo-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies port 8080 from client to echo + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(clientEgressToEchoDenyPolicyYAML). // Deny client to echo traffic via port 8080 + WithScenarios( + tests.ClientToClient(), // Client to client traffic should be allowed + tests.PodToPod(), // Client to echo traffic should be denied + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("kind", "client") && + a.Destination().HasLabel("kind", "echo") && + a.Destination().Port() == 8080 { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_to_echo_expression_deny.go b/connectivity/factory/client_egress_to_echo_expression_deny.go new file mode 100644 index 0000000000..f12f38de6b --- /dev/null +++ b/connectivity/factory/client_egress_to_echo_expression_deny.go @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-expression-deny.yaml + clientEgressToEchoExpressionDenyPolicyYAML string + + clientEgressToEchoExpressionDeny = factory{ + name: "client-egress-to-echo-expression-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies port 8080 from client to echo (using label match expression), but allows traffic from client2 + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(clientEgressToEchoExpressionDenyPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be denied + tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be allowed + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && + a.Source().HasLabel("name", "client") { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_to_echo_service_account.go b/connectivity/factory/client_egress_to_echo_service_account.go new file mode 100644 index 0000000000..5182616de1 --- /dev/null +++ b/connectivity/factory/client_egress_to_echo_service_account.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-service-account.yaml + clientEgressToEchoServiceAccountPolicyYAML string + + clientEgressToEchoServiceAccount = factory{ + name: "client-egress-to-echo-service-account", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client to endpoint with service account label as echo-same-node + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEchoServiceAccountPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"kind": "client"})), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("name", "echo-same-node") { + return check.ResultOK, check.ResultOK + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_egress_to_echo_service_account_deny.go b/connectivity/factory/client_egress_to_echo_service_account_deny.go new file mode 100644 index 0000000000..07ce0d16b8 --- /dev/null +++ b/connectivity/factory/client_egress_to_echo_service_account_deny.go @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-service-account-deny.yaml + clientEgressToEchoServiceAccountDenyPolicyYAML string + + clientEgressToEchoServiceAccountDeny = factory{ + name: "client-egress-to-echo-service-account-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies port 8080 from client to endpoint with service account, but not from client2 + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(clientEgressToEchoServiceAccountDenyPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client"})), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("name", "echo-same-node") { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_ingress.go b/connectivity/factory/client_ingress.go new file mode 100644 index 0000000000..38d9f5526b --- /dev/null +++ b/connectivity/factory/client_ingress.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-ingress-from-client2.yaml + clientIngressFromClient2PolicyYAML string + + clientIngress = factory{ + name: "client-ingress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy only allows ingress into client from client2. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientIngressFromClient2PolicyYAML). + WithScenarios(tests.ClientToClient()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") { + return check.ResultOK, check.ResultOK + } + return check.ResultOK, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_ingress_from_other_client_icmp_deny.go b/connectivity/factory/client_ingress_from_other_client_icmp_deny.go new file mode 100644 index 0000000000..1f90f1ee6a --- /dev/null +++ b/connectivity/factory/client_ingress_from_other_client_icmp_deny.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-icmp-deny.yaml + echoIngressICMPDenyPolicyYAML string + + clientIngressFromOtherClientIcmpDeny = factory{ + name: "client-ingress-from-other-client-icmp-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies ICMP ingress to client only from other client + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(echoIngressICMPDenyPolicyYAML). // Deny ICMP traffic from client to another client + WithFeatureRequirements(features.RequireEnabled(features.ICMPPolicy)). + WithScenarios( + tests.PodToPod(), // Client to echo traffic should be allowed + tests.ClientToClient(), // Client to client traffic should be denied + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && + a.Destination().HasLabel("kind", "client") { + return check.ResultDrop, check.ResultPolicyDenyIngressDrop + } + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_ingress_icmp.go b/connectivity/factory/client_ingress_icmp.go new file mode 100644 index 0000000000..ffb037b2da --- /dev/null +++ b/connectivity/factory/client_ingress_icmp.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-icmp.yaml + echoIngressICMPPolicyYAML string + + clientIngressIcmp = factory{ + name: "client-ingress-icmp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allowed ICMP traffic from client to another client. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(echoIngressICMPPolicyYAML). + WithFeatureRequirements(features.RequireEnabled(features.ICMPPolicy)). + WithScenarios(tests.ClientToClient()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") { + return check.ResultOK, check.ResultOK + } + return check.ResultOK, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_ingress_knp.go b/connectivity/factory/client_ingress_knp.go new file mode 100644 index 0000000000..e21c21616f --- /dev/null +++ b/connectivity/factory/client_ingress_knp.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-ingress-from-client2-knp.yaml + clientIngressFromClient2PolicyKNPYAML string + + clientIngressKnp = factory{ + name: "client-ingress-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Run a simple test with k8s Network Policy. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(clientIngressFromClient2PolicyKNPYAML). + WithScenarios(tests.ClientToClient()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") { + return check.ResultOK, check.ResultOK + } + return check.ResultOK, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_ingress_to_echo_named_port_deny.go b/connectivity/factory/client_ingress_to_echo_named_port_deny.go new file mode 100644 index 0000000000..00096bef06 --- /dev/null +++ b/connectivity/factory/client_ingress_to_echo_named_port_deny.go @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-echo-named-port-deny.yaml + clientEgressToEchoDenyNamedPortPolicyYAML string + + clientIngressToEchoNamedPortDeny = factory{ + name: "client-ingress-to-echo-named-port-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies port http-8080 from client to echo, but allows traffic from client2 to echo + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(clientEgressToEchoDenyNamedPortPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be denied + tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be allowed + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && a.Source().HasLabel("name", "client") { + return check.ResultDropCurlTimeout, check.ResultPolicyDenyIngressDrop + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_with_service_account_egress_to_echo.go b/connectivity/factory/client_with_service_account_egress_to_echo.go new file mode 100644 index 0000000000..60f992f2ea --- /dev/null +++ b/connectivity/factory/client_with_service_account_egress_to_echo.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-with-service-account-egress-to-echo.yaml + clientWithServiceAccountEgressToEchoPolicyYAML string + + clientWithServiceAccountEgressToEcho = factory{ + name: "client-with-service-account-egress-to-echo", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows port 8080 from client with service account label to echo + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientWithServiceAccountEgressToEchoPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"kind": "client"})), + ) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/client_with_service_account_egress_to_echo_deny.go b/connectivity/factory/client_with_service_account_egress_to_echo_deny.go new file mode 100644 index 0000000000..664641923e --- /dev/null +++ b/connectivity/factory/client_with_service_account_egress_to_echo_deny.go @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-with-service-account-egress-to-echo-deny.yaml + clientWithServiceAccountEgressToEchoDenyPolicyYAML string + + clientWithServiceAccountEgressToEchoDeny = factory{ + name: "client-with-service-account-egress-to-echo-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy denies port 8080 from client with service account selector to echo, but not from client2 + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(clientWithServiceAccountEgressToEchoDenyPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client"})), // Client to echo should be denied + tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client2"})), // Client2 to echo should be allowed + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && a.Source().HasLabel("name", "client") { + return check.ResultPolicyDenyEgressDrop, check.ResultNone + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/cluster_entity.go b/connectivity/factory/cluster_entity.go new file mode 100644 index 0000000000..435df4fc80 --- /dev/null +++ b/connectivity/factory/cluster_entity.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var clusterEntity = factory{ + name: "cluster-entity", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows cluster entity + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowClusterEntityPolicyYAML). + WithScenarios( + // Only enable to local cluster for now due to the below + // https://github.com/cilium/cilium/blob/88c4dddede2a3b5b9a7339c1316a0dedd7229a26/pkg/policy/api/entity.go#L126 + tests.PodToPod(tests.WithDestinationLabelsOption(map[string]string{"name": "echo-same-node"})), + ). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/cluster_entity_multi_cluster.go b/connectivity/factory/cluster_entity_multi_cluster.go new file mode 100644 index 0000000000..e092f5323e --- /dev/null +++ b/connectivity/factory/cluster_entity_multi_cluster.go @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var clusterEntityMultiCluster = factory{ + name: "cluster-entity-multi-cluster", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowClusterEntityPolicyYAML). + WithScenarios( + tests.PodToPod(tests.WithDestinationLabelsOption(map[string]string{"name": "echo-other-node"})), + ). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.MultiCluster != "" }, +} diff --git a/connectivity/factory/dns_only.go b/connectivity/factory/dns_only.go new file mode 100644 index 0000000000..bad5a418a0 --- /dev/null +++ b/connectivity/factory/dns_only.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var dnsOnly = factory{ + name: "dns-only", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Only allow UDP:53 to kube-dns, no DNS proxy enabled. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithScenarios( + tests.PodToPod(), // connects to other Pods directly, no DNS + tests.PodToWorld(), // resolves set domain-name defaults to one.one.one.one + ). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDropCurlTimeout, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/echo_ingress.go b/connectivity/factory/echo_ingress.go new file mode 100644 index 0000000000..5bdbe24754 --- /dev/null +++ b/connectivity/factory/echo_ingress.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var echoIngress = factory{ + name: "echo-ingress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows ingress to echo only from client with a label 'other:client'. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(echoIngressFromOtherClientPolicyYAML). + WithScenarios(tests.PodToPod()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { + // TCP handshake fails both in egress and ingress when + // L3(/L4) policy drops at either location. + return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/echo_ingress_auth_always_fail.go b/connectivity/factory/echo_ingress_auth_always_fail.go new file mode 100644 index 0000000000..20390ccb5a --- /dev/null +++ b/connectivity/factory/echo_ingress_auth_always_fail.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-mutual-authentication-fail.yaml + echoIngressAuthFailPolicyYAML string + + echoIngressAuthAlwaysFail = factory{ + name: "echo-ingress-auth-always-fail", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test mutual auth with always-fail + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(echoIngressAuthFailPolicyYAML). + // this test is only useful when auth is supported in the Cilium version and it is enabled + // currently this is tested spiffe as that is the only functional auth method + WithFeatureRequirements(features.RequireEnabled(features.AuthSpiffe)). + WithScenarios(tests.PodToPod()). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultDropCurlTimeout, check.ResultDropAuthRequired + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/echo_ingress_from_other_client_deny.go b/connectivity/factory/echo_ingress_from_other_client_deny.go new file mode 100644 index 0000000000..d2da2c78db --- /dev/null +++ b/connectivity/factory/echo_ingress_from_other_client_deny.go @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/echo-ingress-from-other-client-deny.yaml + echoIngressFromOtherClientDenyPolicyYAML string + + echoIngressFromOtherClientDeny = factory{ + name: "echo-ingress-from-other-client-deny", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Tests with deny policy + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic + WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic + WithCiliumPolicy(echoIngressFromOtherClientDenyPolicyYAML). // Deny other client contact echo + WithScenarios( + tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be allowed + tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be denied + tests.ClientToClient(), // Client to client should be allowed + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") && a.Destination().HasLabel("kind", "echo") { + return check.ResultDrop, check.ResultPolicyDenyIngressDrop + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/echo_ingress_from_outside.go b/connectivity/factory/echo_ingress_from_outside.go new file mode 100644 index 0000000000..aa930d3e04 --- /dev/null +++ b/connectivity/factory/echo_ingress_from_outside.go @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var echoIngressFromOutside = factory{ + name: "echo-ingress-from-outside", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(echoIngressFromOtherClientPolicyYAML). + WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). + WithIPRoutesFromOutsideToPodCIDRs(). + WithScenarios(tests.FromCIDRToPod()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { + // TCP handshake fails both in egress and ingress when + // L3(/L4) policy drops at either location. + return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout + } + return check.ResultOK, check.ResultOK + }) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeUnsafeTests }, +} diff --git a/connectivity/factory/echo_ingress_knp.go b/connectivity/factory/echo_ingress_knp.go new file mode 100644 index 0000000000..724409d934 --- /dev/null +++ b/connectivity/factory/echo_ingress_knp.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/echo-ingress-from-other-client-knp.yaml + echoIngressFromOtherClientPolicyKNPYAML string + + echoIngressKnp = factory{ + name: "echo-ingress-knp", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This k8s policy allows ingress to echo only from client with a label 'other:client'. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(echoIngressFromOtherClientPolicyKNPYAML). + WithScenarios(tests.PodToPod()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { + // TCP handshake fails both in egress and ingress when + // L3(/L4) policy drops at either location. + return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout + } + return check.ResultOK, check.ResultOK + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/echo_ingress_l7.go b/connectivity/factory/echo_ingress_l7.go new file mode 100644 index 0000000000..4db739673a --- /dev/null +++ b/connectivity/factory/echo_ingress_l7.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-l7-http.yaml + echoIngressL7HTTPPolicyYAML string + + echoIngressL7 = factory{ + name: "echo-ingress-l7", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test L7 HTTP introspection using an ingress policy on echo pods. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(echoIngressL7HTTPPolicyYAML). // L7 allow policy with HTTP introspection + WithScenarios(tests.PodToPodWithEndpoints()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") { // Only client2 is allowed to make HTTP calls. + // Trying to access private endpoint without "secret" header set + // should lead to a drop. + if a.Destination().Path() == "/private" && !a.Destination().HasLabel("X-Very-Secret-Token", "42") { + return check.ResultDropCurlHTTPError, check.ResultNone + } + egress = check.ResultOK + // Expect all curls from client2 to be proxied and to be GET calls. + egress.HTTP = check.HTTP{ + Method: "GET", + } + return egress, check.ResultNone + } + return check.ResultDrop, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/echo_ingress_l7_named_port.go b/connectivity/factory/echo_ingress_l7_named_port.go new file mode 100644 index 0000000000..2fbe108046 --- /dev/null +++ b/connectivity/factory/echo_ingress_l7_named_port.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-l7-http-named-port.yaml + echoIngressL7HTTPNamedPortPolicyYAML string + + echoIngressL7NamedPort = factory{ + name: "echo-ingress-l7-named-port", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test L7 HTTP introspection using an ingress policy on echo pods. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(echoIngressL7HTTPNamedPortPolicyYAML). // L7 allow policy with HTTP introspection (named port) + WithScenarios(tests.PodToPodWithEndpoints()). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Source().HasLabel("other", "client") { // Only client2 is allowed to make HTTP calls. + // Trying to access private endpoint without "secret" header set + // should lead to a drop. + if a.Destination().Path() == "/private" && !a.Destination().HasLabel("X-Very-Secret-Token", "42") { + return check.ResultDropCurlHTTPError, check.ResultNone + } + egress = check.ResultOK + // Expect all curls from client2 to be proxied and to be GET calls. + egress.HTTP = check.HTTP{ + Method: "GET", + } + return egress, check.ResultNone + } + return check.ResultDrop, check.ResultDefaultDenyIngressDrop + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/echo_ingress_mutual_auth_spiffe.go b/connectivity/factory/echo_ingress_mutual_auth_spiffe.go new file mode 100644 index 0000000000..5958c80581 --- /dev/null +++ b/connectivity/factory/echo_ingress_mutual_auth_spiffe.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-mutual-authentication.yaml + echoIngressMutualAuthPolicyYAML string + + echoIngressMutualAuthSpiffe = factory{ + name: "echo-ingress-mutual-auth-spiffe", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test mutual auth with SPIFFE + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(echoIngressMutualAuthPolicyYAML). + WithFeatureRequirements(features.RequireEnabled(features.AuthSpiffe)). + WithScenarios(tests.PodToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/egress_gateway.go b/connectivity/factory/egress_gateway.go new file mode 100644 index 0000000000..5766cfefea --- /dev/null +++ b/connectivity/factory/egress_gateway.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var egressGateway = factory{ + name: "egress-gateway", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ + Name: "cegp-sample-client", + PodSelectorKind: "client", + }). + WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ + Name: "cegp-sample-echo", + PodSelectorKind: "echo", + }). + WithIPRoutesFromOutsideToPodCIDRs(). + WithFeatureRequirements( + features.RequireEnabled(features.EgressGateway), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithScenarios(tests.EgressGateway()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeUnsafeTests }, +} diff --git a/connectivity/factory/egress_gateway_excluded_cidrs.go b/connectivity/factory/egress_gateway_excluded_cidrs.go new file mode 100644 index 0000000000..89d10353b4 --- /dev/null +++ b/connectivity/factory/egress_gateway_excluded_cidrs.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium/pkg/versioncheck" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var egressGatewayExcludedCidrs = factory{ + name: "egress-gateway-excluded-cidrs", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ + Name: "cegp-sample-client", + PodSelectorKind: "client", + ExcludedCIDRsConf: check.ExternalNodeExcludedCIDRs, + }). + WithFeatureRequirements( + features.RequireEnabled(features.EgressGateway), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithScenarios(tests.EgressGatewayExcludedCIDRs()) + }, + condition: func(version semver.Version, params check.Parameters) bool { + return versioncheck.MustCompile(">=1.14.0")(version) + }, +} diff --git a/connectivity/factory/factory.go b/connectivity/factory/factory.go new file mode 100644 index 0000000000..2b1aa11004 --- /dev/null +++ b/connectivity/factory/factory.go @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/factory/manifests/template" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/allow-all-egress.yaml + allowAllEgressPolicyYAML string + + //go:embed manifests/allow-all-ingress.yaml + allowAllIngressPolicyYAML string + + //go:embed manifests/deny-all-ingress.yaml + denyAllIngressPolicyYAML string + + //go:embed manifests/deny-cidr.yaml + denyCIDRPolicyYAML string + + //go:embed manifests/allow-cluster-entity.yaml + allowClusterEntityPolicyYAML string + + //go:embed manifests/client-egress-only-dns.yaml + clientEgressOnlyDNSPolicyYAML string + + //go:embed manifests/client-egress-to-fqdns-one-one-one-one.yaml + clientEgressToFQDNsCiliumIOPolicyYAML string + + //go:embed manifests/echo-ingress-from-other-client.yaml + echoIngressFromOtherClientPolicyYAML string + + //go:embed manifests/client-egress-to-cidr-cp-host-knp.yaml + clientEgressToCIDRCPHostPolicyYAML string + + //go:embed manifests/client-egress-to-cidr-external.yaml + clientEgressToCIDRExternalPolicyYAML string + + //go:embed manifests/client-egress-to-cidr-external-knp.yaml + clientEgressToCIDRExternalPolicyKNPYAML string + + //go:embed manifests/client-egress-to-cidr-k8s.yaml + clientEgressToCIDRK8sPolicyYAML string + + //go:embed manifests/client-egress-to-cidr-node-knp.yaml + clientEgressToCIDRNodeKNPYAML string + + //go:embed manifests/client-egress-to-cidr-external-deny.yaml + clientEgressToCIDRExternalDenyPolicyYAML string + + //go:embed manifests/client-egress-l7-http.yaml + clientEgressL7HTTPPolicyYAML string + + //go:embed manifests/client-egress-l7-http-named-port.yaml + clientEgressL7HTTPNamedPortPolicyYAML string + + //go:embed manifests/client-egress-l7-tls.yaml + clientEgressL7TLSPolicyYAML string + + //go:embed manifests/client-egress-l7-http-matchheader-secret.yaml + clientEgressL7HTTPMatchheaderSecretYAML string + + //go:embed manifests/echo-ingress-from-cidr.yaml + echoIngressFromCIDRYAML string +) + +var ( + clientLabel = map[string]string{"name": "client"} + client2Label = map[string]string{"name": "client2"} + + runAlways = func(semver.Version, check.Parameters) bool { return true } + + parallelTests = []factory{ + noUnexpectedPacketDrops, + noPolicies, + noPoliciesFromOutside, + noPoliciesExtra, + allowAllExceptWorld, + clientIngress, + clientIngressKnp, + allowAllWithMetricsCheck, + allIngressDeny, + allIngressDenyFromOutside, + allIngressDenyKnp, + allEgressDeny, + allEgressDenyKnp, + allEntitiesDeny, + clusterEntity, + clusterEntityMultiCluster, + hostEntityEgress, + hostEntityIngress, + echoIngress, + echoIngressFromOutside, + echoIngressKnp, + clientIngressIcmp, + clientEgress, + clientEgressKnp, + clientEgressExpression, + clientEgressExpressionKnp, + clientWithServiceAccountEgressToEcho, + clientEgressToEchoServiceAccount, + toEntitiesWorld, + toCidrExternal, + toCidrExternalKnp, + fromCidrHostNetns, + echoIngressFromOtherClientDeny, + clientIngressFromOtherClientIcmpDeny, + clientEgressToEchoDeny, + clientIngressToEchoNamedPortDeny, + clientEgressToEchoExpressionDeny, + clientWithServiceAccountEgressToEchoDeny, + clientEgressToEchoServiceAccountDeny, + clientEgressToCidrDeny, + clientEgressToCidrDenyDefault, + health, + northSouthLoadbalancing, + podToPodEncryption, + nodeToNodeEncryption, + egressGateway, + egressGatewayExcludedCidrs, + podToNodeCidrpolicy, + northSouthLoadbalancingWithL7Policy, + echoIngressL7, + echoIngressL7NamedPort, + clientEgressL7Method, + clientEgressL7, + clientEgressL7NamedPort, + clientEgressL7TlsDenyWithoutHeaders, + clientEgressL7TlsHeaders, + clientEgressL7SetHeader, + echoIngressAuthAlwaysFail, + echoIngressMutualAuthSpiffe, + podToIngressService, + podToIngressServiceDenyAll, + podToIngressServiceDenyIngressIdentity, + podToIngressServiceDenyBackendService, + podToIngressServiceAllowIngressIdentity, + outsideToIngressService, + outsideToIngressServiceDenyWorldIdentity, + outsideToIngressServiceDenyCidr, + outsideToIngressServiceDenyAllIngress, + dnsOnly, + toFqdns, + podToControlplaneHost, + podToK8sOnControlplane, + podToControlplaneHostCidr, + podToK8sOnControlplaneCidr, + } +) + +type factory struct { + name string + build func(name string, ct *check.ConnectivityTest, templates map[string]string) + condition func(version semver.Version, params check.Parameters) bool +} + +func InjectTests(ct *check.ConnectivityTest, extraTests func(ct *check.ConnectivityTest) error) error { + templates, err := renderTemplates(ct.Params()) + if err != nil { + return err + } + + // Network Performance Test + if ct.Params().Perf { + injectTests(ct, templates, networkPerf) + return nil + } + + // Conn disrupt Test + if ct.Params().IncludeConnDisruptTest { + injectTests(ct, templates, noInterruptedConnections, noIpsecXfrmErrors) + if ct.Params().ConnDisruptTestSetup { + // Exit early, as --conn-disrupt-test-setup is only needed to deploy pods which + // will be used by another invocation of "cli connectivity test" (with + // include --include-conn-disrupt-test" + return nil + } + } + + injectTests(ct, templates, parallelTests...) + + if err := extraTests(ct); err != nil { + return err + } + + injectTests(ct, templates, checkLogErrors) + return nil +} + +func renderTemplates(param check.Parameters) (map[string]string, error) { + templates := map[string]string{ + "clientEgressToCIDRExternalPolicyYAML": clientEgressToCIDRExternalPolicyYAML, + "clientEgressToCIDRExternalPolicyKNPYAML": clientEgressToCIDRExternalPolicyKNPYAML, + "clientEgressToCIDRNodeKNPYAML": clientEgressToCIDRNodeKNPYAML, + "clientEgressToCIDRExternalDenyPolicyYAML": clientEgressToCIDRExternalDenyPolicyYAML, + "clientEgressL7HTTPPolicyYAML": clientEgressL7HTTPPolicyYAML, + "clientEgressL7HTTPNamedPortPolicyYAML": clientEgressL7HTTPNamedPortPolicyYAML, + "clientEgressToFQDNsCiliumIOPolicyYAML": clientEgressToFQDNsCiliumIOPolicyYAML, + "clientEgressL7TLSPolicyYAML": clientEgressL7TLSPolicyYAML, + "clientEgressL7HTTPMatchheaderSecretYAML": clientEgressL7HTTPMatchheaderSecretYAML, + "echoIngressFromCIDRYAML": echoIngressFromCIDRYAML, + "denyCIDRPolicyYAML": denyCIDRPolicyYAML, + } + if param.K8sLocalHostTest { + templates["clientEgressToCIDRCPHostPolicyYAML"] = clientEgressToCIDRCPHostPolicyYAML + templates["clientEgressToCIDRK8sPolicyKNPYAML"] = clientEgressToCIDRK8sPolicyYAML + } + + renderedTemplates := map[string]string{} + for key, temp := range templates { + val, err := template.Render(temp, param) + if err != nil { + return nil, err + } + renderedTemplates[key] = val + } + return renderedTemplates, nil +} + +func injectTests(ct *check.ConnectivityTest, templates map[string]string, tests ...factory) { + for _, t := range tests { + if t.condition(ct.CiliumVersion, ct.Params()) { + t.build(t.name, ct, templates) + } + } +} + +func withKPRReqForMultiCluster(ct *check.ConnectivityTest, reqs ...features.Requirement) []features.Requirement { + // Skip the nodeport-related tests in the multicluster scenario if KPR is not + // enabled, since global nodeport services are not supported in that case. + if ct.Params().MultiCluster != "" { + reqs = append(reqs, features.RequireEnabled(features.KPRNodePort)) + } + return reqs +} diff --git a/connectivity/factory/from_cidr_host_netns.go b/connectivity/factory/from_cidr_host_netns.go new file mode 100644 index 0000000000..9f7ef87db3 --- /dev/null +++ b/connectivity/factory/from_cidr_host_netns.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var fromCidrHostNetns = factory{ + name: "from-cidr-host-netns", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). + WithCiliumPolicy(templates["echoIngressFromCIDRYAML"]). + WithIPRoutesFromOutsideToPodCIDRs(). + WithScenarios(tests.FromCIDRToPod()). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK, check.ResultNone + }) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeUnsafeTests }, +} diff --git a/connectivity/factory/health.go b/connectivity/factory/health.go new file mode 100644 index 0000000000..d6373b3d94 --- /dev/null +++ b/connectivity/factory/health.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var health = factory{ + name: "health", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Health check tests. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.HealthChecking)). + WithScenarios(tests.CiliumHealth()) + }, + condition: runAlways, +} diff --git a/connectivity/factory/host_entity_egress.go b/connectivity/factory/host_entity_egress.go new file mode 100644 index 0000000000..515d968c86 --- /dev/null +++ b/connectivity/factory/host_entity_egress.go @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/allow-host-entity-egress.yaml + allowHostEntityEgressPolicyYAML string + + hostEntityEgress = factory{ + name: "host-entity-egress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows egress traffic towards the host entity + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowHostEntityEgressPolicyYAML). + WithScenarios(tests.PodToHost()). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/host_entity_ingress.go b/connectivity/factory/host_entity_ingress.go new file mode 100644 index 0000000000..56bca21785 --- /dev/null +++ b/connectivity/factory/host_entity_ingress.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/allow-host-entity-ingress.yaml + allowHostEntityIngressPolicyYAML string + + hostEntityIngress = factory{ + name: "host-entity-ingress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows ingress traffic from the host entity + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(allowHostEntityIngressPolicyYAML). + WithScenarios(tests.HostToPod()) + }, + condition: runAlways, + } +) diff --git a/connectivity/manifests/allow-all-egress.yaml b/connectivity/factory/manifests/allow-all-egress.yaml similarity index 100% rename from connectivity/manifests/allow-all-egress.yaml rename to connectivity/factory/manifests/allow-all-egress.yaml diff --git a/connectivity/manifests/allow-all-except-world.yaml b/connectivity/factory/manifests/allow-all-except-world.yaml similarity index 100% rename from connectivity/manifests/allow-all-except-world.yaml rename to connectivity/factory/manifests/allow-all-except-world.yaml diff --git a/connectivity/manifests/allow-all-ingress.yaml b/connectivity/factory/manifests/allow-all-ingress.yaml similarity index 100% rename from connectivity/manifests/allow-all-ingress.yaml rename to connectivity/factory/manifests/allow-all-ingress.yaml diff --git a/connectivity/manifests/allow-cluster-entity.yaml b/connectivity/factory/manifests/allow-cluster-entity.yaml similarity index 100% rename from connectivity/manifests/allow-cluster-entity.yaml rename to connectivity/factory/manifests/allow-cluster-entity.yaml diff --git a/connectivity/manifests/allow-host-entity-egress.yaml b/connectivity/factory/manifests/allow-host-entity-egress.yaml similarity index 100% rename from connectivity/manifests/allow-host-entity-egress.yaml rename to connectivity/factory/manifests/allow-host-entity-egress.yaml diff --git a/connectivity/manifests/allow-host-entity-ingress.yaml b/connectivity/factory/manifests/allow-host-entity-ingress.yaml similarity index 100% rename from connectivity/manifests/allow-host-entity-ingress.yaml rename to connectivity/factory/manifests/allow-host-entity-ingress.yaml diff --git a/connectivity/manifests/allow-ingress-identity.yaml b/connectivity/factory/manifests/allow-ingress-identity.yaml similarity index 100% rename from connectivity/manifests/allow-ingress-identity.yaml rename to connectivity/factory/manifests/allow-ingress-identity.yaml diff --git a/connectivity/manifests/client-egress-l7-http-matchheader-secret.yaml b/connectivity/factory/manifests/client-egress-l7-http-matchheader-secret.yaml similarity index 100% rename from connectivity/manifests/client-egress-l7-http-matchheader-secret.yaml rename to connectivity/factory/manifests/client-egress-l7-http-matchheader-secret.yaml diff --git a/connectivity/manifests/client-egress-l7-http-method.yaml b/connectivity/factory/manifests/client-egress-l7-http-method.yaml similarity index 100% rename from connectivity/manifests/client-egress-l7-http-method.yaml rename to connectivity/factory/manifests/client-egress-l7-http-method.yaml diff --git a/connectivity/manifests/client-egress-l7-http-named-port.yaml b/connectivity/factory/manifests/client-egress-l7-http-named-port.yaml similarity index 100% rename from connectivity/manifests/client-egress-l7-http-named-port.yaml rename to connectivity/factory/manifests/client-egress-l7-http-named-port.yaml diff --git a/connectivity/manifests/client-egress-l7-http.yaml b/connectivity/factory/manifests/client-egress-l7-http.yaml similarity index 100% rename from connectivity/manifests/client-egress-l7-http.yaml rename to connectivity/factory/manifests/client-egress-l7-http.yaml diff --git a/connectivity/manifests/client-egress-l7-tls.yaml b/connectivity/factory/manifests/client-egress-l7-tls.yaml similarity index 100% rename from connectivity/manifests/client-egress-l7-tls.yaml rename to connectivity/factory/manifests/client-egress-l7-tls.yaml diff --git a/connectivity/manifests/client-egress-only-dns.yaml b/connectivity/factory/manifests/client-egress-only-dns.yaml similarity index 100% rename from connectivity/manifests/client-egress-only-dns.yaml rename to connectivity/factory/manifests/client-egress-only-dns.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-cp-host-knp.yaml b/connectivity/factory/manifests/client-egress-to-cidr-cp-host-knp.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-cp-host-knp.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-cp-host-knp.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-external-deny.yaml b/connectivity/factory/manifests/client-egress-to-cidr-external-deny.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-external-deny.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-external-deny.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-external-knp.yaml b/connectivity/factory/manifests/client-egress-to-cidr-external-knp.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-external-knp.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-external-knp.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-external.yaml b/connectivity/factory/manifests/client-egress-to-cidr-external.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-external.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-external.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-k8s.yaml b/connectivity/factory/manifests/client-egress-to-cidr-k8s.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-k8s.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-k8s.yaml diff --git a/connectivity/manifests/client-egress-to-cidr-node-knp.yaml b/connectivity/factory/manifests/client-egress-to-cidr-node-knp.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-cidr-node-knp.yaml rename to connectivity/factory/manifests/client-egress-to-cidr-node-knp.yaml diff --git a/connectivity/manifests/client-egress-to-echo-deny.yaml b/connectivity/factory/manifests/client-egress-to-echo-deny.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-deny.yaml rename to connectivity/factory/manifests/client-egress-to-echo-deny.yaml diff --git a/connectivity/manifests/client-egress-to-echo-expression-deny.yaml b/connectivity/factory/manifests/client-egress-to-echo-expression-deny.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-expression-deny.yaml rename to connectivity/factory/manifests/client-egress-to-echo-expression-deny.yaml diff --git a/connectivity/manifests/client-egress-to-echo-expression-knp.yaml b/connectivity/factory/manifests/client-egress-to-echo-expression-knp.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-expression-knp.yaml rename to connectivity/factory/manifests/client-egress-to-echo-expression-knp.yaml diff --git a/connectivity/manifests/client-egress-to-echo-expression.yaml b/connectivity/factory/manifests/client-egress-to-echo-expression.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-expression.yaml rename to connectivity/factory/manifests/client-egress-to-echo-expression.yaml diff --git a/connectivity/manifests/client-egress-to-echo-knp.yaml b/connectivity/factory/manifests/client-egress-to-echo-knp.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-knp.yaml rename to connectivity/factory/manifests/client-egress-to-echo-knp.yaml diff --git a/connectivity/manifests/client-egress-to-echo-named-port-deny.yaml b/connectivity/factory/manifests/client-egress-to-echo-named-port-deny.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-named-port-deny.yaml rename to connectivity/factory/manifests/client-egress-to-echo-named-port-deny.yaml diff --git a/connectivity/manifests/client-egress-to-echo-service-account-deny.yaml b/connectivity/factory/manifests/client-egress-to-echo-service-account-deny.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-service-account-deny.yaml rename to connectivity/factory/manifests/client-egress-to-echo-service-account-deny.yaml diff --git a/connectivity/manifests/client-egress-to-echo-service-account.yaml b/connectivity/factory/manifests/client-egress-to-echo-service-account.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo-service-account.yaml rename to connectivity/factory/manifests/client-egress-to-echo-service-account.yaml diff --git a/connectivity/manifests/client-egress-to-echo.yaml b/connectivity/factory/manifests/client-egress-to-echo.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-echo.yaml rename to connectivity/factory/manifests/client-egress-to-echo.yaml diff --git a/connectivity/manifests/client-egress-to-entities-host.yaml b/connectivity/factory/manifests/client-egress-to-entities-host.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-entities-host.yaml rename to connectivity/factory/manifests/client-egress-to-entities-host.yaml diff --git a/connectivity/manifests/client-egress-to-entities-k8s.yaml b/connectivity/factory/manifests/client-egress-to-entities-k8s.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-entities-k8s.yaml rename to connectivity/factory/manifests/client-egress-to-entities-k8s.yaml diff --git a/connectivity/manifests/client-egress-to-entities-world.yaml b/connectivity/factory/manifests/client-egress-to-entities-world.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-entities-world.yaml rename to connectivity/factory/manifests/client-egress-to-entities-world.yaml diff --git a/connectivity/manifests/client-egress-to-fqdns-one-one-one-one.yaml b/connectivity/factory/manifests/client-egress-to-fqdns-one-one-one-one.yaml similarity index 100% rename from connectivity/manifests/client-egress-to-fqdns-one-one-one-one.yaml rename to connectivity/factory/manifests/client-egress-to-fqdns-one-one-one-one.yaml diff --git a/connectivity/manifests/client-ingress-from-client2-knp.yaml b/connectivity/factory/manifests/client-ingress-from-client2-knp.yaml similarity index 100% rename from connectivity/manifests/client-ingress-from-client2-knp.yaml rename to connectivity/factory/manifests/client-ingress-from-client2-knp.yaml diff --git a/connectivity/manifests/client-ingress-from-client2.yaml b/connectivity/factory/manifests/client-ingress-from-client2.yaml similarity index 100% rename from connectivity/manifests/client-ingress-from-client2.yaml rename to connectivity/factory/manifests/client-ingress-from-client2.yaml diff --git a/connectivity/manifests/client-with-service-account-egress-to-echo-deny.yaml b/connectivity/factory/manifests/client-with-service-account-egress-to-echo-deny.yaml similarity index 100% rename from connectivity/manifests/client-with-service-account-egress-to-echo-deny.yaml rename to connectivity/factory/manifests/client-with-service-account-egress-to-echo-deny.yaml diff --git a/connectivity/manifests/client-with-service-account-egress-to-echo.yaml b/connectivity/factory/manifests/client-with-service-account-egress-to-echo.yaml similarity index 100% rename from connectivity/manifests/client-with-service-account-egress-to-echo.yaml rename to connectivity/factory/manifests/client-with-service-account-egress-to-echo.yaml diff --git a/connectivity/manifests/deny-all-egress-knp.yaml b/connectivity/factory/manifests/deny-all-egress-knp.yaml similarity index 100% rename from connectivity/manifests/deny-all-egress-knp.yaml rename to connectivity/factory/manifests/deny-all-egress-knp.yaml diff --git a/connectivity/manifests/deny-all-egress.yaml b/connectivity/factory/manifests/deny-all-egress.yaml similarity index 100% rename from connectivity/manifests/deny-all-egress.yaml rename to connectivity/factory/manifests/deny-all-egress.yaml diff --git a/connectivity/manifests/deny-all-entities.yaml b/connectivity/factory/manifests/deny-all-entities.yaml similarity index 100% rename from connectivity/manifests/deny-all-entities.yaml rename to connectivity/factory/manifests/deny-all-entities.yaml diff --git a/connectivity/manifests/deny-all-ingress-knp.yaml b/connectivity/factory/manifests/deny-all-ingress-knp.yaml similarity index 100% rename from connectivity/manifests/deny-all-ingress-knp.yaml rename to connectivity/factory/manifests/deny-all-ingress-knp.yaml diff --git a/connectivity/manifests/deny-all-ingress.yaml b/connectivity/factory/manifests/deny-all-ingress.yaml similarity index 100% rename from connectivity/manifests/deny-all-ingress.yaml rename to connectivity/factory/manifests/deny-all-ingress.yaml diff --git a/connectivity/manifests/deny-cidr.yaml b/connectivity/factory/manifests/deny-cidr.yaml similarity index 100% rename from connectivity/manifests/deny-cidr.yaml rename to connectivity/factory/manifests/deny-cidr.yaml diff --git a/connectivity/manifests/deny-ingress-backend.yaml b/connectivity/factory/manifests/deny-ingress-backend.yaml similarity index 100% rename from connectivity/manifests/deny-ingress-backend.yaml rename to connectivity/factory/manifests/deny-ingress-backend.yaml diff --git a/connectivity/manifests/deny-ingress-entity.yaml b/connectivity/factory/manifests/deny-ingress-entity.yaml similarity index 100% rename from connectivity/manifests/deny-ingress-entity.yaml rename to connectivity/factory/manifests/deny-ingress-entity.yaml diff --git a/connectivity/manifests/deny-world-entity.yaml b/connectivity/factory/manifests/deny-world-entity.yaml similarity index 100% rename from connectivity/manifests/deny-world-entity.yaml rename to connectivity/factory/manifests/deny-world-entity.yaml diff --git a/connectivity/manifests/echo-ingress-from-cidr.yaml b/connectivity/factory/manifests/echo-ingress-from-cidr.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-from-cidr.yaml rename to connectivity/factory/manifests/echo-ingress-from-cidr.yaml diff --git a/connectivity/manifests/echo-ingress-from-other-client-deny.yaml b/connectivity/factory/manifests/echo-ingress-from-other-client-deny.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-from-other-client-deny.yaml rename to connectivity/factory/manifests/echo-ingress-from-other-client-deny.yaml diff --git a/connectivity/manifests/echo-ingress-from-other-client-knp.yaml b/connectivity/factory/manifests/echo-ingress-from-other-client-knp.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-from-other-client-knp.yaml rename to connectivity/factory/manifests/echo-ingress-from-other-client-knp.yaml diff --git a/connectivity/manifests/echo-ingress-from-other-client.yaml b/connectivity/factory/manifests/echo-ingress-from-other-client.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-from-other-client.yaml rename to connectivity/factory/manifests/echo-ingress-from-other-client.yaml diff --git a/connectivity/manifests/echo-ingress-icmp-deny.yaml b/connectivity/factory/manifests/echo-ingress-icmp-deny.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-icmp-deny.yaml rename to connectivity/factory/manifests/echo-ingress-icmp-deny.yaml diff --git a/connectivity/manifests/echo-ingress-icmp.yaml b/connectivity/factory/manifests/echo-ingress-icmp.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-icmp.yaml rename to connectivity/factory/manifests/echo-ingress-icmp.yaml diff --git a/connectivity/manifests/echo-ingress-l7-http-from-anywhere.yaml b/connectivity/factory/manifests/echo-ingress-l7-http-from-anywhere.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-l7-http-from-anywhere.yaml rename to connectivity/factory/manifests/echo-ingress-l7-http-from-anywhere.yaml diff --git a/connectivity/manifests/echo-ingress-l7-http-named-port.yaml b/connectivity/factory/manifests/echo-ingress-l7-http-named-port.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-l7-http-named-port.yaml rename to connectivity/factory/manifests/echo-ingress-l7-http-named-port.yaml diff --git a/connectivity/manifests/echo-ingress-l7-http.yaml b/connectivity/factory/manifests/echo-ingress-l7-http.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-l7-http.yaml rename to connectivity/factory/manifests/echo-ingress-l7-http.yaml diff --git a/connectivity/manifests/echo-ingress-mutual-authentication-fail.yaml b/connectivity/factory/manifests/echo-ingress-mutual-authentication-fail.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-mutual-authentication-fail.yaml rename to connectivity/factory/manifests/echo-ingress-mutual-authentication-fail.yaml diff --git a/connectivity/manifests/echo-ingress-mutual-authentication.yaml b/connectivity/factory/manifests/echo-ingress-mutual-authentication.yaml similarity index 100% rename from connectivity/manifests/echo-ingress-mutual-authentication.yaml rename to connectivity/factory/manifests/echo-ingress-mutual-authentication.yaml diff --git a/connectivity/manifests/template/template.go b/connectivity/factory/manifests/template/template.go similarity index 100% rename from connectivity/manifests/template/template.go rename to connectivity/factory/manifests/template/template.go diff --git a/connectivity/factory/network_perf.go b/connectivity/factory/network_perf.go new file mode 100644 index 0000000000..10feb62065 --- /dev/null +++ b/connectivity/factory/network_perf.go @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/perf/benchmarks/netperf" +) + +var networkPerf = factory{ + "network-perf", + func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios(netperf.Netperf("")) + }, + func(_ semver.Version, params check.Parameters) bool { return params.Perf }, +} diff --git a/connectivity/factory/no_interrupted_connections.go b/connectivity/factory/no_interrupted_connections.go new file mode 100644 index 0000000000..e000cd4061 --- /dev/null +++ b/connectivity/factory/no_interrupted_connections.go @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var noInterruptedConnections = factory{ + name: "no-interrupted-connections", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios(tests.NoInterruptedConnections()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeConnDisruptTest }, +} diff --git a/connectivity/factory/no_ipsec_xfrm_errors.go b/connectivity/factory/no_ipsec_xfrm_errors.go new file mode 100644 index 0000000000..9e305c76b8 --- /dev/null +++ b/connectivity/factory/no_ipsec_xfrm_errors.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var noIpsecXfrmErrors = factory{ + name: "no-ipsec-xfrm-errors", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireMode(features.EncryptionPod, "ipsec")). + WithScenarios(tests.NoIPsecXfrmErrors(ct.Params().ExpectedXFRMErrors)) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeConnDisruptTest }, +} diff --git a/connectivity/factory/no_policies.go b/connectivity/factory/no_policies.go new file mode 100644 index 0000000000..dee013ca26 --- /dev/null +++ b/connectivity/factory/no_policies.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var noPolicies = factory{ + name: "no-policies", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios( + tests.PodToPod(), + tests.ClientToClient(), + tests.PodToService(), + tests.PodToHostPort(), + tests.PodToWorld(tests.WithRetryAll()), + tests.PodToHost(), + tests.HostToPod(), + tests.PodToExternalWorkload(), + tests.PodToCIDR(tests.WithRetryAll()), + ) + }, + condition: runAlways, +} diff --git a/connectivity/factory/no_policies_extra.go b/connectivity/factory/no_policies_extra.go new file mode 100644 index 0000000000..d2eb65ae87 --- /dev/null +++ b/connectivity/factory/no_policies_extra.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var noPoliciesExtra = factory{ + name: "no-policies-extra", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(withKPRReqForMultiCluster(ct)...). + WithScenarios( + tests.PodToRemoteNodePort(), + tests.PodToLocalNodePort(), + ) + }, + condition: runAlways, +} diff --git a/connectivity/factory/no_policies_from_outside.go b/connectivity/factory/no_policies_from_outside.go new file mode 100644 index 0000000000..735a7d095f --- /dev/null +++ b/connectivity/factory/no_policies_from_outside.go @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var noPoliciesFromOutside = factory{ + name: "no-policies-from-outside", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). + WithIPRoutesFromOutsideToPodCIDRs(). + WithScenarios(tests.FromCIDRToPod()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.IncludeUnsafeTests }, +} diff --git a/connectivity/factory/no_unexpected_packet_drops.go b/connectivity/factory/no_unexpected_packet_drops.go new file mode 100644 index 0000000000..5eb98f9504 --- /dev/null +++ b/connectivity/factory/no_unexpected_packet_drops.go @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var noUnexpectedPacketDrops = factory{ + name: "no-unexpected-packet-drops", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios(tests.NoUnexpectedPacketDrops(ct.Params().ExpectedDropReasons)) + }, + condition: runAlways, +} diff --git a/connectivity/factory/node_to_node_encryption.go b/connectivity/factory/node_to_node_encryption.go new file mode 100644 index 0000000000..5b7a639a84 --- /dev/null +++ b/connectivity/factory/node_to_node_encryption.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var nodeToNodeEncryption = factory{ + name: "node-to-node-encryption", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Encryption checks are always executed as a sanity check, asserting whether + // unencrypted packets shall, or shall not, be observed based on the feature set. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios( + tests.NodeToNodeEncryption( + features.RequireEnabled(features.EncryptionPod), + features.RequireEnabled(features.EncryptionNode), + ), + ) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return !params.SingleNode }, +} diff --git a/connectivity/factory/north_south_loadbalancing.go b/connectivity/factory/north_south_loadbalancing.go new file mode 100644 index 0000000000..deaf2946ea --- /dev/null +++ b/connectivity/factory/north_south_loadbalancing.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var northSouthLoadbalancing = factory{ + name: "north-south-loadbalancing", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + withKPRReqForMultiCluster(ct, features.RequireEnabled(features.NodeWithoutCilium))..., + ). + WithScenarios(tests.OutsideToNodePort()) + }, + condition: runAlways, +} diff --git a/connectivity/factory/north_south_loadbalancing_with_l7_policy.go b/connectivity/factory/north_south_loadbalancing_with_l7_policy.go new file mode 100644 index 0000000000..667060c239 --- /dev/null +++ b/connectivity/factory/north_south_loadbalancing_with_l7_policy.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/echo-ingress-l7-http-from-anywhere.yaml + echoIngressL7HTTPFromAnywherePolicyYAML string + + northSouthLoadbalancingWithL7Policy = factory{ + name: "north-south-loadbalancing-with-l7-policy", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // The following tests have DNS redirect policies. They should be executed last. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + withKPRReqForMultiCluster(ct, + features.RequireEnabled(features.NodeWithoutCilium), + features.RequireEnabled(features.L7Proxy))..., + ). + WithCiliumVersion(">1.13.2"). + WithCiliumPolicy(echoIngressL7HTTPFromAnywherePolicyYAML). + WithScenarios(tests.OutsideToNodePort()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/outside_to_ingress_service.go b/connectivity/factory/outside_to_ingress_service.go new file mode 100644 index 0000000000..a2cb940510 --- /dev/null +++ b/connectivity/factory/outside_to_ingress_service.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var outsideToIngressService = factory{ + name: "outside-to-ingress-service", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium)). + WithScenarios(tests.OutsideToIngressService()) + }, + condition: runAlways, +} diff --git a/connectivity/factory/outside_to_ingress_service_deny_all_ingress.go b/connectivity/factory/outside_to_ingress_service_deny_all_ingress.go new file mode 100644 index 0000000000..3ccc59ee82 --- /dev/null +++ b/connectivity/factory/outside_to_ingress_service_deny_all_ingress.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var outsideToIngressServiceDenyAllIngress = factory{ + name: "outside-to-ingress-service-deny-all-ingress", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/outside_to_ingress_service_deny_cidr.go b/connectivity/factory/outside_to_ingress_service_deny_cidr.go new file mode 100644 index 0000000000..8d51be4f9b --- /dev/null +++ b/connectivity/factory/outside_to_ingress_service_deny_cidr.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var outsideToIngressServiceDenyCidr = factory{ + name: "outside-to-ingress-service-deny-cidr", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(templates["denyCIDRPolicyYAML"]). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/outside_to_ingress_service_deny_world_identity.go b/connectivity/factory/outside_to_ingress_service_deny_world_identity.go new file mode 100644 index 0000000000..0112f987b9 --- /dev/null +++ b/connectivity/factory/outside_to_ingress_service_deny_world_identity.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/deny-world-entity.yaml + denyWorldIdentityPolicyYAML string + + outsideToIngressServiceDenyWorldIdentity = factory{ + name: "outside-to-ingress-service-deny-world-identity", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(denyWorldIdentityPolicyYAML). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/pod_to_controlplane_host.go b/connectivity/factory/pod_to_controlplane_host.go new file mode 100644 index 0000000000..f81d0d6c94 --- /dev/null +++ b/connectivity/factory/pod_to_controlplane_host.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-entities-host.yaml + clientEgressToEntitiesHostPolicyYAML string + + podToControlplaneHost = factory{ + name: "pod-to-controlplane-host", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEntitiesHostPolicyYAML). + WithScenarios(tests.PodToControlPlaneHost()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.K8sLocalHostTest }, + } +) diff --git a/connectivity/factory/pod_to_controlplane_host_cidr.go b/connectivity/factory/pod_to_controlplane_host_cidr.go new file mode 100644 index 0000000000..5bea682cbc --- /dev/null +++ b/connectivity/factory/pod_to_controlplane_host_cidr.go @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToControlplaneHostCidr = factory{ + name: "pod-to-controlplane-host-cidr", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Check that pods can access when referencing them by CIDR selectors + // (when this feature is enabled). + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.CIDRMatchNodes)). + WithK8SPolicy(templates["clientEgressToCIDRCPHostPolicyYAML"]). + WithScenarios(tests.PodToControlPlaneHost()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.K8sLocalHostTest }, +} diff --git a/connectivity/factory/pod_to_ingress_service.go b/connectivity/factory/pod_to_ingress_service.go new file mode 100644 index 0000000000..09724b2e39 --- /dev/null +++ b/connectivity/factory/pod_to_ingress_service.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToIngressService = factory{ + name: "pod-to-ingress-service", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Test Ingress controller + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithScenarios(tests.PodToIngress()) + }, + condition: runAlways, +} diff --git a/connectivity/factory/pod_to_ingress_service_allow_ingress_identity.go b/connectivity/factory/pod_to_ingress_service_allow_ingress_identity.go new file mode 100644 index 0000000000..6961bc60ba --- /dev/null +++ b/connectivity/factory/pod_to_ingress_service_allow_ingress_identity.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/allow-ingress-identity.yaml + allowIngressIdentityPolicyYAML string + + podToIngressServiceAllowIngressIdentity = factory{ + name: "pod-to-ingress-service-allow-ingress-identity", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithCiliumPolicy(allowIngressIdentityPolicyYAML). + WithScenarios(tests.PodToIngress()) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/pod_to_ingress_service_deny_all.go b/connectivity/factory/pod_to_ingress_service_deny_all.go new file mode 100644 index 0000000000..281db011b0 --- /dev/null +++ b/connectivity/factory/pod_to_ingress_service_deny_all.go @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToIngressServiceDenyAll = factory{ + name: "pod-to-ingress-service-deny-all", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/pod_to_ingress_service_deny_backend_service.go b/connectivity/factory/pod_to_ingress_service_deny_backend_service.go new file mode 100644 index 0000000000..30f4fe3886 --- /dev/null +++ b/connectivity/factory/pod_to_ingress_service_deny_backend_service.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/deny-ingress-backend.yaml + denyIngressBackendPolicyYAML string + + podToIngressServiceDenyBackendService = factory{ + name: "pod-to-ingress-service-deny-backend-service", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyIngressBackendPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/pod_to_ingress_service_deny_ingress_identity.go b/connectivity/factory/pod_to_ingress_service_deny_ingress_identity.go new file mode 100644 index 0000000000..e5e05333a6 --- /dev/null +++ b/connectivity/factory/pod_to_ingress_service_deny_ingress_identity.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var ( + //go:embed manifests/deny-ingress-entity.yaml + denyIngressIdentityPolicyYAML string + + podToIngressServiceDenyIngressIdentity = factory{ + name: "pod-to-ingress-service-deny-ingress-identity", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyIngressIdentityPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/pod_to_k8s_on_controlplane.go b/connectivity/factory/pod_to_k8s_on_controlplane.go new file mode 100644 index 0000000000..3117b310ea --- /dev/null +++ b/connectivity/factory/pod_to_k8s_on_controlplane.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-entities-k8s.yaml + clientEgressToEntitiesK8sPolicyYAML string + + podToK8sOnControlplane = factory{ + name: "pod-to-k8s-on-controlplane", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEntitiesK8sPolicyYAML). + WithScenarios(tests.PodToK8sLocal()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.K8sLocalHostTest }, + } +) diff --git a/connectivity/factory/pod_to_k8s_on_controlplane_cidr.go b/connectivity/factory/pod_to_k8s_on_controlplane_cidr.go new file mode 100644 index 0000000000..a62bc45952 --- /dev/null +++ b/connectivity/factory/pod_to_k8s_on_controlplane_cidr.go @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToK8sOnControlplaneCidr = factory{ + name: "pod-to-k8s-on-controlplane-cidr", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.CIDRMatchNodes)). + WithCiliumPolicy(templates["clientEgressToCIDRK8sPolicyKNPYAML"]). + WithScenarios(tests.PodToK8sLocal()) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return params.K8sLocalHostTest }, +} diff --git a/connectivity/factory/pod_to_node_cidrpolicy.go b/connectivity/factory/pod_to_node_cidrpolicy.go new file mode 100644 index 0000000000..fa18c9eabe --- /dev/null +++ b/connectivity/factory/pod_to_node_cidrpolicy.go @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToNodeCidrpolicy = factory{ + name: "pod-to-node-cidrpolicy", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // Check that pods can access nodes when referencing them by CIDR selectors + // (when this feature is enabled). + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithFeatureRequirements(features.RequireEnabled(features.CIDRMatchNodes)). + WithK8SPolicy(templates["clientEgressToCIDRNodeKNPYAML"]). + WithScenarios(tests.PodToHost()) + }, + condition: runAlways, +} diff --git a/connectivity/factory/pod_to_pod_encryption.go b/connectivity/factory/pod_to_pod_encryption.go new file mode 100644 index 0000000000..a9d5850dc6 --- /dev/null +++ b/connectivity/factory/pod_to_pod_encryption.go @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/blang/semver/v4" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var podToPodEncryption = factory{ + name: "pod-to-pod-encryption", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // Encryption checks are always executed as a sanity check, asserting whether + // unencrypted packets shall, or shall not, be observed based on the feature set. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithScenarios( + tests.PodToPodEncryption(features.RequireEnabled(features.EncryptionPod)), + ) + }, + condition: func(_ semver.Version, params check.Parameters) bool { return !params.SingleNode }, +} diff --git a/connectivity/factory/to_cidr_external.go b/connectivity/factory/to_cidr_external.go new file mode 100644 index 0000000000..c4ba67a33b --- /dev/null +++ b/connectivity/factory/to_cidr_external.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var toCidrExternal = factory{ + name: "to-cidr-external", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // This policy allows L3 traffic to ExternalCIDR/24 (including ExternalIP), with the + // exception of ExternalOtherIP. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(templates["clientEgressToCIDRExternalPolicyYAML"]). + WithScenarios( + tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.IPFamilyV4) == ct.Params().ExternalOtherIP { + // Expect packets for ExternalOtherIP to be dropped. + return check.ResultDropCurlTimeout, check.ResultNone + } + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/to_cidr_external_knp.go b/connectivity/factory/to_cidr_external_knp.go new file mode 100644 index 0000000000..a463150afe --- /dev/null +++ b/connectivity/factory/to_cidr_external_knp.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var toCidrExternalKnp = factory{ + name: "to-cidr-external-knp", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // This policy allows L3 traffic to ExternalCIDR/24 (including ExternalIP), with the + // exception of ExternalOtherIP. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithK8SPolicy(templates["clientEgressToCIDRExternalPolicyKNPYAML"]). + WithScenarios( + tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.IPFamilyV4) == ct.Params().ExternalOtherIP { + // Expect packets for ExternalOtherIP to be dropped. + return check.ResultDropCurlTimeout, check.ResultNone + } + return check.ResultOK, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/factory/to_entities_world.go b/connectivity/factory/to_entities_world.go new file mode 100644 index 0000000000..f749013f12 --- /dev/null +++ b/connectivity/factory/to_entities_world.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + _ "embed" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" +) + +var ( + //go:embed manifests/client-egress-to-entities-world.yaml + clientEgressToEntitiesWorldPolicyYAML string + + toEntitiesWorld = factory{ + name: "to-entities-world", + build: func(name string, ct *check.ConnectivityTest, _ map[string]string) { + // This policy allows UDP to kube-dns and port 80 TCP to all 'world' endpoints. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(clientEgressToEntitiesWorldPolicyYAML). + WithScenarios(tests.PodToWorld(tests.WithRetryDestPort(80))). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Port() == 80 { + return check.ResultOK, check.ResultNone + } + // PodToWorld traffic to port 443 will be dropped by the policy + return check.ResultDropCurlTimeout, check.ResultNone + }) + }, + condition: runAlways, + } +) diff --git a/connectivity/factory/to_fqdns.go b/connectivity/factory/to_fqdns.go new file mode 100644 index 0000000000..1179871348 --- /dev/null +++ b/connectivity/factory/to_fqdns.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package factory + +import ( + "fmt" + + "github.com/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium-cli/connectivity/tests" + "github.com/cilium/cilium-cli/utils/features" +) + +var toFqdns = factory{ + name: "to-fqdns", + build: func(name string, ct *check.ConnectivityTest, templates map[string]string) { + // This policy only allows port 80 to domain-name, default one.one.one.one,. DNS proxy enabled. + test := check.NewTest(name, ct.Params().Verbose, ct.Params().Debug) + ct.AddTest(test). + WithCiliumPolicy(templates["clientEgressToFQDNsCiliumIOPolicyYAML"]). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithScenarios( + tests.PodToWorld(tests.WithRetryDestPort(80)), + tests.PodToWorld2(), // resolves cilium.io + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Address(features.IPFamilyAny) == "cilium.io" { + if a.Destination().Path() == "/" || a.Destination().Path() == "" { + egress = check.ResultDNSOK + egress.HTTP = check.HTTP{ + Method: "GET", + URL: "https://cilium.io", + } + // Expect packets for cilium.io / 104.198.14.52 to be dropped. + return check.ResultDropCurlTimeout, check.ResultNone + } + // Else expect HTTP drop by proxy + return check.ResultDNSOKDropCurlHTTPError, check.ResultNone + } + + extTarget := ct.Params().ExternalTarget + if a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(extTarget)) == extTarget { + if a.Destination().Path() == "/" || a.Destination().Path() == "" { + egress = check.ResultDNSOK + egress.HTTP = check.HTTP{ + Method: "GET", + URL: fmt.Sprintf("http://%s/", extTarget), + } + return egress, check.ResultNone + } + // Else expect HTTP drop by proxy + return check.ResultDNSOKDropCurlHTTPError, check.ResultNone + } + // No HTTP proxy on other ports + return check.ResultDNSOKDropCurlTimeout, check.ResultNone + }) + }, + condition: runAlways, +} diff --git a/connectivity/suite.go b/connectivity/suite.go index 805e6927c8..7f38f95e23 100644 --- a/connectivity/suite.go +++ b/connectivity/suite.go @@ -6,193 +6,9 @@ package connectivity import ( "context" _ "embed" - "fmt" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/cilium/cilium/pkg/versioncheck" "github.com/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium-cli/connectivity/manifests/template" - "github.com/cilium/cilium-cli/connectivity/perf/benchmarks/netperf" - "github.com/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium-cli/utils/features" -) - -var ( - //go:embed manifests/allow-all-egress.yaml - allowAllEgressPolicyYAML string - - //go:embed manifests/allow-all-ingress.yaml - allowAllIngressPolicyYAML string - - //go:embed manifests/deny-all-egress.yaml - denyAllEgressPolicyYAML string - - //go:embed manifests/deny-all-egress-knp.yaml - denyAllEgressPolicyKNPYAML string - - //go:embed manifests/deny-all-ingress.yaml - denyAllIngressPolicyYAML string - - //go:embed manifests/deny-all-ingress-knp.yaml - denyAllIngressPolicyKNPYAML string - - //go:embed manifests/deny-all-entities.yaml - denyAllEntitiesPolicyYAML string - - //go:embed manifests/deny-ingress-entity.yaml - denyIngressIdentityPolicyYAML string - - //go:embed manifests/deny-world-entity.yaml - denyWorldIdentityPolicyYAML string - - //go:embed manifests/deny-ingress-backend.yaml - denyIngressBackendPolicyYAML string - - //go:embed manifests/deny-cidr.yaml - denyCIDRPolicyYAML string - - //go:embed manifests/allow-cluster-entity.yaml - allowClusterEntityPolicyYAML string - - //go:embed manifests/allow-host-entity-egress.yaml - allowHostEntityEgressPolicyYAML string - - //go:embed manifests/allow-host-entity-ingress.yaml - allowHostEntityIngressPolicyYAML string - - //go:embed manifests/allow-all-except-world.yaml - allowAllExceptWorldPolicyYAML string - - //go:embed manifests/allow-ingress-identity.yaml - allowIngressIdentityPolicyYAML string - - //go:embed manifests/client-egress-only-dns.yaml - clientEgressOnlyDNSPolicyYAML string - - //go:embed manifests/client-egress-to-echo.yaml - clientEgressToEchoPolicyYAML string - - //go:embed manifests/client-egress-to-echo-knp.yaml - clientEgressToEchoPolicyKNPYAML string - - //go:embed manifests/client-with-service-account-egress-to-echo.yaml - clientWithServiceAccountEgressToEchoPolicyYAML string - - //go:embed manifests/client-egress-to-echo-service-account.yaml - clientEgressToEchoServiceAccountPolicyYAML string - - //go:embed manifests/client-egress-to-echo-expression.yaml - clientEgressToEchoExpressionPolicyYAML string - - //go:embed manifests/client-egress-to-echo-expression-knp.yaml - clientEgressToEchoExpressionPolicyKNPYAML string - - //go:embed manifests/client-egress-to-echo-deny.yaml - clientEgressToEchoDenyPolicyYAML string - - //go:embed manifests/client-egress-to-echo-expression-deny.yaml - clientEgressToEchoExpressionDenyPolicyYAML string - - //go:embed manifests/client-with-service-account-egress-to-echo-deny.yaml - clientWithServiceAccountEgressToEchoDenyPolicyYAML string - - //go:embed manifests/client-egress-to-echo-service-account-deny.yaml - clientEgressToEchoServiceAccountDenyPolicyYAML string - - //go:embed manifests/client-egress-to-echo-named-port-deny.yaml - clientEgressToEchoDenyNamedPortPolicyYAML string - - //go:embed manifests/client-ingress-from-client2.yaml - clientIngressFromClient2PolicyYAML string - - //go:embed manifests/client-ingress-from-client2-knp.yaml - clientIngressFromClient2PolicyKNPYAML string - - //go:embed manifests/client-egress-to-fqdns-one-one-one-one.yaml - clientEgressToFQDNsCiliumIOPolicyYAML string - - //go:embed manifests/echo-ingress-from-other-client.yaml - echoIngressFromOtherClientPolicyYAML string - - //go:embed manifests/echo-ingress-from-other-client-knp.yaml - echoIngressFromOtherClientPolicyKNPYAML string - - //go:embed manifests/echo-ingress-from-other-client-deny.yaml - echoIngressFromOtherClientDenyPolicyYAML string - - //go:embed manifests/client-egress-to-entities-host.yaml - clientEgressToEntitiesHostPolicyYAML string - - //go:embed manifests/client-egress-to-entities-k8s.yaml - clientEgressToEntitiesK8sPolicyYAML string - - //go:embed manifests/client-egress-to-entities-world.yaml - clientEgressToEntitiesWorldPolicyYAML string - - //go:embed manifests/client-egress-to-cidr-cp-host-knp.yaml - clientEgressToCIDRCPHostPolicyYAML string - - //go:embed manifests/client-egress-to-cidr-external.yaml - clientEgressToCIDRExternalPolicyYAML string - - //go:embed manifests/client-egress-to-cidr-external-knp.yaml - clientEgressToCIDRExternalPolicyKNPYAML string - - //go:embed manifests/client-egress-to-cidr-k8s.yaml - clientEgressToCIDRK8sPolicyYAML string - - //go:embed manifests/client-egress-to-cidr-node-knp.yaml - clientEgressToCIDRNodeKNPYAML string - - //go:embed manifests/client-egress-to-cidr-external-deny.yaml - clientEgressToCIDRExternalDenyPolicyYAML string - - //go:embed manifests/client-egress-l7-http.yaml - clientEgressL7HTTPPolicyYAML string - - //go:embed manifests/client-egress-l7-http-method.yaml - clientEgressL7HTTPMethodPolicyYAML string - - //go:embed manifests/client-egress-l7-http-named-port.yaml - clientEgressL7HTTPNamedPortPolicyYAML string - - //go:embed manifests/client-egress-l7-tls.yaml - clientEgressL7TLSPolicyYAML string - - //go:embed manifests/client-egress-l7-http-matchheader-secret.yaml - clientEgressL7HTTPMatchheaderSecretYAML string - - //go:embed manifests/echo-ingress-l7-http.yaml - echoIngressL7HTTPPolicyYAML string - - //go:embed manifests/echo-ingress-l7-http-from-anywhere.yaml - echoIngressL7HTTPFromAnywherePolicyYAML string - - //go:embed manifests/echo-ingress-l7-http-named-port.yaml - echoIngressL7HTTPNamedPortPolicyYAML string - - //go:embed manifests/echo-ingress-icmp.yaml - echoIngressICMPPolicyYAML string - - //go:embed manifests/echo-ingress-icmp-deny.yaml - echoIngressICMPDenyPolicyYAML string - - //go:embed manifests/echo-ingress-from-cidr.yaml - echoIngressFromCIDRYAML string - - //go:embed manifests/echo-ingress-mutual-authentication-fail.yaml - echoIngressAuthFailPolicyYAML string - - //go:embed manifests/echo-ingress-mutual-authentication.yaml - echoIngressMutualAuthPolicyYAML string -) - -var ( - clientLabel = map[string]string{"name": "client"} - client2Label = map[string]string{"name": "client2"} + "github.com/cilium/cilium-cli/connectivity/factory" ) // Hooks defines the extension hooks provided by connectivity tests. @@ -207,1045 +23,12 @@ func Run(ctx context.Context, ct *check.ConnectivityTest, extra Hooks) error { return err } - renderedTemplates := map[string]string{} - - templates := map[string]string{ - "clientEgressToCIDRExternalPolicyYAML": clientEgressToCIDRExternalPolicyYAML, - "clientEgressToCIDRExternalPolicyKNPYAML": clientEgressToCIDRExternalPolicyKNPYAML, - "clientEgressToCIDRNodeKNPYAML": clientEgressToCIDRNodeKNPYAML, - "clientEgressToCIDRExternalDenyPolicyYAML": clientEgressToCIDRExternalDenyPolicyYAML, - "clientEgressL7HTTPPolicyYAML": clientEgressL7HTTPPolicyYAML, - "clientEgressL7HTTPNamedPortPolicyYAML": clientEgressL7HTTPNamedPortPolicyYAML, - "clientEgressToFQDNsCiliumIOPolicyYAML": clientEgressToFQDNsCiliumIOPolicyYAML, - "clientEgressL7TLSPolicyYAML": clientEgressL7TLSPolicyYAML, - "clientEgressL7HTTPMatchheaderSecretYAML": clientEgressL7HTTPMatchheaderSecretYAML, - "echoIngressFromCIDRYAML": echoIngressFromCIDRYAML, - "denyCIDRPolicyYAML": denyCIDRPolicyYAML, - } - - if ct.Params().K8sLocalHostTest { - templates["clientEgressToCIDRCPHostPolicyYAML"] = clientEgressToCIDRCPHostPolicyYAML - templates["clientEgressToCIDRK8sPolicyKNPYAML"] = clientEgressToCIDRK8sPolicyYAML - } - - // render templates, if any problems fail early - for key, temp := range templates { - val, err := template.Render(temp, ct.Params()) - if err != nil { - return err - } - renderedTemplates[key] = val - } - ct.Infof("Cilium version: %v", ct.CiliumVersion) - // Network Performance Test - if ct.Params().Perf { - ct.NewTest("network-perf").WithScenarios( - netperf.Netperf(""), - ) - return ct.Run(ctx) - } - - // Conn disrupt Test - if ct.Params().IncludeConnDisruptTest { - ct.NewTest("no-interrupted-connections").WithScenarios( - tests.NoInterruptedConnections(), - ) - - ct.NewTest("no-ipsec-xfrm-errors"). - WithFeatureRequirements(features.RequireMode(features.EncryptionPod, "ipsec")). - WithScenarios(tests.NoIPsecXfrmErrors(ct.Params().ExpectedXFRMErrors)) - - if ct.Params().ConnDisruptTestSetup { - // Exit early, as --conn-disrupt-test-setup is only needed to deploy pods which - // will be used by another invocation of "cli connectivity test" (with - // include --include-conn-disrupt-test" - return ct.Run(ctx) - } - } - - ct.NewTest("no-unexpected-packet-drops").WithScenarios(tests.NoUnexpectedPacketDrops(ct.Params().ExpectedDropReasons)) - - // Run all tests without any policies in place. - noPoliciesScenarios := []check.Scenario{ - tests.PodToPod(), - tests.ClientToClient(), - tests.PodToService(), - tests.PodToHostPort(), - tests.PodToWorld(tests.WithRetryAll()), - tests.PodToHost(), - tests.HostToPod(), - tests.PodToExternalWorkload(), - tests.PodToCIDR(tests.WithRetryAll()), - } - - ct.NewTest("no-policies").WithScenarios(noPoliciesScenarios...) - - if ct.Params().IncludeUnsafeTests { - ct.NewTest("no-policies-from-outside"). - WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). - WithIPRoutesFromOutsideToPodCIDRs(). - WithScenarios(tests.FromCIDRToPod()) - } - - ct.NewTest("no-policies-extra"). - WithFeatureRequirements(withKPRReqForMultiCluster(ct)...). - WithScenarios( - tests.PodToRemoteNodePort(), - tests.PodToLocalNodePort(), - ) - - // Test with an allow-all-except-world (and unmanaged) policy. - ct.NewTest("allow-all-except-world").WithCiliumPolicy(allowAllExceptWorldPolicyYAML). - WithScenarios( - tests.PodToPod(), - tests.ClientToClient(), - tests.PodToService(), - // We are skipping the following checks because NodePort is - // intended to be used for N-S traffic, which conflicts with - // policies. See GH-17144. - // tests.PodToRemoteNodePort(), - // tests.PodToLocalNodePort(), - tests.PodToHost(), - tests.PodToExternalWorkload(), - ) - - // This policy only allows ingress into client from client2. - ct.NewTest("client-ingress").WithCiliumPolicy(clientIngressFromClient2PolicyYAML). - WithScenarios( - tests.ClientToClient(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") { - return check.ResultOK, check.ResultOK - } - return check.ResultOK, check.ResultDefaultDenyIngressDrop - }) - - // Run a simple test with k8s Network Policy. - ct.NewTest("client-ingress-knp").WithK8SPolicy(clientIngressFromClient2PolicyKNPYAML). - WithScenarios( - tests.ClientToClient(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") { - return check.ResultOK, check.ResultOK - } - return check.ResultOK, check.ResultDefaultDenyIngressDrop - }) - - // This policy allows traffic pod to pod and checks if the metric cilium_forward_count_total increases on cilium agent. - ct.NewTest("allow-all-with-metrics-check"). - WithScenarios( - tests.PodToPod(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultOK.ExpectMetricsIncrease(ct.CiliumAgentMetrics(), "cilium_forward_count_total"), - check.ResultOK.ExpectMetricsIncrease(ct.CiliumAgentMetrics(), "cilium_forward_count_total") - }) - - // This policy denies all ingresses by default. - // - // 1. Pod to Pod fails because there is no egress policy (so egress traffic originating from a pod is allowed), - // but then at the destination there is ingress policy that denies the traffic. - // 2. Egress to world works because there is no egress policy (so egress traffic originating from a pod is allowed), - // then when replies come back, they are considered as "replies" to the outbound connection. - // so they are not subject to ingress policy. - allIngressDenyScenarios := []check.Scenario{tests.PodToPod(), tests.PodToCIDR(tests.WithRetryAll())} - ct.NewTest("all-ingress-deny").WithCiliumPolicy(denyAllIngressPolicyYAML). - WithScenarios(allIngressDenyScenarios...). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || - a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { - return check.ResultOK, check.ResultNone - } - return check.ResultDrop, check.ResultDefaultDenyIngressDrop - }) - - if ct.Params().IncludeUnsafeTests { - ct.NewTest("all-ingress-deny-from-outside").WithCiliumPolicy(denyAllIngressPolicyYAML). - WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). - WithIPRoutesFromOutsideToPodCIDRs(). - WithScenarios(tests.FromCIDRToPod()). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || - a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { - return check.ResultOK, check.ResultNone - } - return check.ResultDrop, check.ResultDefaultDenyIngressDrop - }) - } - - // This policy denies all ingresses by default - ct.NewTest("all-ingress-deny-knp").WithK8SPolicy(denyAllIngressPolicyKNPYAML). - WithScenarios( - // Pod to Pod fails because there is no egress policy (so egress traffic originating from a pod is allowed), - // but then at the destination there is ingress policy that denies the traffic. - tests.PodToPod(), - // Egress to world works because there is no egress policy (so egress traffic originating from a pod is allowed), - // then when replies come back, they are considered as "replies" to the outbound connection. - // so they are not subject to ingress policy. - tests.PodToCIDR(tests.WithRetryAll()), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP || - a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { - return check.ResultOK, check.ResultNone - } - return check.ResultDrop, check.ResultDefaultDenyIngressDrop - }) - - // This policy denies all egresses by default - ct.NewTest("all-egress-deny").WithCiliumPolicy(denyAllEgressPolicyYAML). - WithScenarios( - tests.PodToPod(), - tests.PodToPodWithEndpoints(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // This policy denies all egresses by default using KNP. - ct.NewTest("all-egress-deny-knp").WithK8SPolicy(denyAllEgressPolicyKNPYAML). - WithScenarios( - tests.PodToPod(), - tests.PodToPodWithEndpoints(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // This policy denies all entities by default - ct.NewTest("all-entities-deny").WithCiliumPolicy(denyAllEntitiesPolicyYAML). - WithScenarios( - tests.PodToPod(), - tests.PodToCIDR(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - }) - - // This policy allows cluster entity - ct.NewTest("cluster-entity").WithCiliumPolicy(allowClusterEntityPolicyYAML). - WithScenarios( - // Only enable to local cluster for now due to the below - // https://github.com/cilium/cilium/blob/88c4dddede2a3b5b9a7339c1316a0dedd7229a26/pkg/policy/api/entity.go#L126 - tests.PodToPod(tests.WithDestinationLabelsOption(map[string]string{"name": "echo-same-node"})), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultOK, check.ResultOK - }) - - if ct.Params().MultiCluster != "" { - ct.NewTest("cluster-entity-multi-cluster").WithCiliumPolicy(allowClusterEntityPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithDestinationLabelsOption(map[string]string{"name": "echo-other-node"})), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - } - - // This policy allows egress traffic towards the host entity - ct.NewTest("host-entity-egress").WithCiliumPolicy(allowHostEntityEgressPolicyYAML). - WithScenarios( - tests.PodToHost(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultOK, check.ResultNone - }) - - // This policy allows ingress traffic from the host entity - ct.NewTest("host-entity-ingress").WithCiliumPolicy(allowHostEntityIngressPolicyYAML). - WithScenarios( - tests.HostToPod(), - ) - - // This policy allows ingress to echo only from client with a label 'other:client'. - echoIngressScenarios := []check.Scenario{tests.PodToPod()} - ct.NewTest("echo-ingress").WithCiliumPolicy(echoIngressFromOtherClientPolicyYAML). - WithScenarios(echoIngressScenarios...). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { - // TCP handshake fails both in egress and ingress when - // L3(/L4) policy drops at either location. - return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout - } - return check.ResultOK, check.ResultOK - }) - - if ct.Params().IncludeUnsafeTests { - ct.NewTest("echo-ingress-from-outside").WithCiliumPolicy(echoIngressFromOtherClientPolicyYAML). - WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). - WithIPRoutesFromOutsideToPodCIDRs(). - WithScenarios(tests.FromCIDRToPod()). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { - // TCP handshake fails both in egress and ingress when - // L3(/L4) policy drops at either location. - return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout - } - return check.ResultOK, check.ResultOK - }) - } - - // This k8s policy allows ingress to echo only from client with a label 'other:client'. - ct.NewTest("echo-ingress-knp").WithK8SPolicy(echoIngressFromOtherClientPolicyKNPYAML). - WithScenarios( - tests.PodToPod(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && !a.Source().HasLabel("other", "client") { - // TCP handshake fails both in egress and ingress when - // L3(/L4) policy drops at either location. - return check.ResultDropCurlTimeout, check.ResultDropCurlTimeout - } - return check.ResultOK, check.ResultOK - }) - - // This policy allowed ICMP traffic from client to another client. - ct.NewTest("client-ingress-icmp").WithCiliumPolicy(echoIngressICMPPolicyYAML). - WithFeatureRequirements(features.RequireEnabled(features.ICMPPolicy)). - WithScenarios( - tests.ClientToClient(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") { - return check.ResultOK, check.ResultOK - } - return check.ResultOK, check.ResultDefaultDenyIngressDrop - }) - - // This policy allows port 8080 from client to echo, so this should succeed - ct.NewTest("client-egress").WithCiliumPolicy(clientEgressToEchoPolicyYAML). - WithScenarios( - tests.PodToPod(), - ) - - // This policy allows port 8080 from client to echo, so this should succeed - ct.NewTest("client-egress-knp").WithK8SPolicy(clientEgressToEchoPolicyKNPYAML). - WithScenarios( - tests.PodToPod(), - ) - - // This policy allows port 8080 from client to echo (using label match expression, so this should succeed - ct.NewTest("client-egress-expression").WithCiliumPolicy(clientEgressToEchoExpressionPolicyYAML). - WithScenarios( - tests.PodToPod(), - ) - - // This policy allows port 8080 from client to echo (using label match expression, so this should succeed - ct.NewTest("client-egress-expression-knp").WithK8SPolicy(clientEgressToEchoExpressionPolicyKNPYAML). - WithScenarios( - tests.PodToPod(), - ) - - // This policy allows port 8080 from client with service account label to echo - ct.NewTest("client-with-service-account-egress-to-echo").WithCiliumPolicy(clientWithServiceAccountEgressToEchoPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"kind": "client"})), - ) - - // This policy allows port 8080 from client to endpoint with service account label as echo-same-node - ct.NewTest("client-egress-to-echo-service-account").WithCiliumPolicy(clientEgressToEchoServiceAccountPolicyYAML). - WithScenarios( - tests.PodToPod( - tests.WithSourceLabelsOption(map[string]string{"kind": "client"}), - )). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("name", "echo-same-node") { - return check.ResultOK, check.ResultOK - } - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // This policy allows UDP to kube-dns and port 80 TCP to all 'world' endpoints. - ct.NewTest("to-entities-world").WithCiliumPolicy(clientEgressToEntitiesWorldPolicyYAML). - WithScenarios( - tests.PodToWorld(tests.WithRetryDestPort(80)), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Port() == 80 { - return check.ResultOK, check.ResultNone - } - // PodToWorld traffic to port 443 will be dropped by the policy - return check.ResultDropCurlTimeout, check.ResultNone - }) - - // This policy allows L3 traffic to ExternalCIDR/24 (including ExternalIP), with the - // exception of ExternalOtherIP. - ct.NewTest("to-cidr-external"). - WithCiliumPolicy(renderedTemplates["clientEgressToCIDRExternalPolicyYAML"]). - WithScenarios( - tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.IPFamilyV4) == ct.Params().ExternalOtherIP { - // Expect packets for ExternalOtherIP to be dropped. - return check.ResultDropCurlTimeout, check.ResultNone - } - return check.ResultOK, check.ResultNone - }) - - // This policy allows L3 traffic to ExternalCIDR/24 (including ExternalIP), with the - // exception of ExternalOtherIP. - ct.NewTest("to-cidr-external-knp"). - WithK8SPolicy(renderedTemplates["clientEgressToCIDRExternalPolicyKNPYAML"]). - WithScenarios( - tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.IPFamilyV4) == ct.Params().ExternalOtherIP { - // Expect packets for ExternalOtherIP to be dropped. - return check.ResultDropCurlTimeout, check.ResultNone - } - return check.ResultOK, check.ResultNone - }) - - if ct.Params().IncludeUnsafeTests { - ct.NewTest("from-cidr-host-netns"). - WithFeatureRequirements(features.RequireEnabled(features.NodeWithoutCilium)). - WithCiliumPolicy(renderedTemplates["echoIngressFromCIDRYAML"]). - WithIPRoutesFromOutsideToPodCIDRs(). - WithScenarios( - tests.FromCIDRToPod(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultOK, check.ResultNone - }) - } - - // Tests with deny policy - ct.NewTest("echo-ingress-from-other-client-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(echoIngressFromOtherClientDenyPolicyYAML). // Deny other client contact echo - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be allowed - tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be denied - tests.ClientToClient(), // Client to client should be allowed - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && - a.Destination().HasLabel("kind", "echo") { - return check.ResultDrop, check.ResultPolicyDenyIngressDrop - } - return check.ResultOK, check.ResultOK - }) - - // This policy denies ICMP ingress to client only from other client - ct.NewTest("client-ingress-from-other-client-icmp-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(echoIngressICMPDenyPolicyYAML). // Deny ICMP traffic from client to another client - WithFeatureRequirements(features.RequireEnabled(features.ICMPPolicy)). - WithScenarios( - tests.PodToPod(), // Client to echo traffic should be allowed - tests.ClientToClient(), // Client to client traffic should be denied - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && - a.Destination().HasLabel("kind", "client") { - return check.ResultDrop, check.ResultPolicyDenyIngressDrop - } - return check.ResultOK, check.ResultNone - }) - - // This policy denies port 8080 from client to echo - ct.NewTest("client-egress-to-echo-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(clientEgressToEchoDenyPolicyYAML). // Deny client to echo traffic via port 8080 - WithScenarios( - tests.ClientToClient(), // Client to client traffic should be allowed - tests.PodToPod(), // Client to echo traffic should be denied - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("kind", "client") && - a.Destination().HasLabel("kind", "echo") && - a.Destination().Port() == 8080 { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - return check.ResultOK, check.ResultNone - }) - - // This policy denies port http-8080 from client to echo, but allows traffic from client2 to echo - ct.NewTest("client-ingress-to-echo-named-port-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(clientEgressToEchoDenyNamedPortPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be denied - tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be allowed - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && - a.Source().HasLabel("name", "client") { - return check.ResultDropCurlTimeout, check.ResultPolicyDenyIngressDrop - } - return check.ResultOK, check.ResultOK - }) - - // This policy denies port 8080 from client to echo (using label match expression), but allows traffic from client2 - ct.NewTest("client-egress-to-echo-expression-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(clientEgressToEchoExpressionDenyPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(clientLabel)), // Client to echo should be denied - tests.PodToPod(tests.WithSourceLabelsOption(client2Label)), // Client2 to echo should be allowed - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && - a.Source().HasLabel("name", "client") { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - return check.ResultOK, check.ResultOK - }) - - // This policy denies port 8080 from client with service account selector to echo, but not from client2 - ct.NewTest("client-with-service-account-egress-to-echo-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(clientWithServiceAccountEgressToEchoDenyPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client"})), // Client to echo should be denied - tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client2"})), // Client2 to echo should be allowed - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("kind", "echo") && - a.Source().HasLabel("name", "client") { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - return check.ResultOK, check.ResultOK - }) - - // This policy denies port 8080 from client to endpoint with service account, but not from client2 - ct.NewTest("client-egress-to-echo-service-account-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(allowAllIngressPolicyYAML). // Allow all ingress traffic - WithCiliumPolicy(clientEgressToEchoServiceAccountDenyPolicyYAML). - WithScenarios( - tests.PodToPod(tests.WithSourceLabelsOption(map[string]string{"name": "client"})), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().HasLabel("name", "echo-same-node") { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - return check.ResultOK, check.ResultOK - }) - - // This policy denies L3 traffic to ExternalCIDR except ExternalIP/32 - ct.NewTest("client-egress-to-cidr-deny"). - WithCiliumPolicy(allowAllEgressPolicyYAML). // Allow all egress traffic - WithCiliumPolicy(renderedTemplates["clientEgressToCIDRExternalDenyPolicyYAML"]). - WithScenarios( - tests.PodToCIDR(tests.WithRetryDestIP(ct.Params().ExternalIP)), // Denies all traffic to ExternalOtherIP, but allow ExternalIP - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { - return check.ResultOK, check.ResultNone - } - return check.ResultDrop, check.ResultDrop - }) - - // This test is same as the previous one, but there is no allowed policy. - // The goal is to test default deny policy - ct.NewTest("client-egress-to-cidr-deny-default"). - WithCiliumPolicy(renderedTemplates["clientEgressToCIDRExternalDenyPolicyYAML"]). - WithScenarios( - tests.PodToCIDR(), // Denies all traffic to ExternalOtherIP, but allow ExternalIP - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalOtherIP)) == ct.Params().ExternalOtherIP { - return check.ResultPolicyDenyEgressDrop, check.ResultNone - } - if a.Destination().Address(features.GetIPFamily(ct.Params().ExternalIP)) == ct.Params().ExternalIP { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - } - return check.ResultDrop, check.ResultDrop - }) - - // Health check tests. - ct.NewTest("health"). - WithFeatureRequirements(features.RequireEnabled(features.HealthChecking)). - WithScenarios(tests.CiliumHealth()) - - ct.NewTest("north-south-loadbalancing"). - WithFeatureRequirements(withKPRReqForMultiCluster(ct, - features.RequireEnabled(features.NodeWithoutCilium))...). - WithScenarios( - tests.OutsideToNodePort(), - ) - - if !ct.Params().SingleNode { - // Encryption checks are always executed as a sanity check, asserting whether - // unencrypted packets shall, or shall not, be observed based on the feature set. - ct.NewTest("pod-to-pod-encryption"). - WithScenarios( - tests.PodToPodEncryption(features.RequireEnabled(features.EncryptionPod)), - ) - ct.NewTest("node-to-node-encryption"). - WithScenarios( - tests.NodeToNodeEncryption( - features.RequireEnabled(features.EncryptionPod), - features.RequireEnabled(features.EncryptionNode), - ), - ) - } - - if ct.Params().IncludeUnsafeTests { - ct.NewTest("egress-gateway"). - WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ - Name: "cegp-sample-client", - PodSelectorKind: "client", - }). - WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ - Name: "cegp-sample-echo", - PodSelectorKind: "echo", - }). - WithIPRoutesFromOutsideToPodCIDRs(). - WithFeatureRequirements(features.RequireEnabled(features.EgressGateway), - features.RequireEnabled(features.NodeWithoutCilium)). - WithScenarios( - tests.EgressGateway(), - ) - } - - if versioncheck.MustCompile(">=1.14.0")(ct.CiliumVersion) { - ct.NewTest("egress-gateway-excluded-cidrs"). - WithCiliumEgressGatewayPolicy(check.CiliumEgressGatewayPolicyParams{ - Name: "cegp-sample-client", - PodSelectorKind: "client", - ExcludedCIDRsConf: check.ExternalNodeExcludedCIDRs, - }). - WithFeatureRequirements(features.RequireEnabled(features.EgressGateway), - features.RequireEnabled(features.NodeWithoutCilium)). - WithScenarios( - tests.EgressGatewayExcludedCIDRs(), - ) - } - - // Check that pods can access nodes when referencing them by CIDR selectors - // (when this feature is enabled). - ct.NewTest("pod-to-node-cidrpolicy"). - WithFeatureRequirements( - features.RequireEnabled(features.CIDRMatchNodes)). - WithK8SPolicy(renderedTemplates["clientEgressToCIDRNodeKNPYAML"]). - WithScenarios( - tests.PodToHost(), - ) - - // The following tests have DNS redirect policies. They should be executed last. - - ct.NewTest("north-south-loadbalancing-with-l7-policy"). - WithFeatureRequirements(withKPRReqForMultiCluster(ct, - features.RequireEnabled(features.NodeWithoutCilium), - features.RequireEnabled(features.L7Proxy))...). - WithCiliumVersion(">1.13.2"). - WithCiliumPolicy(echoIngressL7HTTPFromAnywherePolicyYAML). - WithScenarios( - tests.OutsideToNodePort(), - ) - - // Test L7 HTTP introspection using an ingress policy on echo pods. - ct.NewTest("echo-ingress-l7"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(echoIngressL7HTTPPolicyYAML). // L7 allow policy with HTTP introspection - WithScenarios( - tests.PodToPodWithEndpoints(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") { // Only client2 is allowed to make HTTP calls. - // Trying to access private endpoint without "secret" header set - // should lead to a drop. - if a.Destination().Path() == "/private" && !a.Destination().HasLabel("X-Very-Secret-Token", "42") { - return check.ResultDropCurlHTTPError, check.ResultNone - } - egress = check.ResultOK - // Expect all curls from client2 to be proxied and to be GET calls. - egress.HTTP = check.HTTP{ - Method: "GET", - } - return egress, check.ResultNone - } - return check.ResultDrop, check.ResultDefaultDenyIngressDrop - }) - - // Test L7 HTTP introspection using an ingress policy on echo pods. - ct.NewTest("echo-ingress-l7-named-port"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(echoIngressL7HTTPNamedPortPolicyYAML). // L7 allow policy with HTTP introspection (named port) - WithScenarios( - tests.PodToPodWithEndpoints(), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") { // Only client2 is allowed to make HTTP calls. - // Trying to access private endpoint without "secret" header set - // should lead to a drop. - if a.Destination().Path() == "/private" && !a.Destination().HasLabel("X-Very-Secret-Token", "42") { - return check.ResultDropCurlHTTPError, check.ResultNone - } - egress = check.ResultOK - // Expect all curls from client2 to be proxied and to be GET calls. - egress.HTTP = check.HTTP{ - Method: "GET", - } - return egress, check.ResultNone - } - return check.ResultDrop, check.ResultDefaultDenyIngressDrop - }) - - // Test L7 HTTP with different methods introspection using an egress policy on the clients. - ct.NewTest("client-egress-l7-method"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only - WithCiliumPolicy(clientEgressL7HTTPMethodPolicyYAML). // L7 allow policy with HTTP introspection (POST only) - WithScenarios( - tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithDestinationLabelsOption(map[string]string{"other": "echo"})), - tests.PodToPodWithEndpoints(tests.WithDestinationLabelsOption(map[string]string{"first": "echo"})), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. - (a.Destination().Port() == 8080) { // port 8080 is traffic to echo Pod. - if a.Destination().HasLabel("other", "echo") { //we are POSTing only other echo - egress = check.ResultOK - - egress.HTTP = check.HTTP{ - Method: "POST", - } - return egress, check.ResultNone - } - // Else expect HTTP drop by proxy - return check.ResultDropCurlHTTPError, check.ResultNone - } - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // Test L7 HTTP introspection using an egress policy on the clients. - ct.NewTest("client-egress-l7"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only - WithCiliumPolicy(renderedTemplates["clientEgressL7HTTPPolicyYAML"]). // L7 allow policy with HTTP introspection - WithScenarios( - tests.PodToPod(), - tests.PodToWorld(tests.WithRetryDestPort(80), tests.WithRetryPodLabel("other", "client")), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. - // Outbound HTTP to set domain-name defaults to one.one.one.one is L7-introspected and allowed. - (a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(ct.Params().ExternalTarget)) == ct.Params().ExternalTarget || - a.Destination().Port() == 8080) { // 8080 is traffic to echo Pod. - if a.Destination().Path() == "/" || a.Destination().Path() == "" { - egress = check.ResultOK - // Expect all curls from client2 to be proxied and to be GET calls. - egress.HTTP = check.HTTP{ - Method: "GET", - } - return egress, check.ResultNone - } - // Else expect HTTP drop by proxy - return check.ResultDNSOKDropCurlHTTPError, check.ResultNone - } - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // Test L7 HTTP named port introspection using an egress policy on the clients. - ct.NewTest("client-egress-l7-named-port"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only - WithCiliumPolicy(renderedTemplates["clientEgressL7HTTPNamedPortPolicyYAML"]). // L7 allow policy with HTTP introspection (named port) - WithScenarios( - tests.PodToPod(), - tests.PodToWorld(tests.WithRetryDestPort(80), tests.WithRetryPodLabel("other", "client")), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && // Only client2 is allowed to make HTTP calls. - // Outbound HTTP to domain-name, default one.one.one.one, is L7-introspected and allowed. - (a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(ct.Params().ExternalTarget)) == ct.Params().ExternalTarget || - a.Destination().Port() == 8080) { // named port http-8080 is traffic to echo Pod. - if a.Destination().Path() == "/" || a.Destination().Path() == "" { - egress = check.ResultOK - // Expect all curls from client2 to be proxied and to be GET calls. - egress.HTTP = check.HTTP{ - Method: "GET", - } - return egress, check.ResultNone - } - // Else expect HTTP drop by proxy - return check.ResultDNSOKDropCurlHTTPError, check.ResultNone - } - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // Test L7 HTTPS interception using an egress policy on the clients. - // Fail to load site due to missing headers. - ct.NewTest("client-egress-l7-tls-deny-without-headers"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). - WithCABundleSecret(). - WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). - WithCiliumPolicy(renderedTemplates["clientEgressL7TLSPolicyYAML"]). // L7 allow policy with TLS interception - WithScenarios( - tests.PodToWorldWithTLSIntercept(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultDropCurlHTTPError, check.ResultNone - }) - - // Test L7 HTTPS interception using an egress policy on the clients. - ct.NewTest("client-egress-l7-tls-headers"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). - WithCABundleSecret(). - WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). - WithCiliumPolicy(renderedTemplates["clientEgressL7TLSPolicyYAML"]). // L7 allow policy with TLS interception - WithScenarios( - tests.PodToWorldWithTLSIntercept("-H", "X-Very-Secret-Token: 42"), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultOK, check.ResultNone - }) - - // Test L7 HTTP with a header replace set in the policy - ct.NewTest("client-egress-l7-set-header"). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithFeatureRequirements(features.RequireEnabled(features.SecretBackendK8s)). - WithSecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "header-match", - }, - Data: map[string][]byte{ - "value": []byte("Bearer 123456"), - }, - }). - WithCiliumPolicy(renderedTemplates["clientEgressL7HTTPMatchheaderSecretYAML"]). // L7 allow policy with HTTP introspection (POST only) - WithScenarios( - tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"other": "echo"})), - tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"first": "echo"})), - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Source().HasLabel("other", "client") && // Only client2 has the header policy. - (a.Destination().Port() == 8080) { // port 8080 is traffic to echo Pod. - return check.ResultOK, check.ResultNone - } - return check.ResultCurlHTTPError, check.ResultNone // if the header is not set the request will get a 401 - }) - - // Test mutual auth with always-fail - ct.NewTest("echo-ingress-auth-always-fail").WithCiliumPolicy(echoIngressAuthFailPolicyYAML). - // this test is only useful when auth is supported in the Cilium version and it is enabled - // currently this is tested spiffe as that is the only functional auth method - WithFeatureRequirements(features.RequireEnabled(features.AuthSpiffe)). - WithScenarios( - tests.PodToPod(), - ). - WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { - return check.ResultDropCurlTimeout, check.ResultDropAuthRequired - }) - - // Test mutual auth with SPIFFE - ct.NewTest("echo-ingress-mutual-auth-spiffe").WithCiliumPolicy(echoIngressMutualAuthPolicyYAML). - WithFeatureRequirements(features.RequireEnabled(features.AuthSpiffe)). - WithScenarios( - tests.PodToPod(), - ) - - // Test Ingress controller - ct.NewTest("pod-to-ingress-service"). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithScenarios( - tests.PodToIngress(), - ) - - ct.NewTest("pod-to-ingress-service-deny-all"). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithScenarios( - tests.PodToIngress(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - ct.NewTest("pod-to-ingress-service-deny-ingress-identity"). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyIngressIdentityPolicyYAML). - WithScenarios( - tests.PodToIngress(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - ct.NewTest("pod-to-ingress-service-deny-backend-service"). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyIngressBackendPolicyYAML). - WithScenarios( - tests.PodToIngress(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - ct.NewTest("pod-to-ingress-service-allow-ingress-identity"). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithCiliumPolicy(allowIngressIdentityPolicyYAML). - WithScenarios( - tests.PodToIngress(), - ) - - ct.NewTest("outside-to-ingress-service"). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium)). - WithScenarios( - tests.OutsideToIngressService(), - ) - - ct.NewTest("outside-to-ingress-service-deny-world-identity"). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium)). - WithCiliumPolicy(denyWorldIdentityPolicyYAML). - WithScenarios( - tests.OutsideToIngressService(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - ct.NewTest("outside-to-ingress-service-deny-cidr"). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium)). - WithCiliumPolicy(renderedTemplates["denyCIDRPolicyYAML"]). - WithScenarios( - tests.OutsideToIngressService(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - ct.NewTest("outside-to-ingress-service-deny-all-ingress"). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium)). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithScenarios( - tests.OutsideToIngressService(), - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) - - // Only allow UDP:53 to kube-dns, no DNS proxy enabled. - ct.NewTest("dns-only").WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithScenarios( - tests.PodToPod(), // connects to other Pods directly, no DNS - tests.PodToWorld(), // resolves set domain-name defaults to one.one.one.one - ). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDropCurlTimeout, check.ResultNone - }) - - // This policy only allows port 80 to domain-name, default one.one.one.one,. DNS proxy enabled. - ct.NewTest("to-fqdns").WithCiliumPolicy(renderedTemplates["clientEgressToFQDNsCiliumIOPolicyYAML"]). - WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithScenarios( - tests.PodToWorld(tests.WithRetryDestPort(80)), - tests.PodToWorld2(), // resolves cilium.io - ). - WithExpectations(func(a *check.Action) (egress, ingress check.Result) { - if a.Destination().Address(features.IPFamilyAny) == "cilium.io" { - if a.Destination().Path() == "/" || a.Destination().Path() == "" { - egress = check.ResultDNSOK - egress.HTTP = check.HTTP{ - Method: "GET", - URL: "https://cilium.io", - } - // Expect packets for cilium.io / 104.198.14.52 to be dropped. - return check.ResultDropCurlTimeout, check.ResultNone - } - // Else expect HTTP drop by proxy - return check.ResultDNSOKDropCurlHTTPError, check.ResultNone - } - - extTarget := ct.Params().ExternalTarget - if a.Destination().Port() == 80 && a.Destination().Address(features.GetIPFamily(extTarget)) == extTarget { - if a.Destination().Path() == "/" || a.Destination().Path() == "" { - egress = check.ResultDNSOK - egress.HTTP = check.HTTP{ - Method: "GET", - URL: fmt.Sprintf("http://%s/", extTarget), - } - return egress, check.ResultNone - } - // Else expect HTTP drop by proxy - return check.ResultDNSOKDropCurlHTTPError, check.ResultNone - } - // No HTTP proxy on other ports - return check.ResultDNSOKDropCurlTimeout, check.ResultNone - }) - - if ct.Params().K8sLocalHostTest { - ct.NewTest("pod-to-controlplane-host"). - WithCiliumPolicy(clientEgressToEntitiesHostPolicyYAML). - WithScenarios( - tests.PodToControlPlaneHost(), - ) - - ct.NewTest("pod-to-k8s-on-controlplane"). - WithCiliumPolicy(clientEgressToEntitiesK8sPolicyYAML). - WithScenarios( - tests.PodToK8sLocal(), - ) - // Check that pods can access when referencing them by CIDR selectors - // (when this feature is enabled). - ct.NewTest("pod-to-controlplane-host-cidr"). - WithFeatureRequirements( - features.RequireEnabled(features.CIDRMatchNodes)). - WithK8SPolicy(renderedTemplates["clientEgressToCIDRCPHostPolicyYAML"]). - WithScenarios( - tests.PodToControlPlaneHost(), - ) - - ct.NewTest("pod-to-k8s-on-controlplane-cidr"). - WithFeatureRequirements( - features.RequireEnabled(features.CIDRMatchNodes)). - WithCiliumPolicy(renderedTemplates["clientEgressToCIDRK8sPolicyKNPYAML"]). - WithScenarios( - tests.PodToK8sLocal(), - ) - } - - // Tests with DNS redirects to the proxy (e.g., client-egress-l7, dns-only, - // and to-fqdns) should always be executed last. See #367 for details. - - if err := extra.AddConnectivityTests(ct); err != nil { + extraTests := func(ct *check.ConnectivityTest) error { return extra.AddConnectivityTests(ct) } + if err := factory.InjectTests(ct, extraTests); err != nil { return err } - if versioncheck.MustCompile(">=1.14.0")(ct.CiliumVersion) || ct.Params().IncludeUnsafeTests { - ct.NewTest("check-log-errors"). - WithSysdumpPolicy(check.SysdumpPolicyOnce). - WithScenarios(tests.NoErrorsInLogs(ct.CiliumVersion)) - } - return ct.Run(ctx) } - -func withKPRReqForMultiCluster(ct *check.ConnectivityTest, reqs ...features.Requirement) []features.Requirement { - // Skip the nodeport-related tests in the multicluster scenario if KPR is not - // enabled, since global nodeport services are not supported in that case. - if ct.Params().MultiCluster != "" { - reqs = append(reqs, features.RequireEnabled(features.KPRNodePort)) - } - return reqs -}