-
Notifications
You must be signed in to change notification settings - Fork 7
/
kubeconfig.go
150 lines (141 loc) · 4.75 KB
/
kubeconfig.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
package kommons
import (
"encoding/base64"
"fmt"
"strings"
"time"
certs "github.com/flanksource/commons/certs"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
)
func CreateKubeConfig(clusterName string, ca certs.CertificateAuthority, endpoint string, group string, user string, expiry time.Duration) ([]byte, error) {
contextName := fmt.Sprintf("%s@%s", user, clusterName)
cert := certs.NewCertificateBuilder(user).Organization(group).Client().Certificate
if cert.X509.PublicKey == nil && cert.PrivateKey != nil {
cert.X509.PublicKey = cert.PrivateKey.Public()
}
signed, err := ca.Sign(cert.X509, expiry)
if err != nil {
return nil, fmt.Errorf("createKubeConfig: failed to sign certificate: %v", err)
}
cert = &certs.Certificate{
X509: signed,
PrivateKey: cert.PrivateKey,
}
if !strings.Contains(endpoint, ":") {
endpoint = endpoint + ":6443"
}
cfg := api.Config{
Clusters: map[string]*api.Cluster{
clusterName: {
Server: "https://" + endpoint,
InsecureSkipTLSVerify: true,
// The CA used for signing the client certificate is not the same as the
// as the CA (kubernetes-ca) that signed the api-server cert. The kubernetes-ca
// is ephemeral.
// TODO dynamically download CA from master server
// CertificateAuthorityData: []byte(platform.Certificates.CA.X509),
},
},
Contexts: map[string]*api.Context{
contextName: {
Cluster: clusterName,
AuthInfo: contextName,
Namespace: "kube-system",
},
},
AuthInfos: map[string]*api.AuthInfo{
contextName: {
ClientKeyData: cert.EncodedPrivateKey(),
ClientCertificateData: cert.EncodedCertificate(),
},
},
CurrentContext: contextName,
}
return clientcmd.Write(cfg)
}
func CreateOIDCKubeConfig(clusterName string, ca certs.CertificateAuthority, endpoint, idpURL, idToken, accessToken, refreshToken string) ([]byte, error) {
if !strings.HasPrefix("https://", endpoint) {
endpoint = "https://" + endpoint
}
if !strings.HasPrefix("https://", idpURL) {
idpURL = "https://" + idpURL
}
cfg := api.Config{
Clusters: map[string]*api.Cluster{
clusterName: {
Server: endpoint + ":6443",
InsecureSkipTLSVerify: true,
},
},
Contexts: map[string]*api.Context{
clusterName: {
Cluster: clusterName,
AuthInfo: "sso@" + clusterName,
},
},
AuthInfos: map[string]*api.AuthInfo{
"sso@" + clusterName: {
AuthProvider: &api.AuthProviderConfig{
Name: "oidc",
Config: map[string]string{
"client-id": "kubernetes",
"client-secret": "ZXhhbXBsZS1hcHAtc2VjcmV0",
"extra-scopes": "offline_access openid profile email groups",
"idp-certificate-authority-data": base64.StdEncoding.EncodeToString(ca.GetPublicChain()[0].EncodedCertificate()),
"idp-issuer-url": idpURL,
"id-token": idToken,
"access-token": accessToken,
"refresh-token": refreshToken,
},
},
},
},
CurrentContext: clusterName,
}
return clientcmd.Write(cfg)
}
// CreateMultiKubeConfig creates a kubeconfig file contents for a map of
// cluster name -> cluster API endpoint hosts, all with a shared
// user name, group and cert expiry.
// NOTE: these clusters all need to share the same plaform CA
func CreateMultiKubeConfig(ca certs.CertificateAuthority, clusters map[string]string, group string, user string, expiry time.Duration) ([]byte, error) {
if len(clusters) < 1 {
return []byte{}, fmt.Errorf("CreateMultiKubeConfig failed since it was given an empty cluster map")
}
cfg := api.Config{
Clusters: map[string]*api.Cluster{},
Contexts: map[string]*api.Context{},
AuthInfos: map[string]*api.AuthInfo{},
CurrentContext: "",
}
for clusterName, endpoint := range clusters {
cert := certs.NewCertificateBuilder(user).Organization(group).Client().Certificate
if cert.X509.PublicKey == nil && cert.PrivateKey != nil {
cert.X509.PublicKey = cert.PrivateKey.Public()
}
signed, err := ca.Sign(cert.X509, expiry)
if err != nil {
return nil, fmt.Errorf("createKubeConfig: failed to sign certificate: %v", err)
}
cert = &certs.Certificate{
X509: signed,
PrivateKey: cert.PrivateKey,
}
cfg.Clusters[clusterName] = &api.Cluster{
Server: endpoint,
InsecureSkipTLSVerify: true,
}
context := fmt.Sprintf("%s@%s", user, clusterName)
cfg.Contexts[clusterName] = &api.Context{
Cluster: clusterName,
AuthInfo: context,
Namespace: "kube-system", //TODO: verify
}
cfg.AuthInfos[context] = &api.AuthInfo{
ClientKeyData: cert.EncodedPrivateKey(),
ClientCertificateData: cert.EncodedCertificate(),
}
}
return clientcmd.Write(cfg)
}