From a0ef798dcec6c4d8564666a58e499e756a2939b5 Mon Sep 17 00:00:00 2001 From: "antoine.choimet" <12182686+achoimet@users.noreply.github.com.> Date: Tue, 20 Oct 2026 17:01:35 +0200 Subject: [PATCH 1/2] feat: support StackState with self-signed certificates Trust a mounted CA through SSL_CERT_DIR (chart: extraVolumes/extraVolumeMounts), or skip verification with stackstate.insecureSkipVerify. Both go through extension-kit's exttls, shared with the other extensions. --- README.md | 39 +++++ .../steadybit-extension-stackstate/Chart.yaml | 2 +- .../templates/deployment.yaml | 8 + .../__snapshot__/deployment_test.yaml.snap | 124 +++++++++++++++ .../tests/deployment_test.yaml | 17 +++ .../values.yaml | 16 ++ e2e/mock_stackstate_server_test.go | 34 ++++- e2e/self_signed_test.go | 141 +++++++++++++++++ go.mod | 61 ++++---- go.sum | 142 +++++++++--------- main.go | 2 + 11 files changed, 482 insertions(+), 104 deletions(-) create mode 100644 e2e/self_signed_test.go diff --git a/README.md b/README.md index 077bb08..453ee40 100755 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ You need to have a StackState service token. The following steps describe how to | `STEADYBIT_EXTENSION_SERVICE_TOKEN` | `stackstate.serviceToken` | Stack State Service Token | yes | | | `STEADYBIT_EXTENSION_API_BASE_URL` | `stackstate.apiBaseUrl` | Stack State API Base URL (example: https://yourcompany.app.stackstate.io/api) | yes | | | `STEADYBIT_EXTENSION_DISCOVERY_ATTRIBUTES_EXCLUDES_SERVICE` | `discovery.attributes.excludes.service` | List of Service Attributes which will be excluded during discovery. Checked by key equality and supporting trailing "*" | no | | +| `STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY` | `stackstate.insecureSkipVerify` | Skip TLS certificate verification when connecting to StackState. See [Importing your own certificates](#importing-your-own-certificates). | no | `false` | Beyond the settings above, this extension supports the configuration common to all Steadybit @@ -32,6 +33,44 @@ extensions: - [Group Matching](https://github.com/steadybit/discovery-kit/blob/main/docs/target-enrichment.md#group-matching) — tag discovered targets with a group, so enrichment rules only match within it. +## Importing your own certificates + +If your StackState is served with a self-signed certificate, or one issued by a private CA, either trust the CA +(recommended) or skip certificate verification. + +### Option 1: Mounting custom certificates + +Store the CA certificate (`*.crt`) in a config map: + +```shell +kubectl create configmap -n steadybit-agent stackstate-self-signed-ca --from-file=./self-signed-ca.crt +``` + +Then mount it and add it to the trusted certificate directories: + +```yaml +extraVolumeMounts: + - name: extra-certs + mountPath: /etc/ssl/extra-certs + readOnly: true +extraVolumes: + - name: extra-certs + configMap: + name: stackstate-self-signed-ca +extraEnv: + - name: SSL_CERT_DIR + value: /etc/ssl/extra-certs:/etc/ssl/certs +``` + +### Option 2: Skipping certificate verification + +Disables TLS certificate verification. Suitable for testing, not recommended for production. + +```yaml +stackstate: + insecureSkipVerify: true +``` + ## Installation ### Kubernetes diff --git a/charts/steadybit-extension-stackstate/Chart.yaml b/charts/steadybit-extension-stackstate/Chart.yaml index 8fe1425..e12fd0d 100644 --- a/charts/steadybit-extension-stackstate/Chart.yaml +++ b/charts/steadybit-extension-stackstate/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: steadybit-extension-stackstate description: Steadybit stackstate extension Helm chart for Kubernetes. -version: 1.1.40 +version: 1.1.41 appVersion: v1.0.36 home: https://www.steadybit.com/ icon: https://steadybit-website-assets.s3.amazonaws.com/logo-symbol-transparent.png diff --git a/charts/steadybit-extension-stackstate/templates/deployment.yaml b/charts/steadybit-extension-stackstate/templates/deployment.yaml index a36bb72..cfc8d27 100644 --- a/charts/steadybit-extension-stackstate/templates/deployment.yaml +++ b/charts/steadybit-extension-stackstate/templates/deployment.yaml @@ -68,6 +68,8 @@ spec: key: service-token - name: STEADYBIT_EXTENSION_API_BASE_URL value: {{ .Values.stackstate.apiBaseUrl }} + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: {{ .Values.stackstate.insecureSkipVerify | quote }} {{- with .Values.extraEnv }} {{- toYaml . | nindent 12 }} {{- end }} @@ -77,6 +79,9 @@ spec: {{- end }} volumeMounts: {{- include "extensionlib.deployment.volumeMounts" (list .) | nindent 12 }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} livenessProbe: initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} periodSeconds: {{ .Values.probes.liveness.periodSeconds }} @@ -101,6 +106,9 @@ spec: {{- end }} volumes: {{- include "extensionlib.deployment.volumes" (list .) | nindent 8 }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} serviceAccountName: {{ .Values.serviceAccount.name }} {{- with .Values.nodeSelector }} nodeSelector: diff --git a/charts/steadybit-extension-stackstate/tests/__snapshot__/deployment_test.yaml.snap b/charts/steadybit-extension-stackstate/tests/__snapshot__/deployment_test.yaml.snap index 3d49993..bd80962 100644 --- a/charts/steadybit-extension-stackstate/tests/__snapshot__/deployment_test.yaml.snap +++ b/charts/steadybit-extension-stackstate/tests/__snapshot__/deployment_test.yaml.snap @@ -39,6 +39,8 @@ manifest should match snapshot using podAnnotations and Labels: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -123,6 +125,8 @@ manifest should match snapshot with TLS: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -171,6 +175,96 @@ manifest should match snapshot with TLS: secret: optional: false secretName: server-cert +manifest should match snapshot with custom certificates and insecureSkipVerify: + 1: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + steadybit.com/discovery-disabled: "true" + steadybit.com/extension: "true" + name: RELEASE-NAME-steadybit-extension-stackstate + namespace: NAMESPACE + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: steadybit-extension-stackstate + template: + metadata: + annotations: + oneagent.dynatrace.com/injection: "false" + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: steadybit-extension-stackstate + steadybit.com/discovery-disabled: "true" + steadybit.com/extension: "true" + spec: + containers: + - env: + - name: STEADYBIT_LOG_LEVEL + value: INFO + - name: STEADYBIT_LOG_FORMAT + value: text + - name: STEADYBIT_EXTENSION_SERVICE_TOKEN + valueFrom: + secretKeyRef: + key: service-token + name: steadybit-extension-stackstate + - name: STEADYBIT_EXTENSION_API_BASE_URL + value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "true" + - name: SSL_CERT_DIR + value: /etc/ssl/extra-certs:/etc/ssl/certs + image: ghcr.io/steadybit/extension-stackstate:v0.0.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health/liveness + port: 8084 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + name: extension + readinessProbe: + failureThreshold: 3 + httpGet: + path: /health/readiness + port: 8084 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 200m + memory: 128Mi + requests: + cpu: 50m + memory: 32Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /etc/ssl/extra-certs + name: extra-certs + readOnly: true + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccountName: steadybit-extension-stackstate + volumes: + - configMap: + name: stackstate-self-signed-ca + name: extra-certs manifest should match snapshot with custom image registry: 1: | apiVersion: apps/v1 @@ -210,6 +304,8 @@ manifest should match snapshot with custom image registry: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: my-registry.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -290,6 +386,8 @@ manifest should match snapshot with env vars: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: https://stackstate.example.com + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -370,6 +468,8 @@ manifest should match snapshot with existing secret: name: secret-stackstate-existing - name: STEADYBIT_EXTENSION_API_BASE_URL value: https://stackstate.example.com + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -450,6 +550,8 @@ manifest should match snapshot with extra env vars: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" - name: FOO value: bar envFrom: @@ -539,6 +641,8 @@ manifest should match snapshot with extra labels: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -619,6 +723,8 @@ manifest should match snapshot with global image pull secrets: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -701,6 +807,8 @@ manifest should match snapshot with global image registry: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: corp-registry.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -781,6 +889,8 @@ manifest should match snapshot with global priority class: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -862,6 +972,8 @@ manifest should match snapshot with image pull secrets: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -944,6 +1056,8 @@ manifest should match snapshot with legacy image name containing registry: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -1030,6 +1144,8 @@ manifest should match snapshot with mutual TLS: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -1130,6 +1246,8 @@ manifest should match snapshot with mutual TLS using containerPaths: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -1210,6 +1328,8 @@ manifest should match snapshot with podSecurityContext: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -1291,6 +1411,8 @@ manifest should match snapshot with priority class: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: @@ -1372,6 +1494,8 @@ manifest should match snapshot without TLS: name: steadybit-extension-stackstate - name: STEADYBIT_EXTENSION_API_BASE_URL value: null + - name: STEADYBIT_EXTENSION_INSECURE_SKIP_VERIFY + value: "false" image: ghcr.io/steadybit/extension-stackstate:v0.0.0 imagePullPolicy: IfNotPresent livenessProbe: diff --git a/charts/steadybit-extension-stackstate/tests/deployment_test.yaml b/charts/steadybit-extension-stackstate/tests/deployment_test.yaml index deddb98..4abe8e0 100644 --- a/charts/steadybit-extension-stackstate/tests/deployment_test.yaml +++ b/charts/steadybit-extension-stackstate/tests/deployment_test.yaml @@ -153,3 +153,20 @@ tests: - global-pull-secret asserts: - matchSnapshot: {} + - it: manifest should match snapshot with custom certificates and insecureSkipVerify + set: + stackstate: + insecureSkipVerify: true + extraVolumeMounts: + - name: extra-certs + mountPath: /etc/ssl/extra-certs + readOnly: true + extraVolumes: + - name: extra-certs + configMap: + name: stackstate-self-signed-ca + extraEnv: + - name: SSL_CERT_DIR + value: /etc/ssl/extra-certs:/etc/ssl/certs + asserts: + - matchSnapshot: {} diff --git a/charts/steadybit-extension-stackstate/values.yaml b/charts/steadybit-extension-stackstate/values.yaml index a8bf96b..989392a 100644 --- a/charts/steadybit-extension-stackstate/values.yaml +++ b/charts/steadybit-extension-stackstate/values.yaml @@ -9,6 +9,8 @@ stackstate: apiBaseUrl: "" # stackstate.existingSecret -- If defined, will skip secret creation and instead assume that the referenced secret contains the keys api-token. existingSecret: null + # stackstate.insecureSkipVerify -- If true, the extension will skip TLS certificate verification when connecting to StackState (e.g. for self-signed certificates). Prefer mounting your CA, see README. + insecureSkipVerify: false image: # image.registry -- The container registry to use. Defaults to global.image.registry or ghcr.io. @@ -140,6 +142,20 @@ extraEnv: [] # name: env-secrets extraEnvFrom: [] +# extraVolumeMounts -- Additional volumeMounts to add to the container, e.g. to mount custom CA certificates +# extraVolumeMounts: +# - name: extra-certs +# mountPath: /etc/ssl/extra-certs +# readOnly: true +extraVolumeMounts: [] + +# extraVolumes -- Additional volumes to add to the pod +# extraVolumes: +# - name: extra-certs +# configMap: +# name: stackstate-self-signed-ca +extraVolumes: [] + discovery: # discovery.group -- Optional group identifier. When set, the extension adds steadybit.group= to every discovered target. Used as an additional matcher in enrichment rules. group: "" diff --git a/e2e/mock_stackstate_server_test.go b/e2e/mock_stackstate_server_test.go index 48eefa8..ebc4cd7 100644 --- a/e2e/mock_stackstate_server_test.go +++ b/e2e/mock_stackstate_server_test.go @@ -5,11 +5,16 @@ package e2e import ( + "crypto/tls" "fmt" + stdlog "log" "net" "net/http" "net/http/httptest" + "os" + "strings" "sync" + "sync/atomic" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -21,6 +26,18 @@ type mockServer struct { http *httptest.Server stateMu sync.RWMutex state string + // tlsHandshakeErrors counts handshakes the client aborted, e.g. because it does not trust the certificate. + tlsHandshakeErrors atomic.Int64 +} + +// errorLogWriter forwards the mock's server error log to stderr and counts TLS handshake errors. +type errorLogWriter struct{ mock *mockServer } + +func (w errorLogWriter) Write(p []byte) (int, error) { + if strings.Contains(string(p), "TLS handshake error") { + w.mock.tlsHandshakeErrors.Add(1) + } + return os.Stderr.Write(p) } func (m *mockServer) setState(state string) { @@ -36,17 +53,28 @@ func (m *mockServer) getState() string { } func createMockStackstateServer() *mockServer { + return createMockStackstateServerWithTLS(nil) +} + +// createMockStackstateServerWithTLS serves HTTPS with the given certificate, or plain HTTP when it is nil. +func createMockStackstateServerWithTLS(cert *tls.Certificate) *mockServer { listener, err := net.Listen("tcp", "0.0.0.0:0") if err != nil { panic(fmt.Sprintf("httptest: failed to listen: %v", err)) } mux := http.NewServeMux() + mock := &mockServer{state: "CLEAR"} - server := httptest.Server{Listener: listener, Config: &http.Server{Handler: mux}} - server.Start() + server := httptest.Server{Listener: listener, Config: &http.Server{Handler: mux, ErrorLog: stdlog.New(errorLogWriter{mock}, "", stdlog.LstdFlags)}} + if cert != nil { + server.TLS = &tls.Config{Certificates: []tls.Certificate{*cert}} + server.StartTLS() + } else { + server.Start() + } log.Info().Str("url", server.URL).Msg("Started Mock-Server") - mock := &mockServer{http: &server, state: "CLEAR"} + mock.http = &server mux.Handle("POST /snapshot", handler(mock.viewSnapshot)) return mock } diff --git a/e2e/self_signed_test.go b/e2e/self_signed_test.go new file mode 100644 index 0000000..06517c0 --- /dev/null +++ b/e2e/self_signed_test.go @@ -0,0 +1,141 @@ +/* + * Copyright 2026 steadybit GmbH. All rights reserved. + */ + +package e2e + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "net" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/steadybit/action-kit/go/action_kit_test/e2e" + "github.com/steadybit/extension-kit/extlogging" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const selfSignedCaConfigMap = "stackstate-self-signed-ca" + +// TestWithMinikubeSelfSignedCertificate runs the extension against a StackState served over HTTPS with a +// self-signed certificate: it must refuse the connection by default, and accept it once the operator either +// skips verification or mounts the CA. Each configuration gets its own cluster, as the e2e harness cannot +// reconfigure a Deployment in place (it waits on the terminating pod of the previous revision). +func TestWithMinikubeSelfSignedCertificate(t *testing.T) { + cert, caFile := generateSelfSignedCert(t) + server := createMockStackstateServerWithTLS(&cert) + defer server.http.Close() + split := strings.SplitAfter(server.http.URL, ":") + port := split[len(split)-1] + + extlogging.InitZeroLog() + + installCaConfigMap := func(m *e2e.Minikube) error { + return m.CreateConfigMap("default", selfSignedCaConfigMap, caFile) + } + + scenarios := []struct { + name string + args []string + test func(t *testing.T, m *e2e.Minikube, e *e2e.Extension) + }{ + { + name: "rejects self-signed certificate by default", + test: testNoServicesDiscovered(server), + }, + { + name: "accepts self-signed certificate with insecureSkipVerify", + args: []string{"--set", "stackstate.insecureSkipVerify=true"}, + test: testDiscovery, + }, + { + name: "accepts self-signed certificate with mounted CA", + args: []string{ + "--set", "extraEnv[0].name=SSL_CERT_DIR", + "--set", "extraEnv[0].value=/etc/ssl/extra-certs:/etc/ssl/certs", + "--set", "extraVolumeMounts[0].name=extra-certs", + "--set", "extraVolumeMounts[0].mountPath=/etc/ssl/extra-certs", + "--set", "extraVolumeMounts[0].readOnly=true", + "--set", "extraVolumes[0].name=extra-certs", + "--set", "extraVolumes[0].configMap.name=" + selfSignedCaConfigMap, + }, + test: testDiscovery, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + extFactory := e2e.HelmExtensionFactory{ + Name: "extension-stackstate", + Port: 8083, + ExtraArgs: func(m *e2e.Minikube) []string { + return append([]string{ + "--set", fmt.Sprintf("stackstate.apiBaseUrl=https://host.minikube.internal:%s", port), + "--set", "stackstate.serviceToken=service-token-123", + "--set", "logging.level=trace", + }, scenario.args...) + }, + } + e2e.WithMinikube(t, e2e.DefaultMinikubeOpts().AfterStart(installCaConfigMap), &extFactory, []e2e.WithMinikubeTestCase{ + {Name: scenario.name, Test: scenario.test}, + }) + }) + } +} + +// testNoServicesDiscovered asserts the extension reached the mock but aborted the TLS handshake, and so +// discovered nothing. Discovery reports an empty list on any request failure, so the handshake errors are +// what proves the certificate was rejected. Targets are refreshed on startup, so the window covers the +// first refresh. +func testNoServicesDiscovered(server *mockServer) func(t *testing.T, m *e2e.Minikube, e *e2e.Extension) { + return func(t *testing.T, _ *e2e.Minikube, e *e2e.Extension) { + responded := false + for deadline := time.Now().Add(20 * time.Second); time.Now().Before(deadline); time.Sleep(2 * time.Second) { + targets, err := e.DiscoverTargets("com.steadybit.extension_stackstate.service") + if err != nil { + continue + } + responded = true + require.Empty(t, targets, "no service must be discovered from a server with an untrusted certificate") + } + assert.True(t, responded, "discovery never answered") + assert.Positive(t, server.tlsHandshakeErrors.Load(), "the extension must have reached the mock and rejected its certificate") + } +} + +// generateSelfSignedCert returns a certificate valid for host.minikube.internal, and the path of its PEM file +// to mount as CA. +func generateSelfSignedCert(t *testing.T) (tls.Certificate, string) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + template := x509.Certificate{ + SerialNumber: big.NewInt(time.Now().UnixNano()), + Subject: pkix.Name{CommonName: "host.minikube.internal"}, + NotBefore: time.Now().Add(-time.Hour), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: true, + DNSNames: []string{"host.minikube.internal", "localhost"}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, + } + der, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key) + require.NoError(t, err) + + caFile := filepath.Join(t.TempDir(), "self-signed-ca.crt") + require.NoError(t, os.WriteFile(caFile, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0o600)) + return tls.Certificate{Certificate: [][]byte{der}, PrivateKey: key}, caFile +} diff --git a/go.mod b/go.mod index ee99e7d..d8fc936 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/steadybit/discovery-kit/go/discovery_kit_commons v0.3.2 github.com/steadybit/discovery-kit/go/discovery_kit_sdk v1.4.2 github.com/steadybit/discovery-kit/go/discovery_kit_test v1.2.2 - github.com/steadybit/extension-kit v1.12.1 + github.com/steadybit/extension-kit v1.12.2 github.com/stretchr/testify v1.12.1 ) @@ -32,26 +32,26 @@ require ( github.com/getkin/kin-openapi v0.149.0 // indirect github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v1.0.0 // indirect - github.com/go-openapi/jsonreference v1.0.0 // indirect - github.com/go-openapi/swag v0.28.0 // indirect - github.com/go-openapi/swag/cmdutils v0.28.0 // indirect - github.com/go-openapi/swag/conv v0.29.0 // indirect - github.com/go-openapi/swag/fileutils v0.28.0 // indirect - github.com/go-openapi/swag/jsonutils v0.29.0 // indirect - github.com/go-openapi/swag/loading v0.29.0 // indirect - github.com/go-openapi/swag/mangling v0.28.0 // indirect - github.com/go-openapi/swag/netutils v0.28.0 // indirect - github.com/go-openapi/swag/pools v0.29.0 // indirect - github.com/go-openapi/swag/stringutils v0.28.0 // indirect - github.com/go-openapi/swag/typeutils v0.29.0 // indirect - github.com/go-openapi/swag/yamlutils v0.29.0 // indirect + github.com/go-openapi/jsonpointer v1.0.1 // indirect + github.com/go-openapi/jsonreference v1.0.1 // indirect + github.com/go-openapi/swag v0.29.2 // indirect + github.com/go-openapi/swag/cmdutils v0.29.2 // indirect + github.com/go-openapi/swag/conv v0.29.2 // indirect + github.com/go-openapi/swag/fileutils v0.29.2 // indirect + github.com/go-openapi/swag/jsonutils v0.29.2 // indirect + github.com/go-openapi/swag/loading v0.29.2 // indirect + github.com/go-openapi/swag/mangling v0.29.2 // indirect + github.com/go-openapi/swag/netutils v0.29.2 // indirect + github.com/go-openapi/swag/pools v0.29.2 // indirect + github.com/go-openapi/swag/stringutils v0.29.2 // indirect + github.com/go-openapi/swag/typeutils v0.29.2 // indirect + github.com/go-openapi/swag/yamlutils v0.29.2 // indirect github.com/google/gnostic-models v0.7.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.31.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.20.0 // indirect + github.com/klauspost/compress v1.20.3 // indirect github.com/mattn/go-colorable v0.1.15 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/moby/spdystream v0.5.1 // indirect @@ -71,18 +71,19 @@ require ( github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect github.com/zmwangx/debounce v1.0.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect - go.opentelemetry.io/otel v1.46.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.46.0 // indirect - go.opentelemetry.io/otel/metric v1.46.0 // indirect - go.opentelemetry.io/otel/sdk v1.46.0 // indirect - go.opentelemetry.io/otel/trace v1.46.0 // indirect - go.opentelemetry.io/proto/otlp v1.11.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect + go.opentelemetry.io/otel v1.47.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.47.0 // indirect + go.opentelemetry.io/otel/log v1.47.0 // indirect + go.opentelemetry.io/otel/metric v1.47.0 // indirect + go.opentelemetry.io/otel/sdk v1.47.0 // indirect + go.opentelemetry.io/otel/trace v1.47.0 // indirect + go.opentelemetry.io/proto/otlp v1.11.1 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect - golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 // indirect + golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba // indirect golang.org/x/net v0.61.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.24.0 // indirect @@ -90,9 +91,9 @@ require ( golang.org/x/term v0.47.0 // indirect golang.org/x/text v0.43.0 // indirect golang.org/x/time v0.15.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect - google.golang.org/grpc v1.83.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect + google.golang.org/grpc v1.84.0 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index fa3e9b7..663f8aa 100644 --- a/go.sum +++ b/go.sum @@ -35,40 +35,40 @@ github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= -github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= -github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= -github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= -github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= -github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= -github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= -github.com/go-openapi/swag/cmdutils v0.28.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= -github.com/go-openapi/swag/conv v0.29.0 h1:4+1TogWpOIzMPzVKrvx1BfqBYlApB7D7DW3EAWpwmp4= -github.com/go-openapi/swag/conv v0.29.0/go.mod h1:ch1l7V87F6zQXuLs5s0RFvrro6aFvrVcfVXn2PTZnu8= -github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU= -github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8= -github.com/go-openapi/swag/jsonutils v0.29.0 h1:Xgnf9g32ycQjQUnDxkhqLraH2FhitcSE3w7ayQB3TgA= -github.com/go-openapi/swag/jsonutils v0.29.0/go.mod h1:5WYmjf6hJcBve+ArzBaUsYy4M1GXsgjIQTmwJKfZHrA= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.0 h1:bpSF6LFkJJVtaRtJCzbZADVPVHQYKPwPdKthOQA2/5o= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.0/go.mod h1:julgTUKZ9/D0j6O7GKajmRs+812FWxQg/mMpGunWSjg= -github.com/go-openapi/swag/loading v0.29.0 h1:r1lg2DQbT1VgBwgiPYXBM059RNswFI6r36CC0QCcRGw= -github.com/go-openapi/swag/loading v0.29.0/go.mod h1:l/Z4MNbom0jSqzvWJqK2VUUWEceBknGEuVbLHLq4KN0= -github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM= -github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w= -github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k= -github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ= -github.com/go-openapi/swag/pools v0.29.0 h1:uMQcoJeHJ8fWkdfEXJZMMpqk6hpfW8qTL5Q/IoRFFII= -github.com/go-openapi/swag/pools v0.29.0/go.mod h1:leDcaghjkRAhCuCRv9NfJU5f0mjoU3cT/XZObhMk3pc= -github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU= -github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= -github.com/go-openapi/swag/typeutils v0.29.0 h1:HrWCYZeXVVNDo/7QQPRaYk33XeIDxksbxpalID3bWR8= -github.com/go-openapi/swag/typeutils v0.29.0/go.mod h1:hxpgDZJVBkBsi/d3MIUosafoFdE5exaQRmVp0zwu3YE= -github.com/go-openapi/swag/yamlutils v0.29.0 h1:JOKKuhMnBx4HYTM+kPEYw8S5YKKU9PnC4Mwb+c69BBA= -github.com/go-openapi/swag/yamlutils v0.29.0/go.mod h1:/+FVozjFWZzku6mRz5U/Qmq5Yk8PLFxBLLWA/jHaxYE= -github.com/go-openapi/testify/enable/yaml/v2 v2.6.1 h1:Jm+/ze2rMtbD98yen92AhATGLGREDYXG56Xr4gMjEtE= -github.com/go-openapi/testify/enable/yaml/v2 v2.6.1/go.mod h1:YDPnwCRDu38/oJBVMBVXOUDiJ9cIeBHWvfImHaXqnv4= -github.com/go-openapi/testify/v2 v2.6.1 h1:6CNJhTjMzgaeaH8WhshcsZNPIvRemiOcFpU7seO/y7Q= -github.com/go-openapi/testify/v2 v2.6.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-openapi/jsonpointer v1.0.1 h1:2KxywRmNwJkT/FMBa3iRNHEaAxSJvjqoufQZy3au1Mg= +github.com/go-openapi/jsonpointer v1.0.1/go.mod h1:wI7ZYsFmbIi9nBXOZqgDaS/bqOchRGZjqxFli7FBYxY= +github.com/go-openapi/jsonreference v1.0.1 h1:4zJ7AmYDKNmD3aSpfPnFNCFA5E80/xMHUNKgydaLh38= +github.com/go-openapi/jsonreference v1.0.1/go.mod h1:dYplQXa6p5lXprLcJ8LE2iU7vNpXsAHDQ5ZAgL+Qx3A= +github.com/go-openapi/swag v0.29.2 h1:9n8frkcsuQRA0INU31VbxNxt1zBaHxrHYGEf5BUjFi4= +github.com/go-openapi/swag v0.29.2/go.mod h1:RkCiX1gCVXWgLOavDXE3ALJrQ/VO2ziiIzOUs3z10xo= +github.com/go-openapi/swag/cmdutils v0.29.2 h1:cXEzX/nWCODon251f+1HgL75/R4XXML5IZxgLCWMoro= +github.com/go-openapi/swag/cmdutils v0.29.2/go.mod h1:XziaSVzYqkDvpWXzASfWajw2YvJrLscq610O2XiyqJw= +github.com/go-openapi/swag/conv v0.29.2 h1:8c9shoB8l0QRSR6ymq1llHdBWDqpIgJfjTGHx3Vuhm0= +github.com/go-openapi/swag/conv v0.29.2/go.mod h1:AZS0YigTNf8qNtD6WqJz/N4RUNmpr76SyjFGkq4+p6Q= +github.com/go-openapi/swag/fileutils v0.29.2 h1:mdUL+Vw5ah1fO1AvFCoHeIyv7YZsCz2MN3KNqd/lLVI= +github.com/go-openapi/swag/fileutils v0.29.2/go.mod h1:7QKmmodjAebaq61lGVJa8ldLdGeMF4DSgYv8tXOGGo0= +github.com/go-openapi/swag/jsonutils v0.29.2 h1:uZNSD2/rJDYAfvsLYkykTzXuyxM3QpDKV9jhRHrMu6k= +github.com/go-openapi/swag/jsonutils v0.29.2/go.mod h1:ONTdNvj3Y+IXRzfa17E+Rgt2ns/qiSOYjIo2K7v2yDs= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.2 h1:w+Fd6EBOMGlC74GYGHqCLGyb3Bpams8TtNrgM/SG4jo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.2/go.mod h1:HC2egPORFzbj/gf05Zrfgz8Mgplx3oW7hgGi7pjZVhM= +github.com/go-openapi/swag/loading v0.29.2 h1:QU1ry24e6r6Shoxe380Nx0X5iKkpRO+hJffsyJ2dVlY= +github.com/go-openapi/swag/loading v0.29.2/go.mod h1:DqilDjuiJKETecsS4TRopWG1acUDsfqN39ZmQhPu6uI= +github.com/go-openapi/swag/mangling v0.29.2 h1:ltdo3K0tTP4P6zWhVVWDU9D37/YYBuMJRdZxiS2Dtog= +github.com/go-openapi/swag/mangling v0.29.2/go.mod h1:RjDi4TnItAenS3cgCXSpIl1kKbjG7il6pnmQVl/8bp8= +github.com/go-openapi/swag/netutils v0.29.2 h1:dBli6jyUa93sDS/XYWShJzf4+nnVfFKfvY9SLUaUzB8= +github.com/go-openapi/swag/netutils v0.29.2/go.mod h1:1pM6Xg/Um8E1eps3umWl8Hme3ByWXOtHsvFC0CULHUE= +github.com/go-openapi/swag/pools v0.29.2 h1:PlGoDRF8WtSyXkedZZkpW3f9wDhFf3u8KtaBcmgmh8c= +github.com/go-openapi/swag/pools v0.29.2/go.mod h1:V3lhxVT4qDYRqc2MRSSbLsTYIYV/2HlHafhyEkmzLIc= +github.com/go-openapi/swag/stringutils v0.29.2 h1:lcnBxwAaysT3bMUVBfn9V/PkfVqkurpqufKU6rTUMGk= +github.com/go-openapi/swag/stringutils v0.29.2/go.mod h1:i9cdh7sGaa0nm3CqIvH5IM5h2QClk1wns2ktKeILvRI= +github.com/go-openapi/swag/typeutils v0.29.2 h1:O7aVvkTs3pXwikgtrPLenigEMdQFgONKRooQA9pgf2I= +github.com/go-openapi/swag/typeutils v0.29.2/go.mod h1:7+GDG+uz9Ke+eVt4rClZg7wklSDp8hT/mKNh/pC26TE= +github.com/go-openapi/swag/yamlutils v0.29.2 h1:IFKFFeDnuIwzfsuWRQU+rI8iL3g4XyAYjV/RlnlxPLM= +github.com/go-openapi/swag/yamlutils v0.29.2/go.mod h1:7MGqtcrK73sxQ4ceiyIf8qiXS/s09JLMdR5esK5euYQ= +github.com/go-openapi/testify/enable/yaml/v2 v2.7.0 h1:wPW6YRgx3+SID1yUy/Xwa17L8kFEaEKod2VRbJDZNUs= +github.com/go-openapi/testify/enable/yaml/v2 v2.7.0/go.mod h1:mI1M88etYbc3PhgHsWQK2kwvNwW5aGFqMPbmib+SGIs= +github.com/go-openapi/testify/v2 v2.7.0 h1:bycOreEj6wfBvijg3YFogZ/sFjTCDmQnwSodSzHa3X8= +github.com/go-openapi/testify/v2 v2.7.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk= github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -84,8 +84,8 @@ github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25d github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 h1:/Tnpcb2E0Pz/tN9s3bfEY2Q8ePCEX9iuS+cneUwncnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0/go.mod h1:zOBXOsUaBSjKgmH4OGzV1esUpR3oUSCPYVd2cUBjKYY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.31.0 h1:Bd7KaOxzULLxtZ/K5s1aLbWhR0+5RToO65TXHsf3bqQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.31.0/go.mod h1:nN7ts3dFXKtCZWc//yfkpcQNKJABg16/uDVAZpLDalo= github.com/jarcoal/httpmock v1.4.2 h1:dKwiP/9zITCPfBLsDn3kchbSOu16JrnxtVEmL0fPRcI= github.com/jarcoal/httpmock v1.4.2/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -96,14 +96,14 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= -github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= +github.com/klauspost/compress v1.20.3 h1:zWNoFqq/lSuYQRim3dUXlXeA0IqwuZGicdG5ZTfY5j4= +github.com/klauspost/compress v1.20.3/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/madflojo/testcerts v1.5.0 h1:GhQllyAiGzXVZU+i8O/cQkPTHzN59RxMGtm3uETgXnU= -github.com/madflojo/testcerts v1.5.0/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= +github.com/madflojo/testcerts v1.5.1 h1:UiCNtmXvflCmQU2Ujv1FFHODzQiKE7GphMKmZkqIOl8= +github.com/madflojo/testcerts v1.5.1/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= @@ -164,8 +164,8 @@ github.com/steadybit/discovery-kit/go/discovery_kit_sdk v1.4.2 h1:CzMFnqK3J+APGi github.com/steadybit/discovery-kit/go/discovery_kit_sdk v1.4.2/go.mod h1:xTVEG3KHdviZQOg0vda8UJIHnmT41dBLrn97UnYYqyk= github.com/steadybit/discovery-kit/go/discovery_kit_test v1.2.2 h1:z6sSjOY/PJMyWYTJpm+RcmXrgrTwVj5/zwHF0Ulb9Yo= github.com/steadybit/discovery-kit/go/discovery_kit_test v1.2.2/go.mod h1:QJKCpw29htOjS6ySVuuy6sVi5A34TPunGZZUXs+Lrxk= -github.com/steadybit/extension-kit v1.12.1 h1:5OwTSzuB8mB4XtCPUfu+OtxI6x2ofhg4QR+wVivfA0c= -github.com/steadybit/extension-kit v1.12.1/go.mod h1:vlOfQ4LkTRRLZhrSGkdLhvgi4YEZq8jR0yp05j9KYhI= +github.com/steadybit/extension-kit v1.12.2 h1:YEPvK5WogwzeZPYkEaQwokePhtLZ7nHsFEQ7bBQhsfM= +github.com/steadybit/extension-kit v1.12.2/go.mod h1:sZzKIafjnBBcj4ohDLER8hS5AjKjlFsfZosPDHoxR3Q= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= @@ -180,34 +180,36 @@ github.com/zmwangx/debounce v1.0.0 h1:Dyf+WfLESjc2bqFKHgI1dZTW9oh6CJm8SBDkhXrwLB github.com/zmwangx/debounce v1.0.0/go.mod h1:U+/QHt+bSMdUh8XKOb6U+MQV5Ew4eS8M3ua5WJ7Ns6I= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU= -go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc= -go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0 h1:w53CDeOA/Kurp7yRsegSr6pbbr759dOvJ+yNmWM6Hxs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0/go.mod h1:BOmGMCbAtvcJiSJ+hLuhgPLdDbimnraSl8irz3iY8sY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.46.0 h1:KrC1YrQeSt46ITMWAbgQx1M1eV1/1TKzttrBzymPmss= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.46.0/go.mod h1:zDSEzoEqsOrgBeGvH66KRgxh90VonFyJqBHA0Pk3+rM= -go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8= -go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o= -go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI= -go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM= -go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE= -go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4= -go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= -go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= -go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk= -go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw= +go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM= +go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0 h1:UFpxOpYPmMNUtOWhdb+nC1WELIgVf8z9higURrbzYU4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0/go.mod h1:YBGjxe3lt0jtXoEXxGrGhv/jM7oUBUDVK7zhAvNyEjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.47.0 h1:aXZXsZ012wOgVkqaiQv+Z/d8V0xKjmg70F6m4CE94lc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.47.0/go.mod h1:ziu1gUIJhAaxM3EV1e3Ralk5AAyL1UOYz3lJJ4VSI38= +go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI= +go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw= +go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY= +go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU= +go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I= +go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0= +go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw= +go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw= +go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM= +go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0= +go.opentelemetry.io/proto/otlp v1.11.1 h1:SCrPqH9NE5CmBrOqpjNCiT0X5mGwMyGERXdogfR7Yjw= +go.opentelemetry.io/proto/otlp v1.11.1/go.mod h1:wq8W4aSf6bOy8RZyESOeQFr9Pu7wydWX/TY4sgvrTPg= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= -golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 h1:YXnL44eJ77R+ji4/ooy8UsXIhz+lbi2Qgdlc8iRN0gY= -golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297/go.mod h1:Mkmymgv+uMpSQ/XxJ/7GpdrdYoqm3u72jEbpCLiJmNk= +golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba h1:Ck8QetSgk912qxWLMCKxd0in+aiyBQyDSMae6e/xmpU= +golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba/go.mod h1:50RgIsmK7OwqzTTeqcSXQW8SswW0o8fRcDxmqGluJ8E= golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= @@ -224,12 +226,12 @@ golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688 h1:ax2KzoSRIZU/M0cIxri3pKxy99vniH1PVxWC6si/eZI= -google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688/go.mod h1:1RJ9BQGyNdZwkGc1eTqkErfRZ6RJyYPHZo73BZ1vQqI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 h1:cYNAzI2sUwhmCcoj9TxvihSrqsxt6uIkj3rDRhSDmW4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= -google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= -google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= +google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc h1:rZHRz0ogq4Pid1IKtA/ivHi8XONVF5tqUQXA2TtgpkE= +google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:K/n0XLazCJHjD73YuMyNJsN38BPPy1kfFnKxUXaThFU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= +google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= +google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index ae0297d..e0a3923 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "github.com/steadybit/extension-kit/extotel" "github.com/steadybit/extension-kit/extruntime" "github.com/steadybit/extension-kit/extsignals" + "github.com/steadybit/extension-kit/exttls" "github.com/steadybit/extension-stackstate/config" "github.com/steadybit/extension-stackstate/extservice" ) @@ -60,6 +61,7 @@ func main() { func initStackStateHttpClient() { client := resty.New() + client.SetTransport(exttls.Transport()) client.SetBaseURL(config.Config.ApiBaseUrl) client.SetHeader("X-API-Key", config.Config.ServiceToken) client.SetHeader("Content-Type", "application/json") From 762f5d01572010122e39f16a57a8a7d95e1379af Mon Sep 17 00:00:00 2001 From: "antoine.choimet" <12182686+achoimet@users.noreply.github.com.> Date: Wed, 21 Oct 2026 14:17:26 +0200 Subject: [PATCH 2/2] test(e2e): reset the TLS handshake error count per scenario The rejection check relied on running first: handshake errors from an earlier scenario would otherwise satisfy it. --- e2e/self_signed_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/e2e/self_signed_test.go b/e2e/self_signed_test.go index 06517c0..ab93f02 100644 --- a/e2e/self_signed_test.go +++ b/e2e/self_signed_test.go @@ -77,6 +77,8 @@ func TestWithMinikubeSelfSignedCertificate(t *testing.T) { for _, scenario := range scenarios { t.Run(scenario.name, func(t *testing.T) { + // Count only this scenario's handshake errors, so the assertion does not depend on scenario order. + server.tlsHandshakeErrors.Store(0) extFactory := e2e.HelmExtensionFactory{ Name: "extension-stackstate", Port: 8083,