mirror of https://github.com/kubernetes/kops.git
Remove support for reading legacy-format keypairs
This commit is contained in:
parent
83c2a0885e
commit
8a6d29cd40
|
|
@ -113,10 +113,7 @@ func (f *Factory) Clientset() (simple.Clientset, error) {
|
|||
return nil, field.Invalid(field.NewPath("State Store"), registryPath, INVALID_STATE_ERROR)
|
||||
}
|
||||
|
||||
// For kops CLI / controller, we do allow vfs list (unlike nodeup!)
|
||||
allowVFSList := true
|
||||
|
||||
f.clientset = vfsclientset.NewVFSClientset(basePath, allowVFSList)
|
||||
f.clientset = vfsclientset.NewVFSClientset(basePath)
|
||||
}
|
||||
if strings.HasPrefix(registryPath, "file://") {
|
||||
klog.Warning("The local filesystem state store is not functional for running clusters")
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ import (
|
|||
)
|
||||
|
||||
func apply(ctx context.Context) error {
|
||||
allowList := true
|
||||
clientset := vfsclientset.NewVFSClientset(registryBase, allowList)
|
||||
clientset := vfsclientset.NewVFSClientset(registryBase)
|
||||
|
||||
cluster, err := clientset.GetCluster(ctx, clusterName)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func up(ctx context.Context) error {
|
||||
allowList := true
|
||||
clientset := vfsclientset.NewVFSClientset(registryBase, allowList)
|
||||
clientset := vfsclientset.NewVFSClientset(registryBase)
|
||||
|
||||
cluster := &api.Cluster{}
|
||||
cluster.ObjectMeta.Name = clusterName
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ k8s.io/kops/protokube/pkg/gossip/openstack
|
|||
k8s.io/kops/protokube/pkg/hostmount
|
||||
k8s.io/kops/protokube/pkg/protokube
|
||||
k8s.io/kops/protokube/tests/integration/build_etcd_manifest
|
||||
k8s.io/kops/tests
|
||||
k8s.io/kops/tests/codecs
|
||||
k8s.io/kops/tests/integration/channel
|
||||
k8s.io/kops/tests/integration/conversion
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ type fakeKeyStore struct {
|
|||
T *testing.T
|
||||
}
|
||||
|
||||
func (k fakeKeyStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
|
||||
func (k fakeKeyStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ func mockedPopulateClusterSpec(c *kops.Cluster) (*kops.Cluster, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error building vfspath: %v", err)
|
||||
}
|
||||
clientset := vfsclientset.NewVFSClientset(basePath, true)
|
||||
clientset := vfsclientset.NewVFSClientset(basePath)
|
||||
return cloudup.PopulateClusterSpec(clientset, c, assetBuilder)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ import (
|
|||
)
|
||||
|
||||
type VFSClientset struct {
|
||||
basePath vfs.Path
|
||||
allowList bool
|
||||
basePath vfs.Path
|
||||
}
|
||||
|
||||
var _ simple.Clientset = &VFSClientset{}
|
||||
|
|
@ -90,7 +89,7 @@ func (c *VFSClientset) KeyStore(cluster *kops.Cluster) (fi.CAStore, error) {
|
|||
return nil, err
|
||||
}
|
||||
basedir := configBase.Join("pki")
|
||||
return fi.NewVFSCAStore(cluster, basedir, c.allowList), nil
|
||||
return fi.NewVFSCAStore(cluster, basedir), nil
|
||||
}
|
||||
|
||||
func (c *VFSClientset) SSHCredentialStore(cluster *kops.Cluster) (fi.SSHCredentialStore, error) {
|
||||
|
|
@ -163,10 +162,9 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster)
|
|||
return DeleteAllClusterState(configBase)
|
||||
}
|
||||
|
||||
func NewVFSClientset(basePath vfs.Path, allowList bool) simple.Clientset {
|
||||
func NewVFSClientset(basePath vfs.Path) simple.Clientset {
|
||||
vfsClientset := &VFSClientset{
|
||||
basePath: basePath,
|
||||
allowList: allowList,
|
||||
basePath: basePath,
|
||||
}
|
||||
return vfsClientset
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func (f fakeStatusStore) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiI
|
|||
|
||||
// mock a fake key store
|
||||
type fakeKeyStore struct {
|
||||
FindKeypairFn func(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error)
|
||||
FindKeypairFn func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error)
|
||||
|
||||
CreateKeypairFn func(signer string, name string, template *x509.Certificate, privateKey *pki.PrivateKey) (*pki.Certificate, error)
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ type fakeKeyStore struct {
|
|||
MirrorToFn func(basedir vfs.Path) error
|
||||
}
|
||||
|
||||
func (f fakeKeyStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
|
||||
func (f fakeKeyStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
return f.FindKeypairFn(name)
|
||||
}
|
||||
|
||||
|
|
@ -144,10 +144,10 @@ func TestBuildKubecfg(t *testing.T) {
|
|||
args{
|
||||
publiccluster,
|
||||
fakeKeyStore{
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
return fakeCertificate(),
|
||||
fakePrivateKey(),
|
||||
fi.KeysetFormatLegacy,
|
||||
true,
|
||||
nil
|
||||
},
|
||||
},
|
||||
|
|
@ -169,10 +169,10 @@ func TestBuildKubecfg(t *testing.T) {
|
|||
args{
|
||||
emptyMasterPublicNameCluster,
|
||||
fakeKeyStore{
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
return fakeCertificate(),
|
||||
fakePrivateKey(),
|
||||
fi.KeysetFormatLegacy,
|
||||
true,
|
||||
nil
|
||||
},
|
||||
},
|
||||
|
|
@ -194,10 +194,10 @@ func TestBuildKubecfg(t *testing.T) {
|
|||
args{
|
||||
gossipCluster,
|
||||
fakeKeyStore{
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, fi.KeysetFormat, error) {
|
||||
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
return fakeCertificate(),
|
||||
fakePrivateKey(),
|
||||
fi.KeysetFormatLegacy,
|
||||
true,
|
||||
nil
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -97,8 +97,6 @@ func (b *EtcdManagerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
return err
|
||||
}
|
||||
|
||||
format := string(fi.KeysetFormatV1Alpha2)
|
||||
|
||||
c.AddTask(&fitasks.ManagedFile{
|
||||
Contents: fi.WrapResource(fi.NewBytesResource(d)),
|
||||
Lifecycle: b.Lifecycle,
|
||||
|
|
@ -112,7 +110,6 @@ func (b *EtcdManagerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Name: fi.String("etcd-manager-ca-" + etcdCluster.Name),
|
||||
Subject: "cn=etcd-manager-ca-" + etcdCluster.Name,
|
||||
Type: "ca",
|
||||
Format: format,
|
||||
})
|
||||
|
||||
// We create a CA for etcd peers and a separate one for clients
|
||||
|
|
@ -120,7 +117,6 @@ func (b *EtcdManagerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Name: fi.String("etcd-peers-ca-" + etcdCluster.Name),
|
||||
Subject: "cn=etcd-peers-ca-" + etcdCluster.Name,
|
||||
Type: "ca",
|
||||
Format: format,
|
||||
})
|
||||
|
||||
// Because API server can only have a single client-cert, we need to share a client CA
|
||||
|
|
@ -128,7 +124,6 @@ func (b *EtcdManagerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Name: fi.String("etcd-clients-ca"),
|
||||
Subject: "cn=etcd-clients-ca",
|
||||
Type: "ca",
|
||||
Format: format,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -138,7 +133,6 @@ func (b *EtcdManagerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Name: fi.String("etcd-clients-ca-cilium"),
|
||||
Subject: "cn=etcd-clients-ca-cilium",
|
||||
Type: "ca",
|
||||
Format: format,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Name: etcd-clients-ca
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-clients-ca
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -12,7 +12,7 @@ Name: etcd-manager-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -21,7 +21,7 @@ Name: etcd-manager-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -30,7 +30,7 @@ Name: etcd-peers-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -39,7 +39,7 @@ Name: etcd-peers-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Name: etcd-clients-ca
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-clients-ca
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -12,7 +12,7 @@ Name: etcd-manager-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -21,7 +21,7 @@ Name: etcd-manager-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -30,7 +30,7 @@ Name: etcd-peers-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -39,7 +39,7 @@ Name: etcd-peers-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Name: etcd-clients-ca
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-clients-ca
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -12,7 +12,7 @@ Name: etcd-manager-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -21,7 +21,7 @@ Name: etcd-manager-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -30,7 +30,7 @@ Name: etcd-peers-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -39,7 +39,7 @@ Name: etcd-peers-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Name: etcd-clients-ca
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-clients-ca
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -12,7 +12,7 @@ Name: etcd-manager-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -21,7 +21,7 @@ Name: etcd-manager-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-manager-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -30,7 +30,7 @@ Name: etcd-peers-ca-events
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-events
|
||||
type: ca
|
||||
---
|
||||
|
|
@ -39,7 +39,7 @@ Name: etcd-peers-ca-main
|
|||
Signer: null
|
||||
alternateNameTasks: null
|
||||
alternateNames: null
|
||||
format: v1alpha2
|
||||
oldFormat: false
|
||||
subject: cn=etcd-peers-ca-main
|
||||
type: ca
|
||||
---
|
||||
|
|
|
|||
|
|
@ -38,17 +38,12 @@ var _ fi.ModelBuilder = &PKIModelBuilder{}
|
|||
// Build is responsible for generating the various pki assets.
|
||||
func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||
|
||||
// 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: format,
|
||||
}
|
||||
c.AddTask(defaultCA)
|
||||
|
||||
|
|
@ -62,7 +57,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "o=" + rbac.NodesGroup + ",cn=kubelet",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +70,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=kubelet-api",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
}
|
||||
{
|
||||
|
|
@ -86,7 +79,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=" + rbac.KubeScheduler,
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -98,7 +90,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=" + rbac.KubeProxy,
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -110,7 +101,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=" + rbac.KubeControllerManager,
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -133,7 +123,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
// TODO: Can this be "server" now that we're not using it for peer connectivity?
|
||||
Type: "clientServer",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
|
||||
// For peer authentication, the same cert is used both as a client
|
||||
|
|
@ -162,7 +151,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=etcd-peer",
|
||||
Type: "clientServer",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
|
||||
c.AddTask(&fitasks.Keypair{
|
||||
|
|
@ -171,7 +159,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=etcd-client",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
|
||||
// @check if calico is enabled as the CNI provider
|
||||
|
|
@ -182,7 +169,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=calico-client",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -193,7 +179,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=" + "system:kube-router",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -205,7 +190,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "o=" + rbac.SystemPrivilegedGroup + ",cn=kubecfg",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -217,7 +201,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=apiserver-proxy-client",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -228,7 +211,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Lifecycle: b.Lifecycle,
|
||||
Subject: "cn=apiserver-aggregator-ca",
|
||||
Type: "ca",
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(aggregatorCA)
|
||||
|
||||
|
|
@ -239,7 +221,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=aggregator",
|
||||
Type: "client",
|
||||
Signer: aggregatorCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(aggregator)
|
||||
}
|
||||
|
|
@ -252,7 +233,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "o=" + rbac.SystemPrivilegedGroup + ",cn=kops",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -290,7 +270,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Type: "server",
|
||||
AlternateNames: alternateNames,
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -308,7 +287,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Type: "server",
|
||||
AlternateNames: alternateNames,
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
}
|
||||
c.AddTask(t)
|
||||
}
|
||||
|
|
@ -335,7 +313,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Type: "server",
|
||||
AlternateNames: alternateNames,
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
|
||||
// @note: we use this for mutual tls between node and authorizer
|
||||
|
|
@ -344,7 +321,6 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
Subject: "cn=node-authorizer-client",
|
||||
Type: "client",
|
||||
Signer: defaultCA,
|
||||
Format: format,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["keypair_test.go"],
|
||||
deps = [
|
||||
"//pkg/apis/kops:go_default_library",
|
||||
"//pkg/diff:go_default_library",
|
||||
"//upup/pkg/fi:go_default_library",
|
||||
"//upup/pkg/fi/fitasks:go_default_library",
|
||||
"//util/pkg/vfs:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
@ -1,254 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
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 tests
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kops/pkg/diff"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/upup/pkg/fi/fitasks"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
)
|
||||
|
||||
type MockTarget struct {
|
||||
}
|
||||
|
||||
func (t *MockTarget) Finish(taskMap map[string]fi.Task) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *MockTarget) ProcessDeletions() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var _ fi.Target = &MockTarget{}
|
||||
|
||||
// Verifies that we regenerate keyset.yaml if they are deleted, which covers the upgrade scenario from kops 1.8 -> kops 1.9
|
||||
func TestKeypairUpgrade(t *testing.T) {
|
||||
lifecycle := fi.LifecycleSync
|
||||
|
||||
runTasksOptions := fi.RunTasksOptions{}
|
||||
runTasksOptions.MaxTaskDuration = 2 * time.Second
|
||||
|
||||
target := &MockTarget{}
|
||||
|
||||
cluster := &kops.Cluster{}
|
||||
vfs.Context.ResetMemfsContext(true)
|
||||
|
||||
basedir, err := vfs.Context.BuildVfsPath("memfs://keystore")
|
||||
if err != nil {
|
||||
t.Fatalf("error building vfs path: %v", err)
|
||||
}
|
||||
|
||||
keystore := fi.NewVFSCAStore(cluster, basedir, true)
|
||||
|
||||
// Generate predictable sequence numbers for testing
|
||||
var n int64
|
||||
keystore.SerialGenerator = func() *big.Int {
|
||||
n++
|
||||
return big.NewInt(n)
|
||||
}
|
||||
|
||||
// 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: format,
|
||||
}
|
||||
|
||||
kubelet := &fitasks.Keypair{
|
||||
Name: fi.String("kubelet"),
|
||||
Lifecycle: &lifecycle,
|
||||
Subject: "o=nodes,cn=kubelet",
|
||||
Type: "client",
|
||||
Signer: ca,
|
||||
Format: format,
|
||||
}
|
||||
|
||||
tasks := make(map[string]fi.Task)
|
||||
tasks["ca"] = ca
|
||||
tasks["kubelet"] = kubelet
|
||||
return tasks
|
||||
}
|
||||
|
||||
t.Logf("Building some keypairs")
|
||||
{
|
||||
allTasks := buildTasks()
|
||||
|
||||
context, err := fi.NewContext(target, nil, nil, keystore, nil, nil, true, allTasks)
|
||||
if err != nil {
|
||||
t.Fatalf("error building context: %v", err)
|
||||
}
|
||||
|
||||
if err := context.RunTasks(runTasksOptions); err != nil {
|
||||
t.Fatalf("unexpected error during Run: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the expected files were generated
|
||||
expected := []string{
|
||||
"memfs://keystore/issued/ca/1.crt",
|
||||
"memfs://keystore/issued/ca/keyset.yaml",
|
||||
"memfs://keystore/issued/kubelet/2.crt",
|
||||
"memfs://keystore/issued/kubelet/keyset.yaml",
|
||||
"memfs://keystore/private/ca/1.key",
|
||||
"memfs://keystore/private/ca/keyset.yaml",
|
||||
"memfs://keystore/private/kubelet/2.key",
|
||||
"memfs://keystore/private/kubelet/keyset.yaml",
|
||||
}
|
||||
checkPaths(t, basedir, expected)
|
||||
|
||||
// Save the contents of those files
|
||||
contents := make(map[string]string)
|
||||
for _, k := range expected {
|
||||
p, err := vfs.Context.BuildVfsPath(k)
|
||||
if err != nil {
|
||||
t.Fatalf("error building vfs path: %v", err)
|
||||
}
|
||||
b, err := p.ReadFile()
|
||||
if err != nil {
|
||||
t.Fatalf("error reading vfs path: %v", err)
|
||||
}
|
||||
contents[k] = string(b)
|
||||
}
|
||||
|
||||
t.Logf("verifying that rerunning tasks does not change keys")
|
||||
{
|
||||
allTasks := buildTasks()
|
||||
|
||||
context, err := fi.NewContext(target, nil, nil, keystore, nil, nil, true, allTasks)
|
||||
if err != nil {
|
||||
t.Fatalf("error building context: %v", err)
|
||||
}
|
||||
|
||||
if err := context.RunTasks(runTasksOptions); err != nil {
|
||||
t.Fatalf("unexpected error during Run: %v", err)
|
||||
}
|
||||
}
|
||||
checkContents(t, basedir, contents)
|
||||
|
||||
t.Logf("deleting keyset.yaml files and verifying they are recreated")
|
||||
FailOnError(t, basedir.Join("issued/ca/keyset.yaml").Remove())
|
||||
FailOnError(t, basedir.Join("issued/kubelet/keyset.yaml").Remove())
|
||||
FailOnError(t, basedir.Join("private/ca/keyset.yaml").Remove())
|
||||
FailOnError(t, basedir.Join("private/kubelet/keyset.yaml").Remove())
|
||||
|
||||
{
|
||||
allTasks := buildTasks()
|
||||
|
||||
context, err := fi.NewContext(target, nil, nil, keystore, nil, nil, true, allTasks)
|
||||
if err != nil {
|
||||
t.Fatalf("error building context: %v", err)
|
||||
}
|
||||
|
||||
if err := context.RunTasks(runTasksOptions); err != nil {
|
||||
t.Fatalf("unexpected error during Run: %v", err)
|
||||
}
|
||||
}
|
||||
checkContents(t, basedir, contents)
|
||||
}
|
||||
|
||||
// FailOnError calls t.Fatalf if err != nil
|
||||
func FailOnError(t *testing.T, err error) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// checkPaths verifies that the path names in the tree rooted at basedir are exactly as expected
|
||||
// Unlike checkContents, it only verifies the names, not the contents
|
||||
func checkPaths(t *testing.T, basedir vfs.Path, expected []string) {
|
||||
paths, err := basedir.ReadTree()
|
||||
if err != nil {
|
||||
t.Errorf("ReadTree failed: %v", err)
|
||||
}
|
||||
|
||||
var actual []string
|
||||
for _, p := range paths {
|
||||
actual = append(actual, p.Path())
|
||||
}
|
||||
sort.Strings(actual)
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("unexpected paths: %v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
// checkPaths verifies that the files and their contents in the tree rooted at basedir are exactly as expected
|
||||
func checkContents(t *testing.T, basedir vfs.Path, expected map[string]string) {
|
||||
paths, err := basedir.ReadTree()
|
||||
if err != nil {
|
||||
t.Errorf("ReadTree failed: %v", err)
|
||||
}
|
||||
|
||||
actual := make(map[string]string)
|
||||
for _, p := range paths {
|
||||
b, err := p.ReadFile()
|
||||
if err != nil {
|
||||
t.Fatalf("error reading vfs path %q: %v", p, err)
|
||||
}
|
||||
actual[p.Path()] = string(b)
|
||||
}
|
||||
|
||||
var actualKeys []string
|
||||
for k := range actual {
|
||||
actualKeys = append(actualKeys, k)
|
||||
}
|
||||
sort.Strings(actualKeys)
|
||||
var expectedKeys []string
|
||||
for k := range expected {
|
||||
expectedKeys = append(expectedKeys, k)
|
||||
}
|
||||
sort.Strings(expectedKeys)
|
||||
|
||||
if !reflect.DeepEqual(actualKeys, expectedKeys) {
|
||||
t.Fatalf("unexpected paths: %v", actualKeys)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
for k := range actual {
|
||||
if actual[k] != expected[k] {
|
||||
t.Errorf("mismatch on key %q", k)
|
||||
t.Errorf("diff: %s", diff.FormatDiff(actual[k], expected[k]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,11 +33,8 @@ const (
|
|||
SecretNameSSHPrimary = "admin"
|
||||
)
|
||||
|
||||
type KeysetFormat string
|
||||
|
||||
const (
|
||||
KeysetFormatLegacy KeysetFormat = "legacy"
|
||||
KeysetFormatV1Alpha2 KeysetFormat = "v1alpha2"
|
||||
keysetFormatLatest = "v1alpha2"
|
||||
)
|
||||
|
||||
type KeystoreItem struct {
|
||||
|
|
@ -51,10 +48,10 @@ type KeystoreItem struct {
|
|||
type Keystore interface {
|
||||
// FindKeypair finds a cert & private key, returning nil where either is not found
|
||||
// (if the certificate is found but not keypair, that is not an error: only the cert will be returned).
|
||||
// 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, KeysetFormat, error)
|
||||
// This func returns a cert, private key and a bool. The bool value is whether the keypair is stored
|
||||
// in a legacy format. This bool is used by a keypair
|
||||
// task to convert a Legacy Keypair to the new Keypair API format.
|
||||
FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, bool, error)
|
||||
|
||||
CreateKeypair(signer string, name string, template *x509.Certificate, privateKey *pki.PrivateKey) (*pki.Certificate, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -98,9 +98,9 @@ func (c *ClientsetCAStore) readCAKeypairs(ctx context.Context, id string) (*keys
|
|||
|
||||
// keyset is a parsed Keyset
|
||||
type keyset struct {
|
||||
format KeysetFormat
|
||||
items map[string]*keysetItem
|
||||
primary *keysetItem
|
||||
legacyFormat bool
|
||||
items map[string]*keysetItem
|
||||
primary *keysetItem
|
||||
}
|
||||
|
||||
// keysetItem is a parsed KeysetItem
|
||||
|
|
@ -160,7 +160,6 @@ func (c *ClientsetCAStore) loadKeyset(ctx context.Context, name string) (*keyset
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyset.format = KeysetFormatV1Alpha2
|
||||
return keyset, nil
|
||||
}
|
||||
|
||||
|
|
@ -205,18 +204,18 @@ func FindPrimary(keyset *kops.Keyset) *kops.KeysetItem {
|
|||
}
|
||||
|
||||
// FindKeypair implements CAStore::FindKeypair
|
||||
func (c *ClientsetCAStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, KeysetFormat, error) {
|
||||
func (c *ClientsetCAStore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
ctx := context.TODO()
|
||||
keyset, err := c.loadKeyset(ctx, name)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
return nil, nil, false, err
|
||||
}
|
||||
|
||||
if keyset != nil && keyset.primary != nil {
|
||||
return keyset.primary.certificate, keyset.primary.privateKey, keyset.format, nil
|
||||
return keyset.primary.certificate, keyset.primary.privateKey, keyset.legacyFormat, nil
|
||||
}
|
||||
|
||||
return nil, nil, "", nil
|
||||
return nil, nil, false, nil
|
||||
}
|
||||
|
||||
// FindCert implements CAStore::FindCert
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ func runChannelBuilderTest(t *testing.T, key string, addonManifests []string) {
|
|||
if err != nil {
|
||||
t.Errorf("error building vfspath: %v", err)
|
||||
}
|
||||
clientset := vfsclientset.NewVFSClientset(basePath, true)
|
||||
clientset := vfsclientset.NewVFSClientset(basePath)
|
||||
|
||||
secretStore, err := clientset.SecretStore(cluster)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ func mockedPopulateClusterSpec(c *kopsapi.Cluster) (*kopsapi.Cluster, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error building vfspath: %v", err)
|
||||
}
|
||||
clientset := vfsclientset.NewVFSClientset(basePath, true)
|
||||
clientset := vfsclientset.NewVFSClientset(basePath)
|
||||
return PopulateClusterSpec(clientset, c, assetBuilder)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@ type Keypair struct {
|
|||
Subject string `json:"subject"`
|
||||
// Type the type of certificate i.e. CA, server, client etc
|
||||
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:"format"`
|
||||
// LegacyFormat is whether the keypair is stored in a legacy format.
|
||||
LegacyFormat bool `json:"oldFormat"`
|
||||
}
|
||||
|
||||
var _ fi.HasCheckExisting = &Keypair{}
|
||||
|
|
@ -76,7 +75,7 @@ func (e *Keypair) Find(c *fi.Context) (*Keypair, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
cert, key, format, err := c.Keystore.FindKeypair(name)
|
||||
cert, key, legacyFormat, err := c.Keystore.FindKeypair(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -100,7 +99,7 @@ func (e *Keypair) Find(c *fi.Context) (*Keypair, error) {
|
|||
AlternateNames: alternateNames,
|
||||
Subject: pkixNameToString(&cert.Subject),
|
||||
Type: buildTypeDescription(cert.Certificate),
|
||||
Format: string(format),
|
||||
LegacyFormat: legacyFormat,
|
||||
}
|
||||
|
||||
actual.Signer = &Keypair{Subject: pkixNameToString(&cert.Certificate.Issuer)}
|
||||
|
|
@ -190,7 +189,7 @@ func (_ *Keypair) Render(c *fi.Context, a, e, changes *Keypair) error {
|
|||
} else if changes.Type != "" {
|
||||
createCertificate = true
|
||||
klog.V(8).Infof("creating certificate new Type")
|
||||
} else if changes.Format != "" {
|
||||
} else if changes.LegacyFormat {
|
||||
changeStoredFormat = true
|
||||
} else {
|
||||
klog.Warningf("Ignoring changes in key: %v", fi.DebugAsJsonString(changes))
|
||||
|
|
@ -244,7 +243,7 @@ func (_ *Keypair) Render(c *fi.Context, a, e, changes *Keypair) error {
|
|||
return err
|
||||
}
|
||||
|
||||
klog.Infof("updated Keypair %q to API format %q", name, e.Format)
|
||||
klog.Infof("updated Keypair %q to new format", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
|||
return fmt.Errorf("error building key store path: %v", err)
|
||||
}
|
||||
|
||||
modelContext.KeyStore = fi.NewVFSCAStore(c.cluster, p, false)
|
||||
modelContext.KeyStore = fi.NewVFSCAStore(c.cluster, p)
|
||||
} else {
|
||||
return fmt.Errorf("KeyStore not set")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,8 @@ import (
|
|||
)
|
||||
|
||||
type VFSCAStore struct {
|
||||
basedir vfs.Path
|
||||
cluster *kops.Cluster
|
||||
allowList bool
|
||||
basedir vfs.Path
|
||||
cluster *kops.Cluster
|
||||
|
||||
mutex sync.Mutex
|
||||
cachedCAs map[string]*cachedEntry
|
||||
|
|
@ -58,12 +57,11 @@ type cachedEntry struct {
|
|||
var _ CAStore = &VFSCAStore{}
|
||||
var _ SSHCredentialStore = &VFSCAStore{}
|
||||
|
||||
func NewVFSCAStore(cluster *kops.Cluster, basedir vfs.Path, allowList bool) *VFSCAStore {
|
||||
func NewVFSCAStore(cluster *kops.Cluster, basedir vfs.Path) *VFSCAStore {
|
||||
c := &VFSCAStore{
|
||||
basedir: basedir,
|
||||
cluster: cluster,
|
||||
cachedCAs: make(map[string]*cachedEntry),
|
||||
allowList: allowList,
|
||||
}
|
||||
|
||||
c.SerialGenerator = func() *big.Int {
|
||||
|
|
@ -100,7 +98,7 @@ func (s *VFSCAStore) readCAKeypairs(id string) (*keyset, *keyset, error) {
|
|||
return cached.certificates, cached.privateKeys, nil
|
||||
}
|
||||
|
||||
caCertificates, err := s.loadCertificates(s.buildCertificatePoolPath(id), true)
|
||||
caCertificates, err := s.loadCertificates(s.buildCertificatePoolPath(id))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -108,7 +106,7 @@ func (s *VFSCAStore) readCAKeypairs(id string) (*keyset, *keyset, error) {
|
|||
var caPrivateKeys *keyset
|
||||
|
||||
if caCertificates != nil {
|
||||
caPrivateKeys, err = s.loadPrivateKeys(s.buildPrivateKeyPoolPath(id), true)
|
||||
caPrivateKeys, err = s.loadPrivateKeys(s.buildPrivateKeyPoolPath(id))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -147,24 +145,24 @@ func (c *VFSCAStore) buildPrivateKeyPath(name string, id string) vfs.Path {
|
|||
return c.basedir.Join("private", name, id+".key")
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) parseKeysetYaml(data []byte) (*kops.Keyset, KeysetFormat, error) {
|
||||
func (c *VFSCAStore) parseKeysetYaml(data []byte) (*kops.Keyset, bool, error) {
|
||||
defaultReadVersion := v1alpha2.SchemeGroupVersion.WithKind("Keyset")
|
||||
|
||||
object, gvk, err := kopscodecs.Decode(data, &defaultReadVersion)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error parsing keyset: %v", err)
|
||||
return nil, false, fmt.Errorf("error parsing keyset: %v", err)
|
||||
}
|
||||
|
||||
keyset, ok := object.(*kops.Keyset)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("object was not a keyset, was a %T", object)
|
||||
return nil, false, fmt.Errorf("object was not a keyset, was a %T", object)
|
||||
}
|
||||
|
||||
if gvk == nil {
|
||||
return nil, "", fmt.Errorf("object did not have GroupVersionKind: %q", keyset.Name)
|
||||
return nil, false, fmt.Errorf("object did not have GroupVersionKind: %q", keyset.Name)
|
||||
}
|
||||
|
||||
return keyset, KeysetFormat(gvk.Version), nil
|
||||
return keyset, gvk.Version != keysetFormatLatest, nil
|
||||
}
|
||||
|
||||
// loadCertificatesBundle loads a keyset from the path
|
||||
|
|
@ -179,7 +177,7 @@ func (c *VFSCAStore) loadKeysetBundle(p vfs.Path) (*keyset, error) {
|
|||
return nil, fmt.Errorf("unable to read bundle %q: %v", p, err)
|
||||
}
|
||||
|
||||
o, format, err := c.parseKeysetYaml(data)
|
||||
o, legacyFormat, err := c.parseKeysetYaml(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing bundle %q: %v", p, err)
|
||||
}
|
||||
|
|
@ -189,7 +187,7 @@ func (c *VFSCAStore) loadKeysetBundle(p vfs.Path) (*keyset, error) {
|
|||
return nil, fmt.Errorf("error mapping bundle %q: %v", p, err)
|
||||
}
|
||||
|
||||
keyset.format = format
|
||||
keyset.legacyFormat = legacyFormat
|
||||
return keyset, nil
|
||||
}
|
||||
|
||||
|
|
@ -291,64 +289,10 @@ func SerializeKeyset(o *kops.Keyset) ([]byte, error) {
|
|||
return objectData.Bytes(), nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) loadCertificates(p vfs.Path, useBundle bool) (*keyset, error) {
|
||||
// Attempt to load prebuilt bundle, which avoids having to list files, which is a permission that can be hard to
|
||||
// give on GCE / other clouds
|
||||
if useBundle {
|
||||
bundlePath := p.Join("keyset.yaml")
|
||||
bundle, err := c.loadKeysetBundle(bundlePath)
|
||||
if !c.allowList {
|
||||
return bundle, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
klog.Warningf("unable to read bundle %q, falling back to directory-list method: %v", bundlePath, err)
|
||||
} else if bundle == nil {
|
||||
klog.V(2).Infof("no certificate bundle %q, falling back to directory-list method", bundlePath)
|
||||
} else {
|
||||
return bundle, nil
|
||||
}
|
||||
}
|
||||
|
||||
keyset := &keyset{
|
||||
items: make(map[string]*keysetItem),
|
||||
}
|
||||
|
||||
files, err := p.ReadDir()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
id := f.Base()
|
||||
if strings.HasSuffix(id, ".yaml") {
|
||||
// ignore bundle
|
||||
continue
|
||||
}
|
||||
id = strings.TrimSuffix(id, ".crt")
|
||||
|
||||
cert, err := c.loadOneCertificate(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading certificate %q: %v", f, err)
|
||||
}
|
||||
|
||||
keyset.items[id] = &keysetItem{
|
||||
id: id,
|
||||
certificate: cert,
|
||||
}
|
||||
}
|
||||
|
||||
if len(keyset.items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
keyset.format = KeysetFormatLegacy
|
||||
keyset.primary = keyset.findPrimary()
|
||||
|
||||
return keyset, nil
|
||||
func (c *VFSCAStore) loadCertificates(p vfs.Path) (*keyset, error) {
|
||||
bundlePath := p.Join("keyset.yaml")
|
||||
bundle, err := c.loadKeysetBundle(bundlePath)
|
||||
return bundle, err
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) loadOneCertificate(p vfs.Path) (*pki.Certificate, error) {
|
||||
|
|
@ -369,32 +313,32 @@ func (c *VFSCAStore) loadOneCertificate(p vfs.Path) (*pki.Certificate, error) {
|
|||
return cert, nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) FindKeypair(id string) (*pki.Certificate, *pki.PrivateKey, KeysetFormat, error) {
|
||||
cert, certFormat, err := c.findCert(id)
|
||||
func (c *VFSCAStore) FindKeypair(id string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
|
||||
cert, legacyFormat, err := c.findCert(id)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
return nil, nil, false, err
|
||||
}
|
||||
|
||||
key, err := c.FindPrivateKey(id)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
return nil, nil, false, err
|
||||
}
|
||||
|
||||
return cert, key, certFormat, nil
|
||||
return cert, key, legacyFormat, nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) findCert(name string) (*pki.Certificate, KeysetFormat, error) {
|
||||
func (c *VFSCAStore) findCert(name string) (*pki.Certificate, bool, error) {
|
||||
p := c.buildCertificatePoolPath(name)
|
||||
certs, err := c.loadCertificates(p, true)
|
||||
certs, err := c.loadCertificates(p)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error in 'FindCert' attempting to load cert %q: %v", name, err)
|
||||
return nil, false, fmt.Errorf("error in 'FindCert' attempting to load cert %q: %v", name, err)
|
||||
}
|
||||
|
||||
if certs != nil && certs.primary != nil {
|
||||
return certs.primary.certificate, certs.format, nil
|
||||
return certs.primary.certificate, certs.legacyFormat, nil
|
||||
}
|
||||
|
||||
return nil, "", nil
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) FindCert(name string) (*pki.Certificate, error) {
|
||||
|
|
@ -407,7 +351,7 @@ func (c *VFSCAStore) FindCertificatePool(name string) (*CertificatePool, error)
|
|||
|
||||
var err error
|
||||
p := c.buildCertificatePoolPath(name)
|
||||
certs, err = c.loadCertificates(p, true)
|
||||
certs, err = c.loadCertificates(p)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error in 'FindCertificatePool' attempting to load cert %q: %v", name, err)
|
||||
}
|
||||
|
|
@ -434,7 +378,7 @@ func (c *VFSCAStore) FindCertificatePool(name string) (*CertificatePool, error)
|
|||
|
||||
func (c *VFSCAStore) FindCertificateKeyset(name string) (*kops.Keyset, error) {
|
||||
p := c.buildCertificatePoolPath(name)
|
||||
certs, err := c.loadCertificates(p, true)
|
||||
certs, err := c.loadCertificates(p)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error in 'FindCertificatePool' attempting to load cert %q: %v", name, err)
|
||||
}
|
||||
|
|
@ -731,78 +675,11 @@ func (c *VFSCAStore) AddCert(name string, cert *pki.Certificate) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) loadPrivateKeys(p vfs.Path, useBundle bool) (*keyset, error) {
|
||||
// Attempt to load prebuilt bundle, which avoids having to list files, which is a permission that can be hard to
|
||||
// give on GCE / other clouds
|
||||
if useBundle {
|
||||
bundlePath := p.Join("keyset.yaml")
|
||||
bundle, err := c.loadKeysetBundle(bundlePath)
|
||||
func (c *VFSCAStore) loadPrivateKeys(p vfs.Path) (*keyset, error) {
|
||||
bundlePath := p.Join("keyset.yaml")
|
||||
bundle, err := c.loadKeysetBundle(bundlePath)
|
||||
|
||||
if !c.allowList {
|
||||
return bundle, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
klog.Warningf("unable to read bundle %q, falling back to directory-list method: %v", bundlePath, err)
|
||||
} else if bundle == nil {
|
||||
klog.V(2).Infof("no private key bundle %q, falling back to directory-list method", bundlePath)
|
||||
} else {
|
||||
return bundle, nil
|
||||
}
|
||||
}
|
||||
|
||||
files, err := p.ReadDir()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys := &keyset{
|
||||
items: make(map[string]*keysetItem),
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
id := f.Base()
|
||||
if strings.HasSuffix(id, ".yaml") {
|
||||
// ignore bundle
|
||||
continue
|
||||
}
|
||||
id = strings.TrimSuffix(id, ".key")
|
||||
|
||||
privateKey, err := c.loadOnePrivateKey(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading private key %q: %v", f, err)
|
||||
}
|
||||
keys.items[id] = &keysetItem{
|
||||
id: id,
|
||||
privateKey: privateKey,
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys.items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
keys.primary = keys.findPrimary()
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) loadOnePrivateKey(p vfs.Path) (*pki.PrivateKey, error) {
|
||||
data, err := p.ReadFile()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
k, err := pki.ParsePEMPrivateKey(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing private key from %q: %v", p, err)
|
||||
}
|
||||
return k, err
|
||||
return bundle, err
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) findPrivateKeyset(id string) (*keyset, error) {
|
||||
|
|
@ -816,7 +693,7 @@ func (c *VFSCAStore) findPrivateKeyset(id string) (*keyset, error) {
|
|||
} else {
|
||||
var err error
|
||||
p := c.buildPrivateKeyPoolPath(id)
|
||||
keys, err = c.loadPrivateKeys(p, true)
|
||||
keys, err = c.loadPrivateKeys(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -871,7 +748,7 @@ func (c *VFSCAStore) storePrivateKey(name string, ki *keysetItem) error {
|
|||
// Write the bundle
|
||||
{
|
||||
p := c.buildPrivateKeyPoolPath(name)
|
||||
ks, err := c.loadPrivateKeys(p, false)
|
||||
ks, err := c.loadPrivateKeys(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -889,6 +766,7 @@ func (c *VFSCAStore) storePrivateKey(name string, ki *keysetItem) error {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO stop writing and remove legacy format files after rollback to pre-kops 1.18 not needed
|
||||
// Write the data
|
||||
{
|
||||
var data bytes.Buffer
|
||||
|
|
@ -913,7 +791,7 @@ func (c *VFSCAStore) storeCertificate(name string, ki *keysetItem) error {
|
|||
// Write the bundle
|
||||
{
|
||||
p := c.buildCertificatePoolPath(name)
|
||||
ks, err := c.loadCertificates(p, false)
|
||||
ks, err := c.loadCertificates(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -931,6 +809,7 @@ func (c *VFSCAStore) storeCertificate(name string, ki *keysetItem) error {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO stop writing and remove legacy format files after rollback to pre-kops 1.18 not needed
|
||||
// Write the data
|
||||
{
|
||||
var data bytes.Buffer
|
||||
|
|
@ -948,10 +827,19 @@ func (c *VFSCAStore) storeCertificate(name string, ki *keysetItem) error {
|
|||
}
|
||||
|
||||
func (c *VFSCAStore) deletePrivateKey(name string, id string) (bool, error) {
|
||||
// Delete the file itself
|
||||
{
|
||||
|
||||
p := c.buildPrivateKeyPath(name, id)
|
||||
if err := p.Remove(); err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Update the bundle
|
||||
{
|
||||
p := c.buildPrivateKeyPoolPath(name)
|
||||
ks, err := c.loadPrivateKeys(p, false)
|
||||
ks, err := c.loadPrivateKeys(p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -966,22 +854,22 @@ func (c *VFSCAStore) deletePrivateKey(name string, id string) (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Delete the file itself
|
||||
{
|
||||
|
||||
p := c.buildPrivateKeyPath(name, id)
|
||||
if err := p.Remove(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *VFSCAStore) deleteCertificate(name string, id string) (bool, error) {
|
||||
// Delete the file itself
|
||||
{
|
||||
p := c.buildCertificatePath(name, id)
|
||||
if err := p.Remove(); err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Update the bundle
|
||||
{
|
||||
p := c.buildCertificatePoolPath(name)
|
||||
ks, err := c.loadCertificates(p, false)
|
||||
ks, err := c.loadCertificates(p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -996,14 +884,7 @@ func (c *VFSCAStore) deleteCertificate(name string, id string) (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Delete the file itself
|
||||
{
|
||||
p := c.buildCertificatePath(name, id)
|
||||
if err := p.Remove(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// AddSSHPublicKey stores an SSH public key
|
||||
|
|
|
|||
Loading…
Reference in New Issue