From 9dbe002693116154b8085de4ea802ad6eb9db8fc Mon Sep 17 00:00:00 2001 From: Chris Burns <29541485+ChrisJBurns@users.noreply.github.com> Date: Tue, 18 Nov 2025 21:48:55 +0000 Subject: [PATCH] ports inline oidc config auth-configmap e2e test to int test Signed-off-by: Chris Burns <29541485+ChrisJBurns@users.noreply.github.com> --- .../mcpserver_runconfig_integration_test.go | 110 +++++++++++ .../assert-mcpserver-pod-running.yaml | 9 - .../assert-mcpserver-running.yaml | 7 - .../auth-configmap/chainsaw-test.yaml | 172 ------------------ .../auth-configmap/mcpserver-auth.yaml | 34 ---- 5 files changed, 110 insertions(+), 222 deletions(-) delete mode 100644 test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-pod-running.yaml delete mode 100644 test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-running.yaml delete mode 100644 test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/chainsaw-test.yaml delete mode 100644 test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/mcpserver-auth.yaml diff --git a/cmd/thv-operator/test-integration/mcp-server/mcpserver_runconfig_integration_test.go b/cmd/thv-operator/test-integration/mcp-server/mcpserver_runconfig_integration_test.go index 10aad7dc0..1f4c597d3 100644 --- a/cmd/thv-operator/test-integration/mcp-server/mcpserver_runconfig_integration_test.go +++ b/cmd/thv-operator/test-integration/mcp-server/mcpserver_runconfig_integration_test.go @@ -547,5 +547,115 @@ var _ = Describe("RunConfig ConfigMap Integration Tests", func() { Expect(runConfig.CmdArgs).To(Equal([]string{"--arg1", "--arg2", "--arg3"})) Expect(runConfig.ToolsFilter).To(Equal([]string{"tool3", "tool1", "tool2"})) }) + + It("Should handle MCPServer with OIDC authentication configuration", func() { + namespace := "oidc-test-ns" + mcpServerName := "oidc-server" + configMapName := mcpServerName + "-runconfig" + + // Create namespace + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + _ = k8sClient.Create(ctx, ns) + + // Create MCPServer with OIDC configuration + mcpServer := &mcpv1alpha1.MCPServer{ + ObjectMeta: metav1.ObjectMeta{ + Name: mcpServerName, + Namespace: namespace, + }, + Spec: mcpv1alpha1.MCPServerSpec{ + Image: "auth/mcp-server:latest", + Transport: "stdio", + ProxyPort: 8080, + OIDCConfig: &mcpv1alpha1.OIDCConfigRef{ + Type: "inline", + Inline: &mcpv1alpha1.InlineOIDCConfig{ + Issuer: "https://auth.example.com", + Audience: "toolhive-api", + JWKSURL: "https://auth.example.com/.well-known/jwks.json", + IntrospectionURL: "https://auth.example.com/oauth/introspect", + ClientID: "toolhive-client", + ClientSecret: "secret123", + JWKSAllowPrivateIP: true, + }, + }, + }, + } + + Expect(k8sClient.Create(ctx, mcpServer)).Should(Succeed()) + defer k8sClient.Delete(ctx, mcpServer) + + // Wait for ConfigMap to be created + configMap := &corev1.ConfigMap{} + Eventually(func() error { + return k8sClient.Get(ctx, types.NamespacedName{ + Name: configMapName, + Namespace: namespace, + }, configMap) + }, timeout, interval).Should(Succeed()) + + // Verify ConfigMap has the expected label + Expect(configMap.Labels).To(HaveKeyWithValue("toolhive.stacklok.io/mcp-server", mcpServerName)) + + // Verify ConfigMap data contains runconfig.json + Expect(configMap.Data).To(HaveKey("runconfig.json")) + runConfigJSON := configMap.Data["runconfig.json"] + Expect(runConfigJSON).NotTo(BeEmpty()) + + // Parse and verify RunConfig content + var runConfig runner.RunConfig + err := json.Unmarshal([]byte(runConfigJSON), &runConfig) + Expect(err).NotTo(HaveOccurred()) + + // Verify OIDC configuration + Expect(runConfig.OIDCConfig).NotTo(BeNil()) + Expect(runConfig.OIDCConfig.Issuer).To(Equal("https://auth.example.com")) + Expect(runConfig.OIDCConfig.Audience).To(Equal("toolhive-api")) + Expect(runConfig.OIDCConfig.JWKSURL).To(Equal("https://auth.example.com/.well-known/jwks.json")) + Expect(runConfig.OIDCConfig.IntrospectionURL).To(Equal("https://auth.example.com/oauth/introspect")) + Expect(runConfig.OIDCConfig.ClientID).To(Equal("toolhive-client")) + Expect(runConfig.OIDCConfig.ClientSecret).To(Equal("secret123")) + Expect(runConfig.OIDCConfig.AllowPrivateIP).To(BeTrue()) + + // Verify fields that should be empty/nil + Expect(runConfig.OIDCConfig.CACertPath).To(BeEmpty()) + Expect(runConfig.OIDCConfig.AuthTokenFile).To(BeEmpty()) + + // Verify middleware_configs includes auth middleware + Expect(runConfig.MiddlewareConfigs).NotTo(BeEmpty()) + + // Find the auth middleware + authMiddlewareFound := false + for _, middleware := range runConfig.MiddlewareConfigs { + if middleware.Type == "auth" { + authMiddlewareFound = true + + // Verify auth middleware has the OIDC config + var params map[string]interface{} + err := json.Unmarshal(middleware.Parameters, ¶ms) + Expect(err).NotTo(HaveOccurred(), "Failed to unmarshal auth middleware parameters") + + if oidcConfigMap, exists := params["oidc_config"]; exists && oidcConfigMap != nil { + oidcConfig, ok := oidcConfigMap.(map[string]interface{}) + Expect(ok).To(BeTrue(), "oidc_config should be a map") + Expect(oidcConfig["Issuer"]).To(Equal("https://auth.example.com")) + Expect(oidcConfig["Audience"]).To(Equal("toolhive-api")) + Expect(oidcConfig["JWKSURL"]).To(Equal("https://auth.example.com/.well-known/jwks.json")) + Expect(oidcConfig["IntrospectionURL"]).To(Equal("https://auth.example.com/oauth/introspect")) + Expect(oidcConfig["ClientID"]).To(Equal("toolhive-client")) + Expect(oidcConfig["ClientSecret"]).To(Equal("secret123")) + Expect(oidcConfig["AllowPrivateIP"]).To(BeTrue()) + } else { + Fail("OIDC config not found in auth middleware parameters") + } + break + } + } + Expect(authMiddlewareFound).To(BeTrue(), "Auth middleware should be present in middleware_configs") + }) }) }) diff --git a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-pod-running.yaml b/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-pod-running.yaml deleted file mode 100644 index 028e1793d..000000000 --- a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-pod-running.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - namespace: toolhive-system - labels: - app: mcpserver - app.kubernetes.io/instance: auth-configmap-test -status: - phase: Running \ No newline at end of file diff --git a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-running.yaml b/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-running.yaml deleted file mode 100644 index 45a9d9ed1..000000000 --- a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/assert-mcpserver-running.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: toolhive.stacklok.dev/v1alpha1 -kind: MCPServer -metadata: - name: auth-configmap-test - namespace: toolhive-system -status: - phase: Running \ No newline at end of file diff --git a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/chainsaw-test.yaml b/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/chainsaw-test.yaml deleted file mode 100644 index 6bde812c1..000000000 --- a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/chainsaw-test.yaml +++ /dev/null @@ -1,172 +0,0 @@ -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: auth-configmap-test -spec: - description: Test that OIDC authentication configuration is correctly generated in ConfigMap - steps: - - name: enable-configmap-mode - try: - - script: - content: | - echo "Setting TOOLHIVE_USE_CONFIGMAP=true on operator deployment..." - - # Use strategic merge patch to add the environment variable to existing env array - kubectl patch deployment toolhive-operator -n toolhive-system --type='strategic' -p='{"spec":{"template":{"spec":{"containers":[{"name":"manager","env":[{"name":"TOOLHIVE_USE_CONFIGMAP","value":"true"}]}]}}}}' - - # Wait for rollout to complete - kubectl rollout status deployment/toolhive-operator -n toolhive-system --timeout=60s - - # Verify the environment variable was set - echo "Verifying TOOLHIVE_USE_CONFIGMAP environment variable is set..." - ENV_VAR=$(kubectl get deployment toolhive-operator -n toolhive-system -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].env[?(@.name=="TOOLHIVE_USE_CONFIGMAP")].value}') - if [ "$ENV_VAR" = "true" ]; then - echo "✓ TOOLHIVE_USE_CONFIGMAP=true verified on operator deployment" - else - echo "✗ Failed to set TOOLHIVE_USE_CONFIGMAP environment variable" - exit 1 - fi - timeout: 120s - - - name: create-mcpserver-with-auth - try: - - apply: - file: mcpserver-auth.yaml - - assert: - file: assert-mcpserver-running.yaml - timeout: 120s - - - name: verify-pod-running - try: - - assert: - file: assert-mcpserver-pod-running.yaml - timeout: 120s - - - name: verify-configmap-oidc-config - try: - - script: - content: | - echo "Verifying ConfigMap OIDC authentication configuration..." - - # Wait for ConfigMap to be created - for i in $(seq 1 10); do - if kubectl get configmap -n toolhive-system -l toolhive.stacklok.io/mcp-server=auth-configmap-test >/dev/null 2>&1; then - echo "✓ ConfigMap exists" - break - fi - echo " Waiting for ConfigMap... (attempt $i/10)" - sleep 2 - done - - # Get the ConfigMap and extract the runconfig.json - CONFIGMAP_JSON=$(kubectl get configmap -n toolhive-system -l toolhive.stacklok.io/mcp-server=auth-configmap-test -o jsonpath='{.items[0].data.runconfig\.json}' 2>/dev/null || echo "") - - if [ -z "$CONFIGMAP_JSON" ]; then - echo "✗ ConfigMap does not contain runconfig.json data" - kubectl get configmap -n toolhive-system -l toolhive.stacklok.io/mcp-server=auth-configmap-test -o yaml - exit 1 - fi - - echo "$CONFIGMAP_JSON" > /tmp/runconfig.json - - # Debug: Show the full ConfigMap content - echo "=== DEBUG: Full runconfig.json content ===" - echo "$CONFIGMAP_JSON" | jq . || echo "$CONFIGMAP_JSON" - echo "=== END DEBUG ===" - - # Verify OIDC configuration is present in runconfig.json - if ! echo "$CONFIGMAP_JSON" | jq -e '.oidc_config' > /dev/null 2>&1; then - echo "✗ oidc_config section not found in runconfig.json" - exit 1 - fi - echo "✓ oidc_config section found" - - # Verify issuer - ISSUER=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.Issuer // empty') - if [ "$ISSUER" != "https://auth.example.com" ]; then - echo "✗ OIDC issuer mismatch. Expected: 'https://auth.example.com', Got: '$ISSUER'" - exit 1 - fi - echo "✓ OIDC issuer verified" - - # Verify audience - AUDIENCE=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.Audience // empty') - if [ "$AUDIENCE" != "toolhive-api" ]; then - echo "✗ OIDC audience mismatch. Expected: 'toolhive-api', Got: '$AUDIENCE'" - exit 1 - fi - echo "✓ OIDC audience verified" - - # Verify JWKS URL - JWKS_URL=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.JWKSURL // empty') - if [ "$JWKS_URL" != "https://auth.example.com/.well-known/jwks.json" ]; then - echo "✗ OIDC JWKS URL mismatch. Expected: 'https://auth.example.com/.well-known/jwks.json', Got: '$JWKS_URL'" - exit 1 - fi - echo "✓ OIDC JWKS URL verified" - - # Verify introspection URL - INTROSPECTION_URL=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.IntrospectionURL // empty') - if [ "$INTROSPECTION_URL" != "https://auth.example.com/oauth/introspect" ]; then - echo "✗ OIDC introspection URL mismatch. Expected: 'https://auth.example.com/oauth/introspect', Got: '$INTROSPECTION_URL'" - exit 1 - fi - echo "✓ OIDC introspection URL verified" - - # Verify client ID - CLIENT_ID=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.ClientID // empty') - if [ "$CLIENT_ID" != "toolhive-client" ]; then - echo "✗ OIDC client ID mismatch. Expected: 'toolhive-client', Got: '$CLIENT_ID'" - exit 1 - fi - echo "✓ OIDC client ID verified" - - # Verify client secret - CLIENT_SECRET=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.ClientSecret // empty') - if [ "$CLIENT_SECRET" != "secret123" ]; then - echo "✗ OIDC client secret mismatch. Expected: 'secret123', Got: '$CLIENT_SECRET'" - exit 1 - fi - echo "✓ OIDC client secret verified" - - # Verify allow private IP - ALLOW_PRIVATE_IP=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.AllowPrivateIP // empty') - if [ "$ALLOW_PRIVATE_IP" != "true" ]; then - echo "✗ OIDC allow private IP mismatch. Expected: 'true', Got: '$ALLOW_PRIVATE_IP'" - exit 1 - fi - echo "✓ OIDC allow private IP verified" - - # Verify CA cert path and auth token file are empty (as noted in unit tests) - CA_CERT_PATH=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.CACertPath // empty') - if [ "$CA_CERT_PATH" != "" ]; then - echo "✗ OIDC CA cert path should be empty. Got: '$CA_CERT_PATH'" - exit 1 - fi - echo "✓ OIDC CA cert path verified (empty as expected)" - - AUTH_TOKEN_FILE=$(echo "$CONFIGMAP_JSON" | jq -r '.oidc_config.AuthTokenFile // empty') - if [ "$AUTH_TOKEN_FILE" != "" ]; then - echo "✗ OIDC auth token file should be empty. Got: '$AUTH_TOKEN_FILE'" - exit 1 - fi - echo "✓ OIDC auth token file verified (empty as expected)" - - echo "✓ All OIDC authentication configuration validations passed!" - timeout: 120s - - - name: cleanup-configmap-mode - try: - - script: - content: | - echo "Cleaning up ConfigMap mode..." - - # Wait for ConfigMap to be deleted - kubectl wait --for=delete configmap -l toolhive.stacklok.io/mcp-server=auth-configmap-test -n toolhive-system --timeout=60s || true - - # Disable ConfigMap mode to avoid affecting subsequent tests - echo "Disabling ConfigMap mode..." - kubectl patch deployment toolhive-operator -n toolhive-system --type='strategic' -p='{"spec":{"template":{"spec":{"containers":[{"name":"manager","env":[{"name":"TOOLHIVE_USE_CONFIGMAP","value":"false"}]}]}}}}' - kubectl rollout status deployment/toolhive-operator -n toolhive-system --timeout=60s - echo "✓ ConfigMap mode cleanup completed" - timeout: 120s \ No newline at end of file diff --git a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/mcpserver-auth.yaml b/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/mcpserver-auth.yaml deleted file mode 100644 index 60074a9f1..000000000 --- a/test/e2e/chainsaw/operator/single-tenancy/test-scenarios/auth-configmap/mcpserver-auth.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: toolhive.stacklok.dev/v1alpha1 -kind: MCPServer -metadata: - name: auth-configmap-test - namespace: toolhive-system -spec: - image: ghcr.io/stackloklabs/yardstick/yardstick-server:0.0.2 - transport: stdio - proxyPort: 8080 - - # Inline OIDC authentication configuration to test ConfigMap generation - oidcConfig: - type: inline - inline: - issuer: "https://auth.example.com" - audience: "toolhive-api" - jwksUrl: "https://auth.example.com/.well-known/jwks.json" - introspectionUrl: "https://auth.example.com/oauth/introspect" - clientId: "toolhive-client" - clientSecret: "secret123" - thvCABundlePath: "/etc/ssl/ca-bundle.pem" - jwksAuthTokenPath: "/etc/auth/token" - jwksAllowPrivateIP: true - - permissionProfile: - type: builtin - name: network - resources: - limits: - cpu: "100m" - memory: "128Mi" - requests: - cpu: "50m" - memory: "64Mi" \ No newline at end of file