/
bootstrap.go
95 lines (83 loc) · 2.93 KB
/
bootstrap.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
package seal
import (
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"github.com/bitnami-labs/sealed-secrets/pkg/crypto"
"github.com/kluctl/kluctl/pkg/k8s"
k8s2 "github.com/kluctl/kluctl/pkg/types/k8s"
"github.com/kluctl/kluctl/pkg/utils/uo"
log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
certUtil "k8s.io/client-go/util/cert"
"k8s.io/client-go/util/keyutil"
"time"
)
const sealedSecretsKeyLabel = "sealedsecrets.bitnami.com/sealed-secrets-key"
const secretName = "sealed-secrets-key-kluctl-bootstrap"
const configMapName = "sealed-secrets-key-kluctl-bootstrap"
func BootstrapSealedSecrets(k *k8s.K8sCluster, namespace string) error {
existing, _, err := k.GetSingleObject(k8s2.ObjectRef{
GVK: schema.GroupVersionKind{Group: "apiextensions.k8s.io", Version: "v1", Kind: "CustomResourceDefinition"},
Name: "sealedsecrets.bitnami.com",
})
if existing != nil {
// no bootstrap needed as the sealed-secrets operator seams to be installed already
return nil
}
existing, _, err = k.GetSingleObject(k8s2.ObjectRef{
GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ConfigMap"},
Name: configMapName,
Namespace: namespace,
})
if existing != nil {
// bootstrap has already been done
return nil
}
log.Infof("Bootstrapping sealed-secrets with a self-generated key")
key, cert, err := crypto.GeneratePrivateKeyAndCert(2048, 10*365*24*time.Hour, "bootstrap.kluctl.io")
if err != nil {
return err
}
certs := []*x509.Certificate{cert}
err = writeKey(k, key, certs, namespace)
if err != nil {
return err
}
return nil
}
func writeKey(k *k8s.K8sCluster, key *rsa.PrivateKey, certs []*x509.Certificate, namespace string) error {
certbytes := []byte{}
for _, cert := range certs {
certbytes = append(certbytes, pem.EncodeToMemory(&pem.Block{Type: certUtil.CertificateBlockType, Bytes: cert.Raw})...)
}
keybytes := pem.EncodeToMemory(&pem.Block{Type: keyutil.RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(key)})
secret := uo.New()
secret.SetK8sGVK(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"})
secret.SetK8sName(secretName)
secret.SetK8sNamespace(namespace)
secret.SetK8sLabel(sealedSecretsKeyLabel, "active")
secret.Object["data"] = map[string]string{
v1.TLSPrivateKeyKey: base64.StdEncoding.EncodeToString(keybytes),
v1.TLSCertKey: base64.StdEncoding.EncodeToString(certbytes),
}
secret.Object["type"] = v1.SecretTypeTLS
configMap := uo.New()
configMap.SetK8sGVK(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ConfigMap"})
configMap.SetK8sName(configMapName)
configMap.SetK8sNamespace(namespace)
configMap.Object["data"] = map[string]string{
v1.TLSCertKey: string(certbytes),
}
_, _, err := k.ReadWrite().PatchObject(secret, k8s.PatchOptions{})
if err != nil {
return err
}
_, _, err = k.ReadWrite().PatchObject(configMap, k8s.PatchOptions{})
if err != nil {
return err
}
return nil
}