blob: 2603eaef2d50cae15ca2c09e9115760cc1c95c63 [file] [log] [blame]
Serge Bazanski9104e382023-04-04 20:08:21 +02001package main
2
3import (
4 "context"
5 "crypto/tls"
6 "crypto/x509"
7 "encoding/json"
8 "fmt"
9 "log"
10 "net/http"
11 "os"
12 "time"
13)
14
15// test1InClusterKubernetes exercises connectivity to the cluster-local
16// Kubernetes API server. It expects to be able to connect to the APIserver using
17// the ServiceAccount and cluster CA injected by the Kubelet.
18//
19// The entire functionality is reimplemented without relying on Kubernetes
20// client code to make the expected behaviour clear.
21func test1InClusterKubernetes(ctx context.Context) error {
22 token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
23 if err != nil {
24 return fmt.Errorf("failed to read serviceaccount token: %w", err)
25 }
26
27 cacert, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")
28 if err != nil {
29 return fmt.Errorf("failed to read cluster CA certificate: %w", err)
30 }
31 pool := x509.NewCertPool()
32 pool.AppendCertsFromPEM(cacert)
33
34 client := &http.Client{
35 Transport: &http.Transport{
36 TLSClientConfig: &tls.Config{
37 RootCAs: pool,
38 },
39 },
40 }
41
42 req, err := http.NewRequestWithContext(ctx, "GET", "https://kubernetes.default.svc.cluster.local/api", nil)
43 if err != nil {
44 return fmt.Errorf("creating request failed: %w", err)
45 }
46 req.Header.Set("Authorization", "Bearer "+string(token))
47
48 res, err := client.Do(req)
49 if err != nil {
50 return fmt.Errorf("request failed: %w", err)
51 }
52 defer res.Body.Close()
53
54 j := struct {
55 Kind string `json:"kind"`
56 Message string `json:"message"`
57 }{}
58 if err := json.NewDecoder(res.Body).Decode(&j); err != nil {
59 return fmt.Errorf("json parse error: %w", err)
60 }
61
62 if j.Kind == "Status" {
63 return fmt.Errorf("API server responded with error: %q", j.Message)
64 }
65 if j.Kind != "APIVersions" {
66 return fmt.Errorf("unexpected response from server (kind: %q)", j.Kind)
67 }
68
69 return nil
70}
71
72func main() {
73 log.Printf("Metropolis Kubernetes self-test starting...")
74 ctx, ctxC := context.WithTimeout(context.Background(), 10*time.Second)
75 defer ctxC()
76
77 log.Printf("1. In-cluster Kubernetes client...")
78 if err := test1InClusterKubernetes(ctx); err != nil {
79 fmt.Println(err.Error())
80 os.Exit(1)
81 }
82
83 log.Printf("All tests passed.")
84}