-
Notifications
You must be signed in to change notification settings - Fork 14
/
main.go
166 lines (147 loc) · 4.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"context"
"crypto/tls"
"flag"
"fmt"
"github.com/gorilla/mux"
stdlog "log"
"net/http"
"os"
"time"
admissioncontrol "github.com/elithrar/admission-control"
log "github.com/go-kit/kit/log"
)
type conf struct {
TLSCertPath string
TLSKeyPath string
HTTPOnly bool
Port string
Host string
}
func main() {
ctx := context.Background()
// Get config
conf := &conf{}
flag.StringVar(&conf.TLSCertPath, "cert-path", "./cert.crt", "The path to the PEM-encoded TLS certificate")
flag.StringVar(&conf.TLSKeyPath, "key-path", "./key.key", "The path to the unencrypted TLS key")
flag.BoolVar(&conf.HTTPOnly, "http-only", false, "Only listen on unencrypted HTTP (e.g. for proxied environments)")
flag.StringVar(&conf.Port, "port", "8443", "The port to listen on (HTTPS).")
flag.StringVar(&conf.Host, "host", "admissiond.questionable.services", "The hostname for the service")
flag.Parse()
// Set up logging
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
stdlog.SetOutput(log.NewStdlibAdapter(logger))
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "loc", log.DefaultCaller)
// TLS configuration
// Only load the TLS keypair if the -http-only flag is not set.
var tlsConf *tls.Config
if !conf.HTTPOnly {
keyPair, err := tls.LoadX509KeyPair(conf.TLSCertPath, conf.TLSKeyPath)
if err != nil {
fatal(logger, err)
}
tlsConf = &tls.Config{
Certificates: []tls.Certificate{keyPair},
ServerName: conf.Host,
}
}
// Set up the routes & logging middleware.
r := mux.NewRouter().StrictSlash(true)
// Show all available routes
msg := "Admission Control example server. See the docs at https://github.com/elithrar/admission-control 🎟"
r.Handle("/", printAvailableRoutes(r, logger, msg)).Methods(http.MethodGet)
// Default health-check endpoint
r.HandleFunc("/healthz", healthCheckHandler).Methods(http.MethodGet)
// Example admission handler endpoints
admissions := r.PathPrefix("/admission-control").Subrouter()
admissions.Handle("/deny-ingresses", &admissioncontrol.AdmissionHandler{
AdmitFunc: admissioncontrol.DenyIngresses(nil),
Logger: logger,
}).Methods(http.MethodPost)
admissions.Handle("/deny-public-services/gcp", &admissioncontrol.AdmissionHandler{
// nil = don't whitelist any namespace.
AdmitFunc: admissioncontrol.DenyPublicLoadBalancers(nil, admissioncontrol.GCP),
Logger: logger,
}).Methods(http.MethodPost)
admissions.Handle("/deny-public-services/azure", &admissioncontrol.AdmissionHandler{
AdmitFunc: admissioncontrol.DenyPublicLoadBalancers(nil, admissioncontrol.Azure),
Logger: logger,
}).Methods(http.MethodPost)
admissions.Handle("/deny-public-services/aws", &admissioncontrol.AdmissionHandler{
AdmitFunc: admissioncontrol.DenyPublicLoadBalancers(nil, admissioncontrol.AWS),
Logger: logger,
}).Methods(http.MethodPost)
admissions.Handle("/enforce-pod-annotations", &admissioncontrol.AdmissionHandler{
AdmitFunc: admissioncontrol.EnforcePodAnnotations(
[]string{"kube-system"},
map[string]func(string) bool{
"k8s.questionable.services/hostname": func(string) bool { return true },
}),
Logger: logger,
}).Methods(http.MethodPost)
// HTTP server
timeout := time.Second * 15
srv := &http.Server{
Handler: admissioncontrol.LoggingMiddleware(logger)(r),
TLSConfig: tlsConf,
Addr: ":" + conf.Port,
IdleTimeout: timeout,
ReadTimeout: timeout,
ReadHeaderTimeout: timeout,
WriteTimeout: timeout,
}
admissionServer, err := admissioncontrol.NewServer(
srv,
log.With(logger, "component", "server"),
)
if err != nil {
fatal(logger, err)
return
}
if err := admissionServer.Run(ctx); err != nil {
fatal(logger, err)
return
}
}
func fatal(logger log.Logger, err error) {
logger.Log(
"status", "fatal",
"err", err,
)
os.Exit(1)
return
}
// healthCheckHandler returns a HTTP 200, everytime.
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
// printAvailableRoutes prints all routes attached to the provided Router, and
// prepends a message to the response.
func printAvailableRoutes(router *mux.Router, logger log.Logger, msg string) http.Handler {
fn := func(w http.ResponseWriter, req *http.Request) {
var routes []string
err := router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
path, err := route.GetPathTemplate()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
logger.Log("msg", "walkFunc failed", err, err.Error())
return err
}
routes = append(routes, path)
return nil
})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
logger.Log("msg", "walkFunc failed", err, err.Error())
return
}
fmt.Fprintln(w, msg)
fmt.Fprintln(w, "Available routes:")
for _, path := range routes {
fmt.Fprintln(w, path)
}
}
return http.HandlerFunc(fn)
}