mirror of
https://github.com/pgsty/minio.git
synced 2026-10-29 12:07:20 +03:00
011b0df5f5
Update the server and five debugging modules, regenerate dependency credits, and refresh static curl and the native Red Hat CA mitigation. Preserve Kafka's default broker protocol and terminal widths. Copy the returned DARE plaintext when unsealing legacy keys, and cover old encrypted keys, Kafka producer exchanges, and MinKMS TLS identity with regression tests. Keep the published PGSTY component references for reproducible builds. Validated with make test, targeted race tests, module integrity and tidy checks, and govulncheck v1.9.0 source analysis. Rechecked the frozen source and artifact hashes behind the earlier whole-stack compatibility evidence. Signed-off-by: Feng Ruohang <rh@vonng.com>
118 lines
4.1 KiB
Go
118 lines
4.1 KiB
Go
// Copyright (c) 2026 Ruohang Feng
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package kms
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"aead.dev/mtls"
|
|
)
|
|
|
|
// Exercise the configured MinKMS transport, including the API-key certificate.
|
|
// A KES integration test does not cover this separate client implementation.
|
|
func TestConnectMinKMSTLSIdentity(t *testing.T) {
|
|
for _, key := range []string{EnvKESEndpoint, EnvKMSSecretKey, EnvKMSSecretKeyFile} {
|
|
t.Setenv(key, "") // Restore the original value after testing absence.
|
|
if err := os.Unsetenv(key); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
key, err := mtls.GenerateKey()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var mu sync.Mutex
|
|
var connections []tls.ConnectionState
|
|
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet || r.URL.Path != "/version" {
|
|
t.Errorf("unexpected KMS request: %s %s", r.Method, r.URL)
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
identity, err := mtls.PeerIdentity(r.TLS)
|
|
if err != nil || identity != key.Identity() {
|
|
t.Errorf("API key identity: got %s, error %v", identity, err)
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
mu.Lock()
|
|
connections = append(connections, *r.TLS)
|
|
mu.Unlock()
|
|
w.Header().Set("Content-Type", "application/json")
|
|
// Force a new TLS connection so the second request checks session reuse.
|
|
w.Header().Set("Connection", "close")
|
|
_, _ = io.WriteString(w, `{"version":"2026-10-22T00-00-00Z","api_version":"v1"}`)
|
|
}))
|
|
server.Config.ErrorLog = log.New(io.Discard, "", 0)
|
|
server.TLS = &tls.Config{MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12, ClientAuth: tls.RequireAnyClientCert}
|
|
server.StartTLS()
|
|
defer server.Close()
|
|
caDir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(caDir, "ca.pem"), pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: server.Certificate().Raw}), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv(EnvKMSEndpoint, server.URL)
|
|
t.Setenv(EnvKMSAPIKey, key.String())
|
|
t.Setenv(EnvKMSDefaultKey, "silo-test-key")
|
|
t.Setenv(EnvKMSEnclave, "silo-test-enclave")
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
client, err := Connect(ctx, &ConnectionOptions{CADir: caDir})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if client.Type != MinKMS || client.DefaultKey != "silo-test-key" || client.conn.(*kmsConn).enclave != "silo-test-enclave" {
|
|
t.Fatal("MinKMS connection lost its configured identity or key scope")
|
|
}
|
|
for range 2 {
|
|
version, err := client.Version(ctx)
|
|
if err != nil || version != "2026-10-22T00-00-00Z" {
|
|
t.Fatalf("trusted MinKMS: version %q, error %v", version, err)
|
|
}
|
|
}
|
|
mu.Lock()
|
|
if len(connections) != 2 || connections[0].DidResume || !connections[1].DidResume || connections[1].Version != tls.VersionTLS12 {
|
|
t.Errorf("TLS 1.2 client session cache was not preserved: %+v", connections)
|
|
}
|
|
mu.Unlock()
|
|
|
|
// An empty CA directory cannot authenticate this private server. The client
|
|
// must reject it instead of silently falling back to insecure TLS.
|
|
untrusted, err := Connect(ctx, &ConnectionOptions{CADir: t.TempDir()})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = untrusted.Version(ctx)
|
|
var unknownCA x509.UnknownAuthorityError
|
|
if !errors.As(err, &unknownCA) {
|
|
t.Fatalf("untrusted KMS server: got %v, want unknown certificate authority", err)
|
|
}
|
|
}
|