...
1
16
17 package inclusterclient
18
19 import (
20 "context"
21 "crypto/sha256"
22 "encoding/base64"
23 "flag"
24 "fmt"
25 "log"
26 "net/http"
27 "time"
28
29 "github.com/spf13/cobra"
30
31 "k8s.io/client-go/kubernetes"
32 "k8s.io/client-go/rest"
33 "k8s.io/component-base/logs"
34 "k8s.io/klog/v2"
35 )
36
37 var pollInterval int
38
39
40 var CmdInClusterClient = &cobra.Command{
41 Use: "inclusterclient",
42 Short: "Periodically poll the Kubernetes \"/healthz\" endpoint",
43 Long: `Periodically polls the Kubernetes "/healthz" endpoint using the in-cluster config. Because of this, this subcommand is meant to be run inside of a Kubernetes pod.
44
45 This subcommand can also be used to validate token rotation.`,
46 Args: cobra.MaximumNArgs(0),
47 Run: main,
48 }
49
50 func init() {
51 CmdInClusterClient.Flags().IntVar(&pollInterval, "poll-interval", 30,
52 "poll interval of call to /healthz in seconds")
53 }
54
55 func main(cmd *cobra.Command, args []string) {
56 logs.InitLogs()
57 defer logs.FlushLogs()
58
59 flag.Set("logtostderr", "true")
60
61 klog.Infof("started")
62
63 cfg, err := rest.InClusterConfig()
64 if err != nil {
65 log.Fatalf("err: %v", err)
66 }
67
68 cfg.Wrap(func(rt http.RoundTripper) http.RoundTripper {
69 return &debugRt{
70 rt: rt,
71 }
72 })
73
74 c := kubernetes.NewForConfigOrDie(cfg).RESTClient()
75
76 t := time.Tick(time.Duration(pollInterval) * time.Second)
77 for {
78 <-t
79 klog.Infof("calling /healthz")
80 b, err := c.Get().AbsPath("/healthz").Do(context.TODO()).Raw()
81 if err != nil {
82 klog.Errorf("status=failed")
83 klog.Errorf("error checking /healthz: %v\n%s\n", err, string(b))
84 }
85 }
86 }
87
88 type debugRt struct {
89 rt http.RoundTripper
90 }
91
92 func (rt *debugRt) RoundTrip(req *http.Request) (*http.Response, error) {
93 authHeader := req.Header.Get("Authorization")
94 if len(authHeader) != 0 {
95 authHash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s", "salt", authHeader)))
96 klog.Infof("authz_header=%s", base64.RawURLEncoding.EncodeToString(authHash[:]))
97 } else {
98 klog.Errorf("authz_header=<empty>")
99 }
100 return rt.rt.RoundTrip(req)
101 }
102
103 func (rt *debugRt) WrappedRoundTripper() http.RoundTripper { return rt.rt }
104
View as plain text