Skip to content

Commit

Permalink
Define KeysetFormat type, embed into keyset
Browse files Browse the repository at this point in the history
The values are 'legacy' when not using keyset.yaml, and the API version
(v1alpha2) for keyset.yaml
  • Loading branch information
justinsb committed Mar 10, 2018
1 parent 6606ab4 commit a76baa9
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 77 deletions.
15 changes: 7 additions & 8 deletions tests/keypair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,23 @@ func TestKeypairUpgrade(t *testing.T) {

// We define a function so we can rebuild the tasks, because we modify in-place when running
buildTasks := func() map[string]fi.Task {
format := string(fi.KeysetFormatV1Alpha2)

ca := &fitasks.Keypair{
Name: fi.String(fi.CertificateId_CA),
Lifecycle: &lifecycle,
Subject: "cn=kubernetes",
Type: "ca",

Format: string(kops.SecretTypeKeypair),
Format: format,
}

kubelet := &fitasks.Keypair{
Name: fi.String("kubelet"),
Lifecycle: &lifecycle,

Subject: "o=nodes,cn=kubelet",
Type: "client",
Signer: ca,

Format: string(kops.SecretTypeKeypair),
Subject: "o=nodes,cn=kubelet",
Type: "client",
Signer: ca,
Format: format,
}

tasks := make(map[string]fi.Task)
Expand Down
9 changes: 8 additions & 1 deletion upup/pkg/fi/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const (
SecretNameSSHPrimary = "admin"
)

type KeysetFormat string

const (
KeysetFormatLegacy KeysetFormat = "legacy"
KeysetFormatV1Alpha2 KeysetFormat = "v1alpha2"
)

type KeystoreItem struct {
Type kops.KeysetType
Name string
Expand All @@ -47,7 +54,7 @@ type Keystore interface {
// This func returns a cert, private key and a string. The string value is the Format of the keystore which is either
// an empty string, which denotes a Legacy Keypair, or a value of "Keypair". This string is used by a keypair
// task convert a Legacy Keypair to the new Keypair API format.
FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, string, error)
FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, KeysetFormat, error)

CreateKeypair(signer string, name string, template *x509.Certificate, privateKey *pki.PrivateKey) (*pki.Certificate, error)

Expand Down
46 changes: 24 additions & 22 deletions upup/pkg/fi/clientset_castore.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (c *ClientsetCAStore) readCAKeypairs(id string) (*keyset, error) {
return cached, nil
}

keyset, _, err := c.loadKeyset(id)
keyset, err := c.loadKeyset(id)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -122,6 +122,7 @@ func (c *ClientsetCAStore) generateCACertificate(id string) (*keyset, error) {

// keyset is a parsed Keyset
type keyset struct {
format KeysetFormat
items map[string]*keysetItem
primary *keysetItem
}
Expand All @@ -133,7 +134,7 @@ type keysetItem struct {
privateKey *pki.PrivateKey
}

func parseKeyset(o *kops.Keyset) (*keyset, string, error) {
func parseKeyset(o *kops.Keyset) (*keyset, error) {
name := o.Name

keyset := &keyset{
Expand All @@ -148,15 +149,15 @@ func parseKeyset(o *kops.Keyset) (*keyset, string, error) {
cert, err := pki.ParsePEMCertificate(key.PublicMaterial)
if err != nil {
glog.Warningf("key public material was %s", key.PublicMaterial)
return nil, "", fmt.Errorf("error loading certificate %s/%s: %v", name, key.Id, err)
return nil, fmt.Errorf("error loading certificate %s/%s: %v", name, key.Id, err)
}
ki.certificate = cert
}

if len(key.PrivateMaterial) != 0 {
privateKey, err := pki.ParsePEMPrivateKey(key.PrivateMaterial)
if err != nil {
return nil, "", fmt.Errorf("error loading private key %s/%s: %v", name, key.Id, err)
return nil, fmt.Errorf("error loading private key %s/%s: %v", name, key.Id, err)
}
ki.privateKey = privateKey
}
Expand All @@ -166,23 +167,25 @@ func parseKeyset(o *kops.Keyset) (*keyset, string, error) {

keyset.primary = keyset.findPrimary()

// This value == Keypair when using the API Keyset. When the keyset is a legacy value the o.Spec.Type value is
// not set. The keypair task is using this value to upgrade legacy keysets to keysets that use the API.
keypairType := string(o.Spec.Type)
return keyset, keypairType, nil
return keyset, nil
}

// loadKeyset gets the named keyset and the format of the Keyset.
func (c *ClientsetCAStore) loadKeyset(name string) (*keyset, string, error) {
func (c *ClientsetCAStore) loadKeyset(name string) (*keyset, error) {
o, err := c.clientset.Keysets(c.namespace).Get(name, v1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return nil, "", nil
return nil, nil
}
return nil, "", fmt.Errorf("error reading keyset %q: %v", name, err)
return nil, fmt.Errorf("error reading keyset %q: %v", name, err)
}

return parseKeyset(o)
keyset, err := parseKeyset(o)
if err != nil {
return nil, err
}
keyset.format = KeysetFormatV1Alpha2
return keyset, nil
}

// findPrimary returns the primary keysetItem in the keyset
Expand Down Expand Up @@ -240,37 +243,36 @@ func (c *ClientsetCAStore) CertificatePool(id string, createIfMissing bool) (*Ce
}

// FindKeypair implements CAStore::FindKeypair
func (c *ClientsetCAStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, string, error) {
keyset, keysetType, err := c.loadKeyset(name)
func (c *ClientsetCAStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, KeysetFormat, error) {
keyset, err := c.loadKeyset(name)
if err != nil {
return nil, nil, "", err
}

if keyset != nil && keyset.primary != nil {
return keyset.primary.certificate, keyset.primary.privateKey, keysetType, nil
return keyset.primary.certificate, keyset.primary.privateKey, keyset.format, nil
}

return nil, nil, "", nil
}

// FindCert implements CAStore::FindCert
func (c *ClientsetCAStore) FindCert(name string) (*pki.Certificate, error) {
keyset, _, err := c.loadKeyset(name)
keyset, err := c.loadKeyset(name)
if err != nil {
return nil, err
}

var cert *pki.Certificate
if keyset != nil && keyset.primary != nil {
cert = keyset.primary.certificate
return keyset.primary.certificate, nil
}

return cert, nil
return nil, nil
}

// FindCertificatePool implements CAStore::FindCertificatePool
func (c *ClientsetCAStore) FindCertificatePool(name string) (*CertificatePool, error) {
keyset, _, err := c.loadKeyset(name)
keyset, err := c.loadKeyset(name)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -392,7 +394,7 @@ func (c *ClientsetCAStore) storeAndVerifyKeypair(name string, cert *pki.Certific
}

// Make double-sure it round-trips
keyset, _, err := c.loadKeyset(name)
keyset, err := c.loadKeyset(name)
if err != nil {
return nil, fmt.Errorf("error fetching stored certificate: %v", err)
}
Expand Down Expand Up @@ -431,7 +433,7 @@ func (c *ClientsetCAStore) AddCert(name string, cert *pki.Certificate) error {

// FindPrivateKey implements CAStore::FindPrivateKey
func (c *ClientsetCAStore) FindPrivateKey(name string) (*pki.PrivateKey, error) {
keyset, _, err := c.loadKeyset(name)
keyset, err := c.loadKeyset(name)
if err != nil {
return nil, err
}
Expand Down
7 changes: 3 additions & 4 deletions upup/pkg/fi/fitasks/keypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Keypair struct {
Type string `json:"type"`
// Format stores the api version of kops.Keyset. We are using this info in order to determine if kops
// is accessing legacy secrets that do not use keyset.yaml.
Format string `json:"keypairType"`
Format string `json:"format"`
}

var _ fi.HasCheckExisting = &Keypair{}
Expand All @@ -76,7 +76,7 @@ func (e *Keypair) Find(c *fi.Context) (*Keypair, error) {
return nil, nil
}

cert, key, keySetType, err := c.Keystore.FindKeypair(name)
cert, key, format, err := c.Keystore.FindKeypair(name)
if err != nil {
return nil, err
}
Expand All @@ -100,8 +100,7 @@ func (e *Keypair) Find(c *fi.Context) (*Keypair, error) {
AlternateNames: alternateNames,
Subject: pkixNameToString(&cert.Subject),
Type: buildTypeDescription(cert.Certificate),

Format: keySetType,
Format: string(format),
}

actual.Signer = &Keypair{Subject: pkixNameToString(&cert.Certificate.Issuer)}
Expand Down
7 changes: 2 additions & 5 deletions upup/pkg/fi/k8sapi/k8s_keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (c *KubernetesKeystore) findSecret(id string) (*v1.Secret, error) {
return secret, nil
}

func (c *KubernetesKeystore) FindKeypair(id string) (*pki.Certificate, *pki.PrivateKey, string, error) {
func (c *KubernetesKeystore) FindKeypair(id string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
secret, err := c.findSecret(id)
if err != nil {
return nil, nil, "", err
Expand All @@ -105,10 +105,7 @@ func (c *KubernetesKeystore) FindKeypair(id string) (*pki.Certificate, *pki.Priv
return nil, nil, "", fmt.Errorf("error parsing secret %s/%s from kubernetes: %v", c.namespace, id, err)
}

// This value is when using the API Keyset. When the keyset is a legacy value the secret.Type value is
// not set. The keypair task is using this value to upgrade legacy keysets to keysets that use the API.
keypairType := string(secret.Type)
return keypair.Certificate, keypair.PrivateKey, keypairType, nil
return keypair.Certificate, keypair.PrivateKey, fi.KeysetFormatV1Alpha2, nil
}

func (c *KubernetesKeystore) CreateKeypair(signer string, id string, template *x509.Certificate, privateKey *pki.PrivateKey) (*pki.Certificate, error) {
Expand Down
Loading

0 comments on commit a76baa9

Please sign in to comment.