-
-
Notifications
You must be signed in to change notification settings - Fork 18
/
main.go
152 lines (128 loc) · 4.15 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
package main
import (
"bytes"
"embed"
"fmt"
"html/template"
"io/fs"
"log"
"net/http"
"os"
"time"
"github.com/bakito/sealed-secrets-web/pkg/config"
"github.com/bakito/sealed-secrets-web/pkg/handler"
"github.com/bakito/sealed-secrets-web/pkg/seal"
"github.com/bakito/sealed-secrets-web/pkg/version"
ssClient "github.com/bitnami-labs/sealed-secrets/pkg/client/clientset/versioned/typed/sealedsecrets/v1alpha1"
"github.com/gin-gonic/gin"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd"
)
var (
//go:embed templates/index.html
indexTemplate string
//go:embed templates/secret.yaml
initialSecretYAML string
//go:embed static/*
static embed.FS
staticFS, _ = fs.Sub(static, "static")
clientConfig clientcmd.ClientConfig
)
func init() {
gin.SetMode(gin.ReleaseMode)
// The "usual" clientcmd/kubectl flags
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
overrides := clientcmd.ConfigOverrides{}
clientConfig = clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, &overrides, os.Stdin)
}
func main() {
cfg, err := config.Parse()
if err != nil {
log.Fatalf("Could not read the config: %s", err.Error())
}
if cfg.PrintVersion {
fmt.Println(version.Print("sealed secrets web"))
return
}
coreClient, ssc, err := handler.BuildClients(clientConfig, cfg.DisableLoadSecrets)
if err != nil {
log.Fatalf("Could build k8s clients:%v", err.Error())
}
sealer, err := seal.NewAPISealer(cfg.Ctx, cfg.SealedSecrets)
if err != nil {
log.Fatalf("Setup sealer: %s", err.Error())
}
log.Printf("Running sealed secrets web (%s) on port %d", version.Version, cfg.Web.Port)
_ = setupRouter(coreClient, ssc, cfg, sealer).Run(fmt.Sprintf(":%d", cfg.Web.Port))
}
func setupRouter(coreClient corev1.CoreV1Interface, ssClient ssClient.BitnamiV1alpha1Interface, cfg *config.Config, sealer seal.Sealer) *gin.Engine {
indexHTML, err := renderIndexHTML(cfg)
if err != nil {
log.Fatalf("Could not render the index html template: %s", err.Error())
}
sHandler := handler.NewHandler(coreClient, ssClient, cfg)
r := gin.New()
r.Use(gin.Recovery())
if cfg.Web.Logger {
r.Use(gin.LoggerWithFormatter(ginLogFormatter()))
}
h := handler.New(indexHTML, sealer, cfg)
r.GET("/", h.Index)
r.StaticFS("/static", http.FS(staticFS))
r.GET("/_health", h.Health)
api := r.Group("/api")
api.GET("/version", h.Version)
api.POST("/raw", h.Raw)
api.GET("/certificate", h.Certificate)
api.POST("/kubeseal", h.KubeSeal)
api.POST("/dencode", h.Dencode)
api.POST("/validate", h.Validate)
api.GET("/secret/:namespace/:name", sHandler.Secret)
api.GET("/secrets", sHandler.AllSecrets)
r.NoRoute(h.RedirectToIndex(cfg.Web.Context))
return r
}
func renderIndexHTML(cfg *config.Config) (string, error) {
indexTmpl := template.Must(template.New("index.html").Parse(indexTemplate))
initialSecret := initialSecretYAML
if cfg.InitialSecret != "" {
initialSecret = cfg.InitialSecret
}
data := map[string]interface{}{
"DisableLoadSecrets": cfg.DisableLoadSecrets,
"DisableValidateSecrets": cfg.SealedSecrets.CertURL != "",
"WebContext": cfg.Web.Context,
"InitialSecret": initialSecret,
"Version": version.Version,
}
var tpl bytes.Buffer
if err := indexTmpl.Execute(&tpl, data); err != nil {
return "", err
}
indexHTML := tpl.String()
return indexHTML, nil
}
func ginLogFormatter() func(param gin.LogFormatterParams) string {
return func(param gin.LogFormatterParams) string {
var statusColor, methodColor, resetColor string
if param.IsOutputColor() {
statusColor = param.StatusCodeColor()
methodColor = param.MethodColor()
resetColor = param.ResetColor()
}
if param.Latency > time.Minute {
param.Latency = param.Latency.Truncate(time.Second)
}
return fmt.Sprintf("%v |%s %3d %s| %13v | %15s |%s %-7s %s %#v\n%s",
param.TimeStamp.Format("2006/01/02 15:04:05"),
statusColor, param.StatusCode, resetColor,
param.Latency,
param.ClientIP,
methodColor, param.Method, resetColor,
handler.Sanitize(param.Path),
param.ErrorMessage,
)
}
}