Bump dynamiclistener to support RSA keys

This commit is contained in:
Darren Shepherd 2019-11-15 23:51:24 +00:00 committed by Craig Jellick
parent 4e544bded2
commit 59177e58b7
8 changed files with 47 additions and 50 deletions

2
go.mod
View File

@ -100,7 +100,7 @@ require (
github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830 github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 // indirect github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 // indirect
github.com/rancher/dynamiclistener v0.1.1-0.20191113144757-736b5d5d8b51 github.com/rancher/dynamiclistener v0.2.0
github.com/rancher/helm-controller v0.2.2 github.com/rancher/helm-controller v0.2.2
github.com/rancher/kine v0.2.4 github.com/rancher/kine v0.2.4
github.com/rancher/remotedialer v0.2.0 github.com/rancher/remotedialer v0.2.0

4
go.sum
View File

@ -582,8 +582,8 @@ github.com/rancher/cri v1.3.0-k3s.2 h1:k2XFyD+ZdsGvNfugdvqD38KSMANT3JmTFULFM2CtI
github.com/rancher/cri v1.3.0-k3s.2/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY= github.com/rancher/cri v1.3.0-k3s.2/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg= github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg=
github.com/rancher/cri-tools v1.16.1-k3s.1/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8= github.com/rancher/cri-tools v1.16.1-k3s.1/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8=
github.com/rancher/dynamiclistener v0.1.1-0.20191113144757-736b5d5d8b51 h1:+UOLT6b1Of/gSiLR1i+m81ITu79vUpIU8zpsxbY4Hlw= github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk=
github.com/rancher/dynamiclistener v0.1.1-0.20191113144757-736b5d5d8b51/go.mod h1:fs/dxyNcB3YT6W9fVz4bDGfhmSQS17QQup6BIcGF++s= github.com/rancher/dynamiclistener v0.2.0/go.mod h1:fs/dxyNcB3YT6W9fVz4bDGfhmSQS17QQup6BIcGF++s=
github.com/rancher/flannel v0.11.0-k3s.1 h1:mIwnfWDafjzQgFkZeJ1AkFrrAT3EdBaA1giE0eLJKo8= github.com/rancher/flannel v0.11.0-k3s.1 h1:mIwnfWDafjzQgFkZeJ1AkFrrAT3EdBaA1giE0eLJKo8=
github.com/rancher/flannel v0.11.0-k3s.1/go.mod h1:Hn4ZV+eq0LhLZP63xZnxdGwXEoRSxs5sxELxu27M3UA= github.com/rancher/flannel v0.11.0-k3s.1/go.mod h1:Hn4ZV+eq0LhLZP63xZnxdGwXEoRSxs5sxELxu27M3UA=
github.com/rancher/go-dqlite v1.1.0-k3s.1 h1:w3ghNkY5vqRnnrcqxvHkpBQr6E+R/nIwJfaGdNgJAiw= github.com/rancher/go-dqlite v1.1.0-k3s.1 h1:w3ghNkY5vqRnnrcqxvHkpBQr6E+R/nIwJfaGdNgJAiw=

View File

@ -1,13 +1,16 @@
package factory package factory
import ( import (
"crypto/ecdsa" "crypto"
"crypto/x509" "crypto/x509"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"github.com/rancher/dynamiclistener/cert"
) )
func GenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { func GenCA() (*x509.Certificate, crypto.Signer, error) {
caKey, err := NewPrivateKey() caKey, err := NewPrivateKey()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -21,7 +24,7 @@ func GenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) {
return caCert, caKey, nil return caCert, caKey, nil
} }
func LoadOrGenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { func LoadOrGenCA() (*x509.Certificate, crypto.Signer, error) {
cert, key, err := loadCA() cert, key, err := loadCA()
if err == nil { if err == nil {
return cert, key, nil return cert, key, nil
@ -52,11 +55,11 @@ func LoadOrGenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) {
return cert, key, nil return cert, key, nil
} }
func loadCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { func loadCA() (*x509.Certificate, crypto.Signer, error) {
return LoadCerts("./certs/ca.pem", "./certs/ca.key") return LoadCerts("./certs/ca.pem", "./certs/ca.key")
} }
func LoadCerts(certFile, keyFile string) (*x509.Certificate, *ecdsa.PrivateKey, error) { func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, error) {
caPem, err := ioutil.ReadFile(certFile) caPem, err := ioutil.ReadFile(certFile)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -66,15 +69,19 @@ func LoadCerts(certFile, keyFile string) (*x509.Certificate, *ecdsa.PrivateKey,
return nil, nil, err return nil, nil, err
} }
key, err := ParseECPrivateKeyPEM(caKey) key, err := cert.ParsePrivateKeyPEM(caKey)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
signer, ok := key.(crypto.Signer)
if !ok {
return nil, nil, fmt.Errorf("key is not a crypto.Signer")
}
cert, err := ParseCertPEM(caPem) cert, err := ParseCertPEM(caPem)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
return cert, key, nil return cert, signer, nil
} }

View File

@ -2,7 +2,6 @@ package factory
import ( import (
"crypto" "crypto"
"crypto/ecdsa"
"crypto/rand" "crypto/rand"
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
@ -15,8 +14,7 @@ import (
) )
const ( const (
ECPrivateKeyBlockType = "EC PRIVATE KEY" CertificateBlockType = "CERTIFICATE"
CertificateBlockType = "CERTIFICATE"
) )
func NewSelfSignedCACert(key crypto.Signer, cn string, org ...string) (*x509.Certificate, error) { func NewSelfSignedCACert(key crypto.Signer, cn string, org ...string) (*x509.Certificate, error) {
@ -72,22 +70,6 @@ func NewSignedCert(signer crypto.Signer, caCert *x509.Certificate, caKey crypto.
return x509.ParseCertificate(cert) return x509.ParseCertificate(cert)
} }
func ParseECPrivateKeyPEM(keyData []byte) (*ecdsa.PrivateKey, error) {
var privateKeyPemBlock *pem.Block
for {
privateKeyPemBlock, keyData = pem.Decode(keyData)
if privateKeyPemBlock == nil {
break
}
if privateKeyPemBlock.Type == ECPrivateKeyBlockType {
return x509.ParseECPrivateKey(privateKeyPemBlock.Bytes)
}
}
return nil, fmt.Errorf("pem does not include a valid EC private key")
}
func ParseCertPEM(pemCerts []byte) (*x509.Certificate, error) { func ParseCertPEM(pemCerts []byte) (*x509.Certificate, error) {
var pemBlock *pem.Block var pemBlock *pem.Block
for { for {

View File

@ -13,6 +13,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/rancher/dynamiclistener/cert"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -105,7 +106,7 @@ func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) {
return secret, true, nil return secret, true, nil
} }
func (t *TLS) newCert(domains []string, ips []net.IP, privateKey *ecdsa.PrivateKey) (*x509.Certificate, error) { func (t *TLS) newCert(domains []string, ips []net.IP, privateKey crypto.Signer) (*x509.Certificate, error) {
return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips) return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips)
} }
@ -134,39 +135,34 @@ func NeedsUpdate(secret *v1.Secret, cn ...string) bool {
return false return false
} }
func getPrivateKey(secret *v1.Secret) (*ecdsa.PrivateKey, error) { func getPrivateKey(secret *v1.Secret) (crypto.Signer, error) {
keyBytes := secret.Data[v1.TLSPrivateKeyKey] keyBytes := secret.Data[v1.TLSPrivateKeyKey]
if len(keyBytes) == 0 { if len(keyBytes) == 0 {
return NewPrivateKey() return NewPrivateKey()
} }
privateKey, err := ParseECPrivateKeyPEM(keyBytes) privateKey, err := cert.ParsePrivateKeyPEM(keyBytes)
if err == nil { if signer, ok := privateKey.(crypto.Signer); ok && err == nil {
return privateKey, nil return signer, nil
} }
return NewPrivateKey() return NewPrivateKey()
} }
func Marshal(x509Cert *x509.Certificate, privateKey *ecdsa.PrivateKey) ([]byte, []byte, error) { func Marshal(x509Cert *x509.Certificate, privateKey crypto.Signer) ([]byte, []byte, error) {
certBlock := pem.Block{ certBlock := pem.Block{
Type: CertificateBlockType, Type: CertificateBlockType,
Bytes: x509Cert.Raw, Bytes: x509Cert.Raw,
} }
keyBytes, err := x509.MarshalECPrivateKey(privateKey) keyBytes, err := cert.MarshalPrivateKeyToPEM(privateKey)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
keyBlock := pem.Block{ return pem.EncodeToMemory(&certBlock), keyBytes, nil
Type: ECPrivateKeyBlockType,
Bytes: keyBytes,
}
return pem.EncodeToMemory(&certBlock), pem.EncodeToMemory(&keyBlock), nil
} }
func NewPrivateKey() (*ecdsa.PrivateKey, error) { func NewPrivateKey() (crypto.Signer, error) {
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
} }

View File

@ -80,9 +80,19 @@ func (s *storage) init(secrets v1controller.SecretController) {
}) })
s.secrets = secrets s.secrets = secrets
secret, err := s.storage.Get() if secret, err := s.storage.Get(); err == nil && secret != nil && len(secret.Data) > 0 {
if err == nil && secret != nil { // just ensure there is a secret in k3s
s.saveInK8s(secret) if _, err := s.secrets.Get(s.namespace, s.name, metav1.GetOptions{}); errors.IsNotFound(err) {
_, _ = s.secrets.Create(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: s.name,
Namespace: s.namespace,
Annotations: secret.Annotations,
},
Type: v1.SecretTypeTLS,
Data: secret.Data,
})
}
} }
} }
@ -132,10 +142,10 @@ func (s *storage) saveInK8s(secret *v1.Secret) (*v1.Secret, error) {
targetSecret.Data = secret.Data targetSecret.Data = secret.Data
if targetSecret.UID == "" { if targetSecret.UID == "" {
logrus.Infof("Creating new TLS secret for %v (count: %d)", targetSecret.Name, len(targetSecret.Data)-1) logrus.Infof("Creating new TLS secret for %v (count: %d): %v", targetSecret.Name, len(targetSecret.Annotations)-1, targetSecret.Annotations)
return s.secrets.Create(targetSecret) return s.secrets.Create(targetSecret)
} else { } else {
logrus.Infof("Updating TLS secret for %v (count: %d)", targetSecret.Name, len(targetSecret.Data)-1) logrus.Infof("Updating TLS secret for %v (count: %d): %v", targetSecret.Name, len(targetSecret.Annotations)-1, targetSecret.Annotations)
return s.secrets.Update(targetSecret) return s.secrets.Update(targetSecret)
} }
} }

View File

@ -2,6 +2,7 @@ package memory
import ( import (
"github.com/rancher/dynamiclistener" "github.com/rancher/dynamiclistener"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -15,7 +16,7 @@ func NewBacked(storage dynamiclistener.TLSStorage) dynamiclistener.TLSStorage {
type memory struct { type memory struct {
storage dynamiclistener.TLSStorage storage dynamiclistener.TLSStorage
secret *v1.Secret secret *v1.Secret
} }
func (m *memory) Get() (*v1.Secret, error) { func (m *memory) Get() (*v1.Secret, error) {
@ -37,6 +38,7 @@ func (m *memory) Update(secret *v1.Secret) error {
} }
} }
logrus.Infof("Active TLS secret %s (ver=%s) (count %d): %v", secret.Name, secret.ResourceVersion, len(secret.Annotations)-1, secret.Annotations)
m.secret = secret m.secret = secret
return nil return nil
} }

2
vendor/modules.txt vendored
View File

@ -748,7 +748,7 @@ github.com/prometheus/procfs/internal/util
# github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 # github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8
github.com/rakelkar/gonetsh/netroute github.com/rakelkar/gonetsh/netroute
github.com/rakelkar/gonetsh/netsh github.com/rakelkar/gonetsh/netsh
# github.com/rancher/dynamiclistener v0.1.1-0.20191113144757-736b5d5d8b51 # github.com/rancher/dynamiclistener v0.2.0
github.com/rancher/dynamiclistener github.com/rancher/dynamiclistener
github.com/rancher/dynamiclistener/factory github.com/rancher/dynamiclistener/factory
github.com/rancher/dynamiclistener/storage/file github.com/rancher/dynamiclistener/storage/file