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 12, 2018
1 parent 994a348 commit 4d1abb7
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 113 deletions.
55 changes: 19 additions & 36 deletions pkg/model/pki.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"

"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/tokens"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/fitasks"
Expand All @@ -38,18 +37,17 @@ var _ fi.ModelBuilder = &PKIModelBuilder{}
// Build is responsible for generating the various pki assets.
func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {

// Note: the fitasks.Keypair structs are created with a Format that == fitasks.KeypairType
// to denote that these tasks are using the newer Keypar API Type. This value is used
// to upgrade a legacy Keypair to the newer Keypair API object.
// We specify the KeysetFormatV1Alpha2 format, to upgrade from the legacy representation (separate files)
// to the newer keyset.yaml representation.
format := string(fi.KeysetFormatV1Alpha2)

// TODO: Only create the CA via this task
defaultCA := &fitasks.Keypair{
Name: fi.String(fi.CertificateId_CA),
Lifecycle: b.Lifecycle,
Subject: "cn=kubernetes",
Type: "ca",

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(defaultCA)

Expand All @@ -62,8 +60,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "o=" + user.NodesGroup + ",cn=kubelet",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -77,8 +74,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=kubelet-api",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
})
}
{
Expand All @@ -88,8 +84,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=" + user.KubeScheduler,
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -101,8 +96,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=" + user.KubeProxy,
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -114,8 +108,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=" + user.KubeControllerManager,
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -135,17 +128,15 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=etcd",
Type: "clientServer",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
})
c.AddTask(&fitasks.Keypair{
Name: fi.String("etcd-client"),
Lifecycle: b.Lifecycle,
Subject: "cn=etcd-client",
Type: "client",
Signer: defaultCA,

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

// @check if calico is enabled as the CNI provider
Expand All @@ -156,8 +147,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=calico-client",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
})
}
}
Expand All @@ -168,8 +158,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=" + "system:kube-router",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -181,8 +170,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "o=" + user.SystemPrivilegedGroup + ",cn=kubecfg",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -194,8 +182,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=apiserver-proxy-client",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand All @@ -206,8 +193,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Lifecycle: b.Lifecycle,
Subject: "cn=apiserver-aggregator-ca",
Type: "ca",

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(aggregatorCA)

Expand All @@ -218,8 +204,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "cn=aggregator",
Type: "client",
Signer: aggregatorCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(aggregator)
}
Expand All @@ -232,8 +217,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Subject: "o=" + user.SystemPrivilegedGroup + ",cn=kops",
Type: "client",
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand Down Expand Up @@ -271,8 +255,7 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
Type: "server",
AlternateNames: alternateNames,
Signer: defaultCA,

Format: string(kops.SecretTypeKeypair),
Format: format,
}
c.AddTask(t)
}
Expand Down
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
Loading

0 comments on commit 4d1abb7

Please sign in to comment.