mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
util/certificates: Add CSR utility function.
This commit is contained in:
parent
9d2a5fe5e8
commit
5801fa5f4d
@ -17,9 +17,18 @@ limitations under the License.
|
||||
package certificates
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
)
|
||||
@ -38,3 +47,96 @@ func ParseCertificateRequestObject(obj *certificates.CertificateSigningRequest)
|
||||
}
|
||||
return csr, nil
|
||||
}
|
||||
|
||||
// NewCertificateRequest generates a PEM-encoded CSR using the supplied private
|
||||
// key file, subject, and SANs. If the private key file does not exist, it generates a
|
||||
// new ECDSA P256 key to use and writes it to the keyFile path.
|
||||
func NewCertificateRequest(keyFile string, subject *pkix.Name, dnsSANs []string, ipSANs []net.IP) ([]byte, error) {
|
||||
var privateKey interface{}
|
||||
|
||||
if _, err := os.Stat(keyFile); os.IsNotExist(err) {
|
||||
privateKey, err = ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ecdsaKey := privateKey.(*ecdsa.PrivateKey)
|
||||
derBytes, err := x509.MarshalECPrivateKey(ecdsaKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pemBlock := &pem.Block{
|
||||
Type: "EC PRIVATE KEY",
|
||||
Bytes: derBytes,
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(keyFile, pem.EncodeToMemory(pemBlock), os.FileMode(0600))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
keyBytes, err := ioutil.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var block *pem.Block
|
||||
var sigType x509.SignatureAlgorithm
|
||||
|
||||
block, _ = pem.Decode(keyBytes)
|
||||
|
||||
switch block.Type {
|
||||
case "EC PRIVATE KEY":
|
||||
privateKey, err = x509.ParseECPrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecdsaKey := privateKey.(*ecdsa.PrivateKey)
|
||||
switch ecdsaKey.Curve.Params().BitSize {
|
||||
case 521:
|
||||
sigType = x509.ECDSAWithSHA512
|
||||
case 384:
|
||||
sigType = x509.ECDSAWithSHA384
|
||||
default:
|
||||
sigType = x509.ECDSAWithSHA256
|
||||
}
|
||||
case "RSA PRIVATE KEY":
|
||||
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rsaKey := privateKey.(*rsa.PrivateKey)
|
||||
keySize := rsaKey.N.BitLen()
|
||||
switch {
|
||||
case keySize >= 4096:
|
||||
sigType = x509.SHA512WithRSA
|
||||
case keySize >= 3072:
|
||||
sigType = x509.SHA384WithRSA
|
||||
default:
|
||||
sigType = x509.SHA256WithRSA
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported key type: %s", block.Type)
|
||||
}
|
||||
|
||||
template := &x509.CertificateRequest{
|
||||
Subject: *subject,
|
||||
SignatureAlgorithm: sigType,
|
||||
DNSNames: dnsSANs,
|
||||
IPAddresses: ipSANs,
|
||||
}
|
||||
|
||||
csr, err := x509.CreateCertificateRequest(cryptorand.Reader, template, privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pemBlock := &pem.Block{
|
||||
Type: "CERTIFICATE REQUEST",
|
||||
Bytes: csr,
|
||||
}
|
||||
|
||||
return pem.EncodeToMemory(pemBlock), nil
|
||||
}
|
||||
|
21
pkg/util/certificates/csr_test.go
Normal file
21
pkg/util/certificates/csr_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package certificates
|
||||
|
||||
import (
|
||||
"crypto/x509/pkix"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewCertificateRequest(t *testing.T) {
|
||||
keyFile := "testdata/dontUseThisKey.pem"
|
||||
subject := &pkix.Name{
|
||||
CommonName: "kube-worker",
|
||||
}
|
||||
dnsSANs := []string{"localhost"}
|
||||
ipSANs := []net.IP{net.ParseIP("127.0.0.1")}
|
||||
|
||||
_, err := NewCertificateRequest(keyFile, subject, dnsSANs, ipSANs)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
6
pkg/util/certificates/testdata/dontUseThisKey.pem
vendored
Normal file
6
pkg/util/certificates/testdata/dontUseThisKey.pem
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MIGkAgEBBDAPEbSXwyDfWf0+61Oofd7aHkmdX69mrzD2Xb1CHF5syfsoRIhnG0dJ
|
||||
ozBulPZCDDWgBwYFK4EEACKhZANiAATjlMJAtKhEPqU/i7MsrgKcK/RmXHC6He7W
|
||||
0p69+9qFXg2raJ9zvvbKxkiu2ELOYRDAz0utcFTBOIgoUJEzBVmsjZQ7dvFa1BKP
|
||||
Ym7MFAKG3O2espBqXn+audgdHGh5B0I=
|
||||
-----END EC PRIVATE KEY-----
|
Loading…
Reference in New Issue
Block a user