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  }