From ac518d3d2f08e92eb4444d6454c5c7517a6679a3 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. It uses the always-fail type to test the fail case. If mTLS-SPIFFE is enabled in the cluster it will also perfom a successful test run with mTLS enabled. Signed-off-by: Maartje Eyskens --- connectivity/check/features.go | 6 +++++ connectivity/check/policy.go | 11 +++++++++ .../manifests/echo-ingress-auth-fail.yaml | 21 ++++++++++++++++ connectivity/manifests/echo-ingress-mtls.yaml | 21 ++++++++++++++++ connectivity/suite.go | 24 +++++++++++++++++++ 5 files changed, 83 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 f6027fa1e2..35de7ee37a 100644 --- a/connectivity/check/features.go +++ b/connectivity/check/features.go @@ -53,6 +53,8 @@ const ( FeatureFlavor Feature = "flavor" FeatureSecretBackendK8s Feature = "secret-backend-k8s" + + FeatureAuthMTLSSpiffe Feature = "auth-mtls-spiffe" ) // FeatureStatus describes the status of a feature. Some features are either @@ -193,6 +195,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 a2960a8732..62ae8f4e28 100644 --- a/connectivity/check/policy.go +++ b/connectivity/check/policy.go @@ -151,6 +151,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{ @@ -197,6 +201,13 @@ var ( DropReasonFunc: defaultDropReason, } + // ResultDropAuthRequired expects a dropped flow with auth required as reason. + ResultDropAuthRequired = Result{ + Drop: true, + // IngressDrop: 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 e14c641654..1a7ffa7719 100644 --- a/connectivity/suite.go +++ b/connectivity/suite.go @@ -114,6 +114,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 ( @@ -728,6 +734,24 @@ 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").WithPolicy(echoIngressAuthFailPolicyYAML). + 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").WithPolicy(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").WithPolicy(clientEgressOnlyDNSPolicyYAML). WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).