Files
CosmicClash/server/agones/kubernetes_client_test.go

126 lines
4.1 KiB
Go

package agones
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"time"
)
func TestKubernetesHTTPClientTrustsCAAddsAndRotatesBearerToken(t *testing.T) {
var seen []string
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
seen = append(seen, r.Header.Get("Authorization"))
w.WriteHeader(http.StatusNoContent)
}))
server.TLS = testTLSConfig(t)
server.StartTLS()
defer server.Close()
directory := t.TempDir()
caPath := filepath.Join(directory, "ca.crt")
tokenPath := filepath.Join(directory, "token")
certificate := server.Certificate()
if err := os.WriteFile(caPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw}), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(tokenPath, []byte("first-token\n"), 0o600); err != nil {
t.Fatal(err)
}
client, err := NewKubernetesHTTPClient(server.URL, tokenPath, caPath, time.Second)
if err != nil {
t.Fatal(err)
}
for _, token := range []string{"first-token", "rotated-token"} {
if err := os.WriteFile(tokenPath, []byte(token), 0o600); err != nil {
t.Fatal(err)
}
response, err := client.Get(server.URL)
if err != nil {
t.Fatal(err)
}
response.Body.Close()
}
if len(seen) != 2 || seen[0] != "Bearer first-token" || seen[1] != "Bearer rotated-token" {
t.Fatalf("authorization headers = %v", seen)
}
}
func TestKubernetesHTTPClientRejectsInvalidConfigurationAndToken(t *testing.T) {
directory := t.TempDir()
caPath := filepath.Join(directory, "ca.crt")
tokenPath := filepath.Join(directory, "token")
if _, err := NewKubernetesHTTPClient("http://kubernetes.default.svc", tokenPath, caPath, time.Second); err == nil {
t.Fatal("non-TLS API origin accepted")
}
if _, err := NewKubernetesHTTPClient("https://kubernetes.default.svc", tokenPath, caPath, time.Second); err == nil {
t.Fatal("missing CA accepted")
}
if err := os.WriteFile(caPath, []byte("not a certificate"), 0o600); err != nil {
t.Fatal(err)
}
if _, err := NewKubernetesHTTPClient("https://kubernetes.default.svc", tokenPath, caPath, time.Second); err == nil {
t.Fatal("invalid CA accepted")
}
}
func TestKubernetesHTTPClientDoesNotForwardCredentialAcrossOrigins(t *testing.T) {
server := httptest.NewTLSServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}))
defer server.Close()
directory := t.TempDir()
caPath := filepath.Join(directory, "ca.crt")
tokenPath := filepath.Join(directory, "token")
if err := os.WriteFile(caPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: server.Certificate().Raw}), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(tokenPath, []byte("secret-token"), 0o600); err != nil {
t.Fatal(err)
}
client, err := NewKubernetesHTTPClient(server.URL, tokenPath, caPath, time.Second)
if err != nil {
t.Fatal(err)
}
if _, err := client.Get("https://example.invalid/"); err == nil {
t.Fatal("credentialed request to another origin was not rejected")
}
}
func testTLSConfig(t *testing.T) *tls.Config {
t.Helper()
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "127.0.0.1"},
NotBefore: time.Now().Add(-time.Minute),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
}
der, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
if err != nil {
t.Fatal(err)
}
certificate, err := tls.X509KeyPair(
pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}),
pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}),
)
if err != nil {
t.Fatal(err)
}
return &tls.Config{Certificates: []tls.Certificate{certificate}, MinVersion: tls.VersionTLS12}
}