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
package kubeconfig
import (
"errors"
"fmt"
"net/url"
"sigs.k8s.io/yaml"
)
var ErrNotHTTPS = errors.New("kubeconfig: server must be https")
type ClientCertInput struct {
ClusterName string
Server string
CACertPEM []byte
CertPEM []byte
KeyPEM []byte
}
func BuildClientCert(in ClientCertInput) (string, error) {
if in.ClusterName == "" {
return "", errors.New("kubeconfig: empty cluster name")
}
if in.Server == "" {
return "", errors.New("kubeconfig: empty server")
}
u, err := url.Parse(in.Server)
if err != nil {
return "", fmt.Errorf("kubeconfig: unparseable server: %w", err)
}
if u.Scheme != "https" {
return "", fmt.Errorf("%w (got %q)", ErrNotHTTPS, u.Scheme)
}
if len(in.CertPEM) == 0 || len(in.KeyPEM) == 0 {
return "", errors.New("kubeconfig: a client certificate and its key are required")
}
cluster := map[string]any{"server": in.Server}
if len(in.CACertPEM) > 0 {
cluster["certificate-authority-data"] = in.CACertPEM
}
user := map[string]any{
"client-certificate-data": in.CertPEM,
"client-key-data": in.KeyPEM,
}
doc := map[string]any{
"apiVersion": "v1",
"kind": "Config",
"clusters": []map[string]any{
{"name": in.ClusterName, "cluster": cluster},
},
"users": []map[string]any{
{"name": in.ClusterName, "user": user},
},
"contexts": []map[string]any{
{"name": in.ClusterName, "context": map[string]any{
"cluster": in.ClusterName,
"user": in.ClusterName,
}},
},
"current-context": in.ClusterName,
}
raw, err := yaml.Marshal(doc)
if err != nil {
return "", fmt.Errorf("kubeconfig: marshal: %w", err)
}
return string(raw), nil
}