github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/cert/kube_certs.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cert 16 17 import ( 18 "crypto" 19 "crypto/x509" 20 "fmt" 21 "net" 22 "os" 23 "path" 24 25 "github.com/alibaba/sealer/logger" 26 ) 27 28 var ( 29 KubernetesDir = "/etc/kubernetes" 30 KubeDefaultCertPath = "/etc/kubernetes/pki" 31 kubeDefaultCertEtcdPath = "/etc/kubernetes/pki/etcd" 32 ) 33 34 func GetUserHomeDir() string { 35 home, err := os.UserHomeDir() 36 if err != nil { 37 logger.Error(err) 38 return "" 39 } 40 return home 41 } 42 43 func CaList(CertPath, CertEtcdPath string) []Config { 44 return []Config{ 45 { 46 Path: CertPath, 47 DefaultPath: KubeDefaultCertPath, 48 BaseName: "ca", 49 CommonName: "kubernetes", 50 Organization: nil, 51 Year: 100, 52 AltNames: AltNames{}, 53 Usages: nil, 54 }, 55 { 56 Path: CertPath, 57 DefaultPath: KubeDefaultCertPath, 58 BaseName: "front-proxy-ca", 59 CommonName: "front-proxy-ca", 60 Organization: nil, 61 Year: 100, 62 AltNames: AltNames{}, 63 Usages: nil, 64 }, 65 { 66 Path: CertEtcdPath, 67 DefaultPath: kubeDefaultCertEtcdPath, 68 BaseName: "ca", 69 CommonName: "etcd-ca", 70 Organization: nil, 71 Year: 100, 72 AltNames: AltNames{}, 73 Usages: nil, 74 }, 75 } 76 } 77 78 func certList(CertPath, CertEtcdPath string) []Config { 79 return []Config{ 80 { 81 Path: CertPath, 82 DefaultPath: KubeDefaultCertPath, 83 BaseName: "apiserver", 84 CAName: "kubernetes", 85 CommonName: "kube-apiserver", 86 Organization: nil, 87 Year: 100, 88 AltNames: AltNames{ 89 DNSNames: map[string]string{ 90 "localhost": "localhost", 91 "kubernetes": "kubernetes", 92 "kubernetes.default": "kubernetes.default", 93 "kubernetes.default.svc": "kubernetes.default.svc", 94 }, 95 IPs: map[string]net.IP{ 96 "127.0.0.1": net.IPv4(127, 0, 0, 1), 97 }, 98 }, 99 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 100 }, 101 { 102 Path: CertPath, 103 DefaultPath: KubeDefaultCertPath, 104 BaseName: "apiserver-kubelet-client", 105 CAName: "kubernetes", 106 CommonName: "kube-apiserver-kubelet-client", 107 Organization: []string{"system:masters"}, 108 Year: 100, 109 AltNames: AltNames{}, 110 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 111 }, 112 { 113 Path: CertPath, 114 DefaultPath: KubeDefaultCertPath, 115 BaseName: "front-proxy-client", 116 CAName: "front-proxy-ca", 117 CommonName: "front-proxy-client", 118 Organization: nil, 119 Year: 100, 120 AltNames: AltNames{}, 121 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 122 }, 123 { 124 Path: CertPath, 125 DefaultPath: KubeDefaultCertPath, 126 BaseName: "apiserver-etcd-client", 127 CAName: "etcd-ca", 128 CommonName: "kube-apiserver-etcd-client", 129 Organization: []string{"system:masters"}, 130 Year: 100, 131 AltNames: AltNames{}, 132 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 133 }, 134 { 135 Path: CertEtcdPath, 136 DefaultPath: kubeDefaultCertEtcdPath, 137 BaseName: "server", 138 CAName: "etcd-ca", 139 CommonName: "etcd", // kubeadm using node name as common name cc.CommonName = mc.NodeRegistration.Name 140 Organization: nil, 141 Year: 100, 142 AltNames: AltNames{}, // need set altNames 143 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 144 }, 145 { 146 Path: CertEtcdPath, 147 DefaultPath: kubeDefaultCertEtcdPath, 148 BaseName: "peer", 149 CAName: "etcd-ca", 150 CommonName: "etcd-peer", // change this in filter 151 Organization: nil, 152 Year: 100, 153 AltNames: AltNames{}, // change this in filter 154 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 155 }, 156 { 157 Path: CertEtcdPath, 158 DefaultPath: kubeDefaultCertEtcdPath, 159 BaseName: "healthcheck-client", 160 CAName: "etcd-ca", 161 CommonName: "kube-etcd-healthcheck-client", 162 Organization: []string{"system:masters"}, 163 Year: 100, 164 AltNames: AltNames{}, 165 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 166 }, 167 } 168 } 169 170 type MetaData struct { 171 APIServer AltNames 172 NodeName string 173 NodeIP string 174 DNSDomain string 175 CertPath string 176 CertEtcdPath string 177 } 178 179 const ( 180 APIserverCert = iota 181 APIserverKubeletClientCert 182 FrontProxyClientCert 183 APIserverEtcdClientCert 184 EtcdServerCert 185 EtcdPeerCert 186 EtcdHealthcheckClientCert 187 ) 188 189 // apiServerIPAndDomains = MasterIP + VIP + CertSANS 暂时只有apiserver, 记得把cluster.local后缀加到apiServerIPAndDOmas里先 190 func NewMetaData(certPATH, certEtcdPATH string, apiServerIPAndDomains []string, SvcCIDR, nodeName, nodeIP, DNSDomain string) (*MetaData, error) { 191 data := &MetaData{} 192 data.CertPath = certPATH 193 data.CertEtcdPath = certEtcdPATH 194 data.DNSDomain = DNSDomain 195 data.APIServer.IPs = make(map[string]net.IP) 196 data.APIServer.DNSNames = make(map[string]string) 197 svcFirstIP, _, err := net.ParseCIDR(SvcCIDR) 198 if err != nil { 199 return nil, err 200 } 201 svcFirstIP[len(svcFirstIP)-1]++ //取svc第一个ip 202 data.APIServer.IPs[svcFirstIP.String()] = svcFirstIP 203 204 for _, altName := range apiServerIPAndDomains { 205 ip := net.ParseIP(altName) 206 if ip != nil { 207 data.APIServer.IPs[ip.String()] = ip 208 continue 209 } 210 data.APIServer.DNSNames[altName] = altName 211 } 212 213 if ip := net.ParseIP(nodeIP); ip != nil { 214 data.APIServer.IPs[ip.String()] = ip 215 } 216 217 data.NodeIP = nodeIP 218 data.NodeName = nodeName 219 return data, nil 220 } 221 222 func (meta *MetaData) apiServerAltName(certList *[]Config) { 223 for _, dns := range meta.APIServer.DNSNames { 224 (*certList)[APIserverCert].AltNames.DNSNames[dns] = dns 225 } 226 227 svcDNS := fmt.Sprintf("kubernetes.default.svc.%s", meta.DNSDomain) 228 (*certList)[APIserverCert].AltNames.DNSNames[svcDNS] = svcDNS 229 (*certList)[APIserverCert].AltNames.DNSNames[meta.NodeName] = meta.NodeName 230 231 for _, ip := range meta.APIServer.IPs { 232 (*certList)[APIserverCert].AltNames.IPs[ip.String()] = ip 233 } 234 logger.Info("APIserver altNames : ", (*certList)[APIserverCert].AltNames) 235 } 236 237 func (meta *MetaData) etcdAltAndCommonName(certList *[]Config) { 238 altname := AltNames{ 239 DNSNames: map[string]string{ 240 "localhost": "localhost", 241 meta.NodeName: meta.NodeName, 242 }, 243 IPs: map[string]net.IP{ 244 net.IPv4(127, 0, 0, 1).String(): net.IPv4(127, 0, 0, 1), 245 net.ParseIP(meta.NodeIP).To4().String(): net.ParseIP(meta.NodeIP).To4(), 246 net.IPv6loopback.String(): net.IPv6loopback, 247 }, 248 } 249 (*certList)[EtcdServerCert].CommonName = meta.NodeName 250 (*certList)[EtcdServerCert].AltNames = altname 251 (*certList)[EtcdPeerCert].CommonName = meta.NodeName 252 (*certList)[EtcdPeerCert].AltNames = altname 253 254 logger.Info("Etcd altnames : %v, commonName : %s", (*certList)[EtcdPeerCert].AltNames, (*certList)[EtcdPeerCert].CommonName) 255 } 256 257 // create sa.key sa.pub for service Account 258 func (meta *MetaData) generatorServiceAccountKeyPaire() error { 259 dir := meta.CertPath 260 _, err := os.Stat(path.Join(dir, "sa.key")) 261 if !os.IsNotExist(err) { 262 logger.Info("sa.key sa.pub already exist") 263 return nil 264 } 265 266 key, err := NewPrivateKey(x509.RSA) 267 if err != nil { 268 return err 269 } 270 pub := key.Public() 271 272 err = WriteKey(dir, "sa", key) 273 if err != nil { 274 return err 275 } 276 277 return WritePublicKey(dir, "sa", pub) 278 } 279 280 func (meta *MetaData) GenerateAll() error { 281 cas := CaList(meta.CertPath, meta.CertEtcdPath) 282 certs := certList(meta.CertPath, meta.CertEtcdPath) 283 meta.apiServerAltName(&certs) 284 meta.etcdAltAndCommonName(&certs) 285 if err := meta.generatorServiceAccountKeyPaire(); err != nil { 286 return err 287 } 288 289 CACerts := map[string]*x509.Certificate{} 290 CAKeys := map[string]crypto.Signer{} 291 for _, ca := range cas { 292 caCert, caKey, err := NewCaCertAndKey(ca) 293 if err != nil { 294 return err 295 } 296 CACerts[ca.CommonName] = caCert 297 CAKeys[ca.CommonName] = caKey 298 299 err = WriteCertAndKey(ca.Path, ca.BaseName, caCert, caKey) 300 if err != nil { 301 return err 302 } 303 } 304 305 for _, cert := range certs { 306 caCert, ok := CACerts[cert.CAName] 307 if !ok { 308 return fmt.Errorf("root ca cert not found %s", cert.CAName) 309 } 310 caKey, ok := CAKeys[cert.CAName] 311 if !ok { 312 return fmt.Errorf("root ca key not found %s", cert.CAName) 313 } 314 315 Cert, Key, err := NewCaCertAndKeyFromRoot(cert, caCert, caKey) 316 if err != nil { 317 return err 318 } 319 err = WriteCertAndKey(cert.Path, cert.BaseName, Cert, Key) 320 if err != nil { 321 return err 322 } 323 } 324 return nil 325 }