mirror of https://github.com/kubernetes/kops.git
Merge pull request #8988 from johngmyers/private-key-size
Use KOPS_RSA_PRIVATE_KEY_SIZE for more keys
This commit is contained in:
commit
936d656b4c
|
@ -112,7 +112,6 @@ k8s.io/kops/pkg/nodeidentity/gce
|
|||
k8s.io/kops/pkg/nodeidentity/openstack
|
||||
k8s.io/kops/pkg/nodelabels
|
||||
k8s.io/kops/pkg/pki
|
||||
k8s.io/kops/pkg/pkiutil
|
||||
k8s.io/kops/pkg/pretty
|
||||
k8s.io/kops/pkg/rbac
|
||||
k8s.io/kops/pkg/resources
|
||||
|
|
|
@ -55,7 +55,6 @@ go_library(
|
|||
"//pkg/kubemanifest:go_default_library",
|
||||
"//pkg/nodelabels:go_default_library",
|
||||
"//pkg/pki:go_default_library",
|
||||
"//pkg/pkiutil:go_default_library",
|
||||
"//pkg/rbac:go_default_library",
|
||||
"//pkg/systemd:go_default_library",
|
||||
"//pkg/tokens:go_default_library",
|
||||
|
@ -78,7 +77,6 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
|
|
|
@ -17,17 +17,16 @@ limitations under the License.
|
|||
package model
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kops/pkg/pkiutil"
|
||||
"k8s.io/kops/pkg/pki"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||
)
|
||||
|
@ -147,8 +146,7 @@ func (b *CiliumBuilder) buildCiliumEtcdSecrets(c *fi.ModelBuilderContext) error
|
|||
|
||||
{
|
||||
p := filepath.Join(dir, "etcd-ca.crt")
|
||||
certBytes := pkiutil.EncodeCertPEM(etcdClientsCACertificate.Certificate)
|
||||
if err := ioutil.WriteFile(p, certBytes, 0644); err != nil {
|
||||
if err := etcdClientsCACertificate.WriteToFile(p, 0644); err != nil {
|
||||
return fmt.Errorf("error writing certificate key file %q: %v", p, err)
|
||||
}
|
||||
}
|
||||
|
@ -156,39 +154,34 @@ func (b *CiliumBuilder) buildCiliumEtcdSecrets(c *fi.ModelBuilderContext) error
|
|||
name := "etcd-client"
|
||||
|
||||
humanName := dir + "/" + name
|
||||
privateKey, err := pkiutil.NewPrivateKey()
|
||||
privateKey, err := pki.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create private key %q: %v", humanName, err)
|
||||
}
|
||||
privateKeyBytes := pkiutil.EncodePrivateKeyPEM(privateKey)
|
||||
|
||||
certConfig := &certutil.Config{
|
||||
CommonName: "cilium",
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
signingKey, ok := etcdClientsCAPrivateKey.Key.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("etcd-clients-ca private key had unexpected type %T", etcdClientsCAPrivateKey.Key)
|
||||
certTmpl := &x509.Certificate{
|
||||
Subject: pkix.Name{
|
||||
CommonName: "cilium",
|
||||
},
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365).UTC(),
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
klog.Infof("signing certificate for %q", humanName)
|
||||
cert, err := pkiutil.NewSignedCert(certConfig, privateKey, etcdClientsCACertificate.Certificate, signingKey)
|
||||
cert, err := pki.SignNewCertificate(privateKey, certTmpl, etcdClientsCACertificate.Certificate, etcdClientsCAPrivateKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error signing certificate for %q: %v", humanName, err)
|
||||
}
|
||||
|
||||
certBytes := pkiutil.EncodeCertPEM(cert)
|
||||
|
||||
p := filepath.Join(dir, name)
|
||||
{
|
||||
if err := ioutil.WriteFile(p+".crt", certBytes, 0644); err != nil {
|
||||
if err := cert.WriteToFile(p+".crt", 0644); err != nil {
|
||||
return fmt.Errorf("error writing certificate key file %q: %v", p+".crt", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if err := ioutil.WriteFile(p+".key", privateKeyBytes, 0600); err != nil {
|
||||
if err := privateKey.WriteToFile(p+".key", 0600); err != nil {
|
||||
return fmt.Errorf("error writing private key file %q: %v", p+".key", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,15 @@ limitations under the License.
|
|||
package model
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kops/pkg/pkiutil"
|
||||
"k8s.io/kops/pkg/pki"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
)
|
||||
|
||||
|
@ -106,8 +105,7 @@ func (b *EtcdManagerTLSBuilder) buildKubeAPIServerKeypair() error {
|
|||
|
||||
{
|
||||
p := filepath.Join(dir, "etcd-ca.crt")
|
||||
certBytes := pkiutil.EncodeCertPEM(etcdClientsCACertificate.Certificate)
|
||||
if err := ioutil.WriteFile(p, certBytes, 0644); err != nil {
|
||||
if err := etcdClientsCACertificate.WriteToFile(p, 0644); err != nil {
|
||||
return fmt.Errorf("error writing certificate key file %q: %v", p, err)
|
||||
}
|
||||
}
|
||||
|
@ -115,39 +113,34 @@ func (b *EtcdManagerTLSBuilder) buildKubeAPIServerKeypair() error {
|
|||
name := "etcd-client"
|
||||
|
||||
humanName := dir + "/" + name
|
||||
privateKey, err := pkiutil.NewPrivateKey()
|
||||
privateKey, err := pki.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create private key %q: %v", humanName, err)
|
||||
}
|
||||
privateKeyBytes := pkiutil.EncodePrivateKeyPEM(privateKey)
|
||||
|
||||
certConfig := &certutil.Config{
|
||||
CommonName: "kube-apiserver",
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
signingKey, ok := etcdClientsCAPrivateKey.Key.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("etcd-clients-ca private key had unexpected type %T", etcdClientsCAPrivateKey.Key)
|
||||
certTmpl := &x509.Certificate{
|
||||
Subject: pkix.Name{
|
||||
CommonName: "kube-apiserver",
|
||||
},
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365).UTC(),
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
klog.Infof("signing certificate for %q", humanName)
|
||||
cert, err := pkiutil.NewSignedCert(certConfig, privateKey, etcdClientsCACertificate.Certificate, signingKey)
|
||||
cert, err := pki.SignNewCertificate(privateKey, certTmpl, etcdClientsCACertificate.Certificate, etcdClientsCAPrivateKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error signing certificate for %q: %v", humanName, err)
|
||||
}
|
||||
|
||||
certBytes := pkiutil.EncodeCertPEM(cert)
|
||||
|
||||
p := filepath.Join(dir, name)
|
||||
{
|
||||
if err := ioutil.WriteFile(p+".crt", certBytes, 0644); err != nil {
|
||||
if err := cert.WriteToFile(p+".crt", 0644); err != nil {
|
||||
return fmt.Errorf("error writing certificate key file %q: %v", p+".crt", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if err := ioutil.WriteFile(p+".key", privateKeyBytes, 0600); err != nil {
|
||||
if err := privateKey.WriteToFile(p+".key", 0600); err != nil {
|
||||
return fmt.Errorf("error writing private key file %q: %v", p+".key", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,4 +24,8 @@ go_test(
|
|||
"sshkey_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
@ -150,3 +151,15 @@ func (c *Certificate) WriteTo(w io.Writer) (int64, error) {
|
|||
}
|
||||
return b.WriteTo(w)
|
||||
}
|
||||
|
||||
func (c *Certificate) WriteToFile(filename string, perm os.FileMode) error {
|
||||
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.WriteTo(f)
|
||||
if err1 := f.Close(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,62 +23,128 @@ import (
|
|||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGenerateCertificate(t *testing.T) {
|
||||
data := "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4JwpEprZ5n8RIEt6jT2lAh+UDgRgx/4px21gjgywQivYHVxH\nAZexVb/E9pBa9Q2G9B1Q7TCO7YsUVRQy4JMDZVt+McFnWVwexnqBYFNcVjkEmDgA\ngvCYGE0P9d/RwRL4KuLHo+u6fv7P0jXMN+CpOxyLhYZZNa0ZOZDHsSiJSQSj9WGF\nGHrbCf0KVDpKieR1uBqHrRO+mLR5zkX2L58m74kjK4dsBhmjeq/7OAoTmiG2QgJ/\nP2IjyhiA2mRqY+hl55lwEUV/0yHYEkJC8LdGkwwZz2eF77aSPGmi/A2CSKgMwDTx\n9m+P7jcpWreYw6NG9BueGoDIve/tgFKwvVFF6QIDAQABAoIBAA0ktjaTfyrAxsTI\nBezb7Zr5NBW55dvuII299cd6MJo+rI/TRYhvUv48kY8IFXp/hyUjzgeDLunxmIf9\n/Zgsoic9Ol44/g45mMduhcGYPzAAeCdcJ5OB9rR9VfDCXyjYLlN8H8iU0734tTqM\n0V13tQ9zdSqkGPZOIcq/kR/pylbOZaQMe97BTlsAnOMSMKDgnftY4122Lq3GYy+t\nvpr+bKVaQZwvkLoSU3rECCaKaghgwCyX7jft9aEkhdJv+KlwbsGY6WErvxOaLWHd\ncuMQjGapY1Fa/4UD00mvrA260NyKfzrp6+P46RrVMwEYRJMIQ8YBAk6N6Hh7dc0G\n8Z6i1m0CgYEA9HeCJR0TSwbIQ1bDXUrzpftHuidG5BnSBtax/ND9qIPhR/FBW5nj\n22nwLc48KkyirlfIULd0ae4qVXJn7wfYcuX/cJMLDmSVtlM5Dzmi/91xRiFgIzx1\nAsbBzaFjISP2HpSgL+e9FtSXaaqeZVrflitVhYKUpI/AKV31qGHf04sCgYEA6zTV\n99Sb49Wdlns5IgsfnXl6ToRttB18lfEKcVfjAM4frnkk06JpFAZeR+9GGKUXZHqs\nz2qcplw4d/moCC6p3rYPBMLXsrGNEUFZqBlgz72QA6BBq3X0Cg1Bc2ZbK5VIzwkg\nST2SSux6ccROfgULmN5ZiLOtdUKNEZpFF3i3qtsCgYADT/s7dYFlatobz3kmMnXK\nsfTu2MllHdRys0YGHu7Q8biDuQkhrJwhxPW0KS83g4JQym+0aEfzh36bWcl+u6R7\nKhKj+9oSf9pndgk345gJz35RbPJYh+EuAHNvzdgCAvK6x1jETWeKf6btj5pF1U1i\nQ4QNIw/QiwIXjWZeubTGsQKBgQCbduLu2rLnlyyAaJZM8DlHZyH2gAXbBZpxqU8T\nt9mtkJDUS/KRiEoYGFV9CqS0aXrayVMsDfXY6B/S/UuZjO5u7LtklDzqOf1aKG3Q\ndGXPKibknqqJYH+bnUNjuYYNerETV57lijMGHuSYCf8vwLn3oxBfERRX61M/DU8Z\nworz/QKBgQDCTJI2+jdXg26XuYUmM4XXfnocfzAXhXBULt1nENcogNf1fcptAVtu\nBAiz4/HipQKqoWVUYmxfgbbLRKKLK0s0lOWKbYdVjhEm/m2ZU8wtXTagNwkIGoyq\nY/C1Lox4f1ROJnCjc/hfcOjcxX5M8A8peecHWlVtUPKTJgxQ7oMKcw==\n-----END RSA PRIVATE KEY-----\n"
|
||||
publicKeyData := "-----BEGIN RSA PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4JwpEprZ5n8RIEt6jT2l\nAh+UDgRgx/4px21gjgywQivYHVxHAZexVb/E9pBa9Q2G9B1Q7TCO7YsUVRQy4JMD\nZVt+McFnWVwexnqBYFNcVjkEmDgAgvCYGE0P9d/RwRL4KuLHo+u6fv7P0jXMN+Cp\nOxyLhYZZNa0ZOZDHsSiJSQSj9WGFGHrbCf0KVDpKieR1uBqHrRO+mLR5zkX2L58m\n74kjK4dsBhmjeq/7OAoTmiG2QgJ/P2IjyhiA2mRqY+hl55lwEUV/0yHYEkJC8LdG\nkwwZz2eF77aSPGmi/A2CSKgMwDTx9m+P7jcpWreYw6NG9BueGoDIve/tgFKwvVFF\n6QIDAQAB\n-----END RSA PUBLIC KEY-----\n"
|
||||
signerCertData := "-----BEGIN CERTIFICATE-----\nMIIBTDCB96ADAgECAhBjHcUz56MCdYqSYy7TYNe3MA0GCSqGSIb3DQEBCwUAMBUx\nEzARBgNVBAMTCnNlbGZzaWduZWQwHhcNMjAwNDI0MjMzNDM5WhcNMzAwNDI0MjMz\nNDM5WjAVMRMwEQYDVQQDEwpzZWxmc2lnbmVkMFwwDQYJKoZIhvcNAQEBBQADSwAw\nSAJBAL5zWUObMH5dBestQgDIa4B/rT7Cc21AK+B7gPvMcEfIWow5u6QE+EyhRTPv\n727oY+2MU9e4vq5RXBG7hneuBoECAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgEGMA8G\nA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADQQBLUFz7gDKRRyjEwgRZnZzP\nOma9WIgOjX36OFllyGkspu1ZcW/EtGEGNXqtMsm1QmG38Lh7Nkehb5xoAmm6hkFA\n-----END CERTIFICATE-----"
|
||||
signerKeyData := "-----BEGIN RSA PRIVATE KEY-----\nMIIBOQIBAAJBAL5zWUObMH5dBestQgDIa4B/rT7Cc21AK+B7gPvMcEfIWow5u6QE\n+EyhRTPv727oY+2MU9e4vq5RXBG7hneuBoECAwEAAQJAZ9ZUUPwIEJ1/YJ4oYmzj\n0AfM2W8DqAlY4ufzh1YL0daGUkiuQg0p6CeqFqgnQluZ3bcXPG8iBQp1EeekULFL\nAQIhAOGbozbIEI+26Ehv41aCMWkKO1R05AVzmoNp1T2Ke6npAiEA2BtEPRSdhLek\nZR7vhk7KNTJ2XExJ+T/l2849EsojANkCIAWYD1b3ZPm7Rk0tgQyPE9yP5WK1t0Wv\nVSB3ClOJUIGpAiAfUBQbJZmNWW6gmFLsiw4RlzY/OW6ehvuvVbrTtiZMQQIgD2zY\nU2EjvR0zY5PsJYbcLHa9ieCA5ni/VW70WKn9K5s=\n-----END RSA PRIVATE KEY-----"
|
||||
|
||||
key, err := ParsePEMPrivateKey([]byte(data))
|
||||
if err != nil {
|
||||
t.Fatalf("error from ParsePEMPrivateKey: %v", err)
|
||||
}
|
||||
require.NoError(t, err, "ParsePEMPrivateKey")
|
||||
signerKey, err := ParsePEMPrivateKey([]byte(signerKeyData))
|
||||
require.NoError(t, err, "ParsePEMPrivateKey")
|
||||
|
||||
{
|
||||
var b bytes.Buffer
|
||||
pkData, err := x509.MarshalPKIXPublicKey(key.Key.(*rsa.PrivateKey).Public())
|
||||
if err != nil {
|
||||
t.Fatalf("error from MarshalPKIXPublicKey: %v", err)
|
||||
}
|
||||
if err := pem.Encode(&b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pkData}); err != nil {
|
||||
t.Fatalf("error serializing public key")
|
||||
}
|
||||
require.NoError(t, err, "MarshalPKIXPublicKey")
|
||||
|
||||
if b.String() != publicKeyData {
|
||||
t.Fatalf("unexpected output from pem Encode: %q", b.String())
|
||||
}
|
||||
err = pem.Encode(&b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pkData})
|
||||
require.NoError(t, err, "serializing public key")
|
||||
|
||||
require.Equal(t, b.String(), publicKeyData)
|
||||
}
|
||||
|
||||
subject := &pkix.Name{
|
||||
CommonName: "kubernetes",
|
||||
}
|
||||
signer, err := ParsePEMCertificate([]byte(signerCertData))
|
||||
require.NoError(t, err, "ParsePEMCertificate")
|
||||
|
||||
template := &x509.Certificate{
|
||||
Subject: *subject,
|
||||
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
template x509.Certificate
|
||||
signer *x509.Certificate
|
||||
signerKey *PrivateKey
|
||||
expectedExtKeyUsage []x509.ExtKeyUsage
|
||||
}{
|
||||
{
|
||||
name: "selfsigned",
|
||||
template: x509.Certificate{
|
||||
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
},
|
||||
expectedExtKeyUsage: nil,
|
||||
},
|
||||
{
|
||||
name: "client",
|
||||
template: x509.Certificate{
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365).UTC(),
|
||||
},
|
||||
signerKey: signerKey,
|
||||
signer: signer.Certificate,
|
||||
expectedExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
{
|
||||
name: "server",
|
||||
template: x509.Certificate{
|
||||
DNSNames: []string{"a.invalid", "b.invalid"},
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365).UTC(),
|
||||
},
|
||||
signerKey: signerKey,
|
||||
signer: signer.Certificate,
|
||||
expectedExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
tc.template.Subject = pkix.Name{
|
||||
CommonName: tc.name,
|
||||
}
|
||||
|
||||
cert, err := SignNewCertificate(key, template, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("error from SignNewCertificate: %v", err)
|
||||
}
|
||||
cert, err := SignNewCertificate(key, &tc.template, tc.signer, tc.signerKey)
|
||||
require.NoError(t, err, "SignNewCertificate")
|
||||
|
||||
{
|
||||
var b bytes.Buffer
|
||||
pkData, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
|
||||
if err != nil {
|
||||
t.Fatalf("error from MarshalPKIXPublicKey: %v", err)
|
||||
}
|
||||
if err := pem.Encode(&b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pkData}); err != nil {
|
||||
t.Fatalf("error serializing public key")
|
||||
}
|
||||
{
|
||||
subject := cert.Certificate.Subject
|
||||
subject.Names = nil
|
||||
assert.Equal(t, subject, tc.template.Subject)
|
||||
}
|
||||
assert.Equal(t, cert.Subject, cert.Certificate.Subject)
|
||||
|
||||
if b.String() != publicKeyData {
|
||||
t.Fatalf("unexpected output from pem Encode: %q", b.String())
|
||||
}
|
||||
assert.Equal(t, cert.Certificate.DNSNames, tc.template.DNSNames)
|
||||
|
||||
assert.Equal(t, cert.IsCA, tc.template.IsCA)
|
||||
assert.Equal(t, cert.Certificate.IsCA, tc.template.IsCA)
|
||||
|
||||
{
|
||||
var b bytes.Buffer
|
||||
pkData, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
|
||||
require.NoError(t, err, "MarshalPKIXPublicKey")
|
||||
|
||||
err = pem.Encode(&b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pkData})
|
||||
require.NoError(t, err, "serializing public key")
|
||||
|
||||
assert.Equal(t, b.String(), publicKeyData)
|
||||
}
|
||||
assert.Equal(t, cert.PublicKey, cert.Certificate.PublicKey)
|
||||
|
||||
if tc.template.KeyUsage == 0 {
|
||||
tc.template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
||||
}
|
||||
assert.Equal(t, cert.Certificate.KeyUsage, tc.template.KeyUsage, "KeyUsage")
|
||||
|
||||
assert.Equal(t, cert.Certificate.ExtKeyUsage, tc.expectedExtKeyUsage, "ExtKeyUsage")
|
||||
|
||||
if tc.signer == nil {
|
||||
tc.signer = cert.Certificate
|
||||
}
|
||||
assert.Equal(t, cert.Certificate.Issuer, signer.Certificate.Subject, "Issuer")
|
||||
pool := x509.NewCertPool()
|
||||
pool.AddCert(tc.signer)
|
||||
_, err = cert.Certificate.Verify(x509.VerifyOptions{
|
||||
Roots: pool,
|
||||
KeyUsages: tc.expectedExtKeyUsage,
|
||||
})
|
||||
assert.NoError(t, err, "verify certificate")
|
||||
|
||||
// notbefore, notafter, serialnumber, basiccvalid
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,14 +96,17 @@ func SignNewCertificate(privateKey *PrivateKey, template *x509.Certificate, sign
|
|||
return nil, fmt.Errorf("error creating certificate: %v", err)
|
||||
}
|
||||
|
||||
c := &Certificate{}
|
||||
c.PublicKey = template.PublicKey
|
||||
|
||||
cert, err := x509.ParseCertificate(certificateData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing certificate: %v", err)
|
||||
}
|
||||
c.Certificate = cert
|
||||
|
||||
c := &Certificate{
|
||||
Subject: cert.Subject,
|
||||
IsCA: cert.IsCA,
|
||||
Certificate: cert,
|
||||
PublicKey: cert.PublicKey,
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
|
|
@ -165,6 +165,18 @@ func (k *PrivateKey) WriteTo(w io.Writer) (int64, error) {
|
|||
return data.WriteTo(w)
|
||||
}
|
||||
|
||||
func (k *PrivateKey) WriteToFile(filename string, perm os.FileMode) error {
|
||||
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = k.WriteTo(f)
|
||||
if err1 := f.Close(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func parsePEMPrivateKey(pemData []byte) (crypto.PrivateKey, error) {
|
||||
for {
|
||||
block, rest := pem.Decode(pemData)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["pki_helpers.go"],
|
||||
importpath = "k8s.io/kops/pkg/pkiutil",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/k8s.io/client-go/util/cert:go_default_library"],
|
||||
)
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
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 pkiutil
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
)
|
||||
|
||||
const (
|
||||
// CertificateBlockType is a possible value for pem.Block.Type.
|
||||
CertificateBlockType = "CERTIFICATE"
|
||||
|
||||
// RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
|
||||
RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
|
||||
|
||||
rsaKeySize = 2048
|
||||
|
||||
duration365d = time.Hour * 24 * 365
|
||||
)
|
||||
|
||||
// EncodeCertPEM returns PEM-endcoded certificate data
|
||||
func EncodeCertPEM(cert *x509.Certificate) []byte {
|
||||
block := pem.Block{
|
||||
Type: CertificateBlockType,
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
return pem.EncodeToMemory(&block)
|
||||
}
|
||||
|
||||
// EncodePrivateKeyPEM returns PEM-encoded private key data
|
||||
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
|
||||
block := pem.Block{
|
||||
Type: RSAPrivateKeyBlockType,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||
}
|
||||
return pem.EncodeToMemory(&block)
|
||||
}
|
||||
|
||||
// NewPrivateKey creates an RSA private key
|
||||
func NewPrivateKey() (*rsa.PrivateKey, error) {
|
||||
return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
|
||||
}
|
||||
|
||||
// NewSignedCert creates a signed certificate using the given CA certificate and key
|
||||
func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
|
||||
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cfg.CommonName) == 0 {
|
||||
return nil, fmt.Errorf("must specify a CommonName")
|
||||
}
|
||||
if len(cfg.Usages) == 0 {
|
||||
return nil, fmt.Errorf("must specify at least one ExtKeyUsage")
|
||||
}
|
||||
|
||||
certTmpl := x509.Certificate{
|
||||
Subject: pkix.Name{
|
||||
CommonName: cfg.CommonName,
|
||||
Organization: cfg.Organization,
|
||||
},
|
||||
DNSNames: cfg.AltNames.DNSNames,
|
||||
IPAddresses: cfg.AltNames.IPs,
|
||||
SerialNumber: serial,
|
||||
NotBefore: caCert.NotBefore,
|
||||
NotAfter: time.Now().Add(duration365d).UTC(),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: cfg.Usages,
|
||||
}
|
||||
certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x509.ParseCertificate(certDERBytes)
|
||||
}
|
Loading…
Reference in New Issue