From e484ca8ac480ca58bb74406ff09235a46dfdb8ac Mon Sep 17 00:00:00 2001 From: Maartje Eyskens Date: Wed, 22 Mar 2023 13:48:28 +0100 Subject: [PATCH] Add connectivity tests for auth This adds tests to validate that the auth handling in policy is working. These tests will only run on clusters with auth enabled on Cilium v1.14.0+. It uses the always-fail type to test the fail case. It will also perfom a successful test run with mTLS-SPIFFE when enabled. Signed-off-by: Maartje Eyskens --- connectivity/check/features.go | 6 +++++ connectivity/check/policy.go | 10 +++++++ .../manifests/echo-ingress-auth-fail.yaml | 21 +++++++++++++++ connectivity/manifests/echo-ingress-mtls.yaml | 21 +++++++++++++++ connectivity/suite.go | 27 +++++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 connectivity/manifests/echo-ingress-auth-fail.yaml create mode 100644 connectivity/manifests/echo-ingress-mtls.yaml diff --git a/connectivity/check/features.go b/connectivity/check/features.go index 6e9aa4513d..7bfe492a03 100644 --- a/connectivity/check/features.go +++ b/connectivity/check/features.go @@ -59,6 +59,8 @@ const ( FeatureCNP Feature = "cilium-network-policy" FeatureKNP Feature = "k8s-network-policy" + + FeatureAuthMTLSSpiffe Feature = "auth-mtls-spiffe" ) // FeatureStatus describes the status of a feature. Some features are either @@ -199,6 +201,10 @@ func (ct *ConnectivityTest) extractFeaturesFromConfigMap(ctx context.Context, cl Enabled: cm.Data["enable-endpoint-routes"] == "true", } + result[FeatureAuthMTLSSpiffe] = FeatureStatus{ + Enabled: cm.Data["mesh-auth-mtls-enabled"] == "true", + } + return nil } diff --git a/connectivity/check/policy.go b/connectivity/check/policy.go index 75156fe4b5..f9c30d2c80 100644 --- a/connectivity/check/policy.go +++ b/connectivity/check/policy.go @@ -202,6 +202,10 @@ func defaultDenyReason(flow *flowpb.Flow) bool { return flow.GetDropReasonDesc() == flowpb.DropReason_POLICY_DENIED } +func authRequiredDropReason(flow *flowpb.Flow) bool { + return flow.GetDropReasonDesc() == flowpb.DropReason_AUTH_REQUIRED +} + var ( // ResultNone expects a successful command, don't match any packets. ResultNone = Result{ @@ -248,6 +252,12 @@ var ( DropReasonFunc: defaultDropReason, } + // ResultDropAuthRequired expects a dropped flow with auth required as reason. + ResultDropAuthRequired = Result{ + Drop: true, + DropReasonFunc: authRequiredDropReason, + } + // ResultAnyReasonEgressDrop expects a dropped flow at Egress and a failed command. ResultAnyReasonEgressDrop = Result{ Drop: true, diff --git a/connectivity/manifests/echo-ingress-auth-fail.yaml b/connectivity/manifests/echo-ingress-auth-fail.yaml new file mode 100644 index 0000000000..7b4389598f --- /dev/null +++ b/connectivity/manifests/echo-ingress-auth-fail.yaml @@ -0,0 +1,21 @@ + +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: auth-ingress-fail + namespace: cilium-test +spec: + description: "Allow other client to contact echo but fail on auth" + endpointSelector: + matchLabels: + kind: echo + ingress: + - fromEndpoints: + - matchLabels: + kind: client + toPorts: + - ports: + - port: "8080" + protocol: TCP + auth: + type: always-fail diff --git a/connectivity/manifests/echo-ingress-mtls.yaml b/connectivity/manifests/echo-ingress-mtls.yaml new file mode 100644 index 0000000000..3b3f22317c --- /dev/null +++ b/connectivity/manifests/echo-ingress-mtls.yaml @@ -0,0 +1,21 @@ + +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: auth-ingress + namespace: cilium-test +spec: + description: "Allow other client to contact echo after mTLS" + endpointSelector: + matchLabels: + kind: echo + ingress: + - fromEndpoints: + - matchLabels: + kind: client + toPorts: + - ports: + - port: "8080" + protocol: TCP + auth: + type: mtls-spiffe diff --git a/connectivity/suite.go b/connectivity/suite.go index dae890c760..a3facf6efa 100644 --- a/connectivity/suite.go +++ b/connectivity/suite.go @@ -135,6 +135,12 @@ var ( //go:embed manifests/echo-ingress-icmp-deny.yaml echoIngressICMPDenyPolicyYAML string + + //go:embed manifests/echo-ingress-auth-fail.yaml + echoIngressAuthFailPolicyYAML string + + //go:embed manifests/echo-ingress-mtls.yaml + echoIngressMTLSPolicyYAML string ) var ( @@ -824,6 +830,27 @@ func Run(ctx context.Context, ct *check.ConnectivityTest) error { return check.ResultCurlHTTPError, check.ResultNone // if the header is not set the request will get a 401 }) + // Test mTLS 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 my mtls-spiffe as that is the only functional auth method + WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureAuthMTLSSpiffe)). + WithScenarios( + tests.PodToPod(), + tests.PodToPodWithEndpoints(), + ). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + return check.ResultDropCurlTimeout, check.ResultDropAuthRequired + }) + + // Test mTLS auth with SPIFFE + ct.NewTest("echo-ingress-auth-mtls-spiffe").WithCiliumPolicy(echoIngressMTLSPolicyYAML). + WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureAuthMTLSSpiffe)). + WithScenarios( + tests.PodToPod(), + tests.PodToPodWithEndpoints(), + ) + // Only allow UDP:53 to kube-dns, no DNS proxy enabled. ct.NewTest("dns-only").WithCiliumPolicy(clientEgressOnlyDNSPolicyYAML). WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).