Clientset fixes per code review

This commit is contained in:
Justin Santa Barbara 2017-09-17 23:22:14 -04:00
parent 914fe68ee2
commit d9a3c46b0b
2 changed files with 29 additions and 34 deletions

View File

@ -22,6 +22,10 @@ import (
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"math/big"
"sync"
"time"
"github.com/golang/glog" "github.com/golang/glog"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
@ -30,11 +34,9 @@ import (
kopsinternalversion "k8s.io/kops/pkg/client/clientset_generated/clientset/typed/kops/internalversion" kopsinternalversion "k8s.io/kops/pkg/client/clientset_generated/clientset/typed/kops/internalversion"
"k8s.io/kops/pkg/pki" "k8s.io/kops/pkg/pki"
"k8s.io/kops/util/pkg/vfs" "k8s.io/kops/util/pkg/vfs"
"math/big"
"sync"
"time"
) )
// ClientsetCAStore is a CAStore implementation that stores keypairs in Keyset on a API server
type ClientsetCAStore struct { type ClientsetCAStore struct {
namespace string namespace string
clientset kopsinternalversion.KopsInterface clientset kopsinternalversion.KopsInterface
@ -93,30 +95,15 @@ func (c *ClientsetCAStore) generateCACertificate() (*keyset, error) {
caPrivateKey := &pki.PrivateKey{Key: caRsaKey} caPrivateKey := &pki.PrivateKey{Key: caRsaKey}
t := time.Now().UnixNano()
template.SerialNumber = pki.BuildPKISerial(t)
caCertificate, err := pki.SignNewCertificate(caPrivateKey, template, nil, nil) caCertificate, err := pki.SignNewCertificate(caPrivateKey, template, nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
t := time.Now().UnixNano() return c.storeAndVerifyKeypair(CertificateId_CA, caCertificate, caPrivateKey)
serial := pki.BuildPKISerial(t)
id := serial.String()
err = c.storeKeypair(CertificateId_CA, id, caCertificate, caPrivateKey)
if err != nil {
return nil, err
}
// Make double-sure it round-trips
keyset, err := c.loadKeyset(CertificateId_CA)
if err != nil {
return nil, err
}
if keyset == nil || keyset.primary == nil || keyset.primary.id != id {
return nil, fmt.Errorf("failed to round-trip CA keyset")
}
return keyset, nil
} }
// keyset is a parsed Keyset // keyset is a parsed Keyset
@ -349,34 +336,41 @@ func (c *ClientsetCAStore) IssueCert(name string, serial *big.Int, privateKey *p
return nil, err return nil, err
} }
err = c.StoreKeypair(name, cert, privateKey) if _, err := c.storeAndVerifyKeypair(name, cert, privateKey); err != nil {
if err != nil { return nil, err
}
return cert, nil
}
// storeAndVerifyKeypair writes the keypair, also re-reading it to double-check it
func (c *ClientsetCAStore) storeAndVerifyKeypair(name string, cert *pki.Certificate, privateKey *pki.PrivateKey) (*keyset, error) {
id := cert.Certificate.SerialNumber.String()
if err := c.storeKeypair(name, id, cert, privateKey); err != nil {
return nil, err return nil, err
} }
// Make double-sure it round-trips // Make double-sure it round-trips
keyset, err := c.loadKeyset(name) keyset, err := c.loadKeyset(name)
if err != nil { if err != nil {
return nil, fmt.Errorf("error fetching issued certificate: %v", err) return nil, fmt.Errorf("error fetching stored certificate: %v", err)
} }
if keyset == nil { if keyset == nil {
return nil, fmt.Errorf("issued certificate not found: %v", err) return nil, fmt.Errorf("stored certificate not found: %v", err)
} }
if keyset.primary == nil { if keyset.primary == nil {
return nil, fmt.Errorf("issued certificate did not have data: %v", err) return nil, fmt.Errorf("stored certificate did not have data: %v", err)
} }
if keyset.primary.id != serial.String() { if keyset.primary.id != id {
return nil, fmt.Errorf("issued certificate changed concurrently (id mismatch)") return nil, fmt.Errorf("stored certificate changed concurrently (id mismatch)")
} }
return keyset.primary.certificate, nil return keyset, nil
} }
// StoreKeypair implements CAStore::StoreKeypair // StoreKeypair implements CAStore::StoreKeypair
func (c *ClientsetCAStore) StoreKeypair(name string, cert *pki.Certificate, privateKey *pki.PrivateKey) error { func (c *ClientsetCAStore) StoreKeypair(name string, cert *pki.Certificate, privateKey *pki.PrivateKey) error {
serial := cert.Certificate.SerialNumber return c.storeKeypair(name, cert.Certificate.SerialNumber.String(), cert, privateKey)
return c.storeKeypair(name, serial.String(), cert, privateKey)
} }
// AddCert implements CAStore::AddCert // AddCert implements CAStore::AddCert

View File

@ -34,6 +34,7 @@ import (
// NamePrefix is a prefix we use to avoid collisions with other keysets // NamePrefix is a prefix we use to avoid collisions with other keysets
const NamePrefix = "token-" const NamePrefix = "token-"
// ClientsetSecretStore is a SecretStore backed by Keyset objects in an API server
type ClientsetSecretStore struct { type ClientsetSecretStore struct {
namespace string namespace string
clientset kopsinternalversion.KopsInterface clientset kopsinternalversion.KopsInterface
@ -160,7 +161,7 @@ func parseSecret(keyset *kops.Keyset) (*fi.Secret, error) {
return s, nil return s, nil
} }
// createSecret writes the secret, but only if it does not exists // createSecret writes the secret, but only if it does not exist
func (c *ClientsetSecretStore) createSecret(s *fi.Secret, name string) (*kops.Keyset, error) { func (c *ClientsetSecretStore) createSecret(s *fi.Secret, name string) (*kops.Keyset, error) {
keyset := &kops.Keyset{} keyset := &kops.Keyset{}
keyset.Name = NamePrefix + name keyset.Name = NamePrefix + name