diff --git a/pkg/cert/cacert.go b/pkg/cert/cacert.go new file mode 100644 index 0000000000000000000000000000000000000000..55a5c5305677c770cd9f8196324051280bebf676 --- /dev/null +++ b/pkg/cert/cacert.go @@ -0,0 +1,74 @@ +/* +Copyright 2023 KylinSoft Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cert + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "math/big" + "time" +) + +func (cm *CertificateManager) GenerateCACertificate() error { + + // 生成CA的私钥和公钥 + var err error + cm.CAKey, err = rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return err + } + caPublicKey := &cm.CACert.PublicKey + + // 生成一个介于 0 和 2^128 - 1 之间的随机序列号,并将结果存储在 serialNumber 变量中 + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return err + } + now := time.Now() + + // 设置生成证书的参数,构建CA证书模板 + caTemplate := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"NKD"}, + CommonName: "CA", + }, //这里还可以加很多参数信息 + NotBefore: now, + NotAfter: now.AddDate(10, 0, 0), // 有效期为10年 + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, // openssl 中的 keyUsage 字段 + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, // openssl 中的 extendedKeyUsage = clientAuth, serverAuth 字段 + BasicConstraintsValid: true, + IsCA: true, //表示用于CA + } + + //caCertBytes是生成证书的中间步骤,它用于将证书的二进制表示存储在内存中,以便后续操作可以使用它 + caCertBytes, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, caPublicKey, cm.CAKey) + if err != nil { + return err + } + //cm.CACert表示已经生成的CA证书,用于存储CA证书的详细信息,例如证书序列号、主题、有效期等 + cm.CACert, err = x509.ParseCertificate(caCertBytes) + if err != nil { + return err + } + + return nil + +} diff --git a/pkg/cert/certapi.go b/pkg/cert/certapi.go new file mode 100644 index 0000000000000000000000000000000000000000..a28444e04f98525b20b491c5d79dd129d38784ae --- /dev/null +++ b/pkg/cert/certapi.go @@ -0,0 +1,36 @@ +/* +Copyright 2023 KylinSoft Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cert + +import ( + "crypto/rsa" + "crypto/x509" +) + +type CertificateGenerator interface { + GenerateCACertificate() error + GenerateCertificate(commonName string) error +} + +// CertificateManager 是证书管理器 +type CertificateManager struct { + CAKey *rsa.PrivateKey + CACert *x509.Certificate + ComponentKey *rsa.PrivateKey + ComponentCert *x509.Certificate + ValidDays int +} diff --git a/pkg/cert/certs.go b/pkg/cert/certs.go new file mode 100644 index 0000000000000000000000000000000000000000..838d74d13d1982c6f71de7709ccab3659762b475 --- /dev/null +++ b/pkg/cert/certs.go @@ -0,0 +1,69 @@ +/* +Copyright 2023 KylinSoft Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cert + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "math/big" + "time" +) + +// 使用CA证书和私钥生成组件证书和私钥 +func (cm *CertificateManager) GenerateComponentCertificate(componentName string) error { + + // 创建组件的公钥和私钥 + var err error + cm.ComponentKey, err = rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return err + } + componentPublicKey := &cm.ComponentKey.PublicKey + + // 生成一个介于 0 和 2^128 - 1 之间的随机序列号,并将结果存储在 serialNumber 变量中 + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return err + } + now := time.Now() + + // 组件证书模板 + componentTemplate := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{Organization: []string{"NKD"}, CommonName: componentName}, + NotBefore: now, + NotAfter: time.Now().AddDate(0, 0, cm.ValidDays), // 有效期为1年 + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + } + + // 使用CA证书和私钥生成组件证书 + componentCertBytes, err := x509.CreateCertificate(rand.Reader, componentTemplate, cm.CACert, componentPublicKey, cm.CAKey) + if err != nil { + return err + } + + cm.ComponentCert, err = x509.ParseCertificate(componentCertBytes) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/cert/tools.go b/pkg/cert/tools.go new file mode 100644 index 0000000000000000000000000000000000000000..9eb5a26f9c132af0516607698c4a60b5698bf778 --- /dev/null +++ b/pkg/cert/tools.go @@ -0,0 +1,67 @@ +/* +Copyright 2023 KylinSoft Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cert + +import ( + "crypto/x509" + "encoding/pem" + "io/ioutil" +) + +const certpath = "/etc/kubernetes/pki/" + +// CACertPEM 返回CA证书的PEM格式字节切片 +func (cm *CertificateManager) CACertPEM() []byte { + return pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: cm.CACert.Raw, + }) +} + +// CAKeyPEM 返回CA私钥的PEM格式字节切片 +func (cm *CertificateManager) CAKeyPEM() []byte { + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(cm.CAKey), + }) +} + +// ComponentCertPEM 返回组件证书的PEM格式字节切片 +func (cm *CertificateManager) ComponentCertPEM() []byte { + return pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: cm.ComponentCert.Raw, + }) +} + +// ComponentKeyPEM 返回组件私钥的PEM格式字节切片 +func (cm *CertificateManager) ComponentKeyPEM() []byte { + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(cm.ComponentKey), + }) +} + +// SaveCertificateToFile 将证书保存到文件 +func SaveCertificateToFile(filename string, certPEM []byte) error { + return ioutil.WriteFile(certpath+filename, certPEM, 0644) +} + +// SavePrivateKeyToFile 将私钥保存到文件 +func SavePrivateKeyToFile(filename string, keyPEM []byte) error { + return ioutil.WriteFile(certpath+filename, keyPEM, 0600) +}