mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 19:53:42 +00:00
68 lines
2.3 KiB
Go
68 lines
2.3 KiB
Go
package agones
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// NewKubernetesHTTPClient builds an in-cluster client for the Kubernetes API.
|
|
// The bearer token is read for every request so kubelet token rotation does not
|
|
// leave a long-running allocator with an expired credential.
|
|
func NewKubernetesHTTPClient(baseURL, tokenPath, caPath string, timeout time.Duration) (*http.Client, error) {
|
|
origin, err := url.Parse(baseURL)
|
|
if err != nil || origin.Scheme != "https" || origin.Host == "" || origin.User != nil || origin.Path != "" || origin.RawQuery != "" || origin.Fragment != "" {
|
|
return nil, fmt.Errorf("Kubernetes API base URL must be an HTTPS origin")
|
|
}
|
|
if strings.TrimSpace(tokenPath) == "" || strings.TrimSpace(caPath) == "" || timeout <= 0 {
|
|
return nil, fmt.Errorf("Kubernetes API token path, CA path, and positive timeout are required")
|
|
}
|
|
caPEM, err := os.ReadFile(caPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read Kubernetes API CA: %w", err)
|
|
}
|
|
roots := x509.NewCertPool()
|
|
if !roots.AppendCertsFromPEM(caPEM) {
|
|
return nil, fmt.Errorf("Kubernetes API CA contains no certificates")
|
|
}
|
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
transport.TLSClientConfig = &tls.Config{RootCAs: roots, MinVersion: tls.VersionTLS12}
|
|
return &http.Client{
|
|
Timeout: timeout,
|
|
Transport: bearerTokenTransport{
|
|
tokenPath: tokenPath,
|
|
expectedOrigin: origin.Scheme + "://" + origin.Host,
|
|
base: transport,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
type bearerTokenTransport struct {
|
|
tokenPath string
|
|
expectedOrigin string
|
|
base http.RoundTripper
|
|
}
|
|
|
|
func (t bearerTokenTransport) RoundTrip(request *http.Request) (*http.Response, error) {
|
|
if request.URL.Scheme+"://"+request.URL.Host != t.expectedOrigin {
|
|
return nil, fmt.Errorf("refusing to send Kubernetes API credential to unexpected origin")
|
|
}
|
|
tokenBytes, err := os.ReadFile(t.tokenPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read Kubernetes API bearer token: %w", err)
|
|
}
|
|
token := strings.TrimSpace(string(tokenBytes))
|
|
if token == "" || strings.ContainsAny(token, " \t\r\n") {
|
|
return nil, fmt.Errorf("Kubernetes API bearer token is empty or malformed")
|
|
}
|
|
cloned := request.Clone(request.Context())
|
|
cloned.Header = request.Header.Clone()
|
|
cloned.Header.Set("Authorization", "Bearer "+token)
|
|
return t.base.RoundTrip(cloned)
|
|
}
|