Skip to content

Commit 5a8e9e1

Browse files
cache the etcd client key
1 parent 88face9 commit 5a8e9e1

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

controllers/remote/cluster_cache_tracker.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package remote
1818

1919
import (
2020
"context"
21+
"crypto/rsa"
2122
"fmt"
2223
"os"
2324
"sync"
@@ -48,6 +49,7 @@ import (
4849

4950
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
5051
"sigs.k8s.io/cluster-api/feature"
52+
"sigs.k8s.io/cluster-api/util/certs"
5153
"sigs.k8s.io/cluster-api/util/conditions"
5254
)
5355

@@ -166,12 +168,23 @@ func (t *ClusterCacheTracker) GetRESTConfig(ctc context.Context, cluster client.
166168
return accessor.config, nil
167169
}
168170

171+
// GetEtcdClientCertificateKey returns a cached certificate key to be used for generating certificates for accessing etcd in the given cluster.
172+
func (t *ClusterCacheTracker) GetEtcdClientCertificateKey(ctx context.Context, cluster client.ObjectKey) (*rsa.PrivateKey, error) {
173+
accessor, err := t.getClusterAccessor(ctx, cluster, t.indexes...)
174+
if err != nil {
175+
return nil, err
176+
}
177+
178+
return accessor.etcdClientCertificateKey, nil
179+
}
180+
169181
// clusterAccessor represents the combination of a delegating client, cache, and watches for a remote cluster.
170182
type clusterAccessor struct {
171-
cache *stoppableCache
172-
client client.Client
173-
watches sets.Set[string]
174-
config *rest.Config
183+
cache *stoppableCache
184+
client client.Client
185+
watches sets.Set[string]
186+
config *rest.Config
187+
etcdClientCertificateKey *rsa.PrivateKey
175188
}
176189

177190
// clusterAccessorExists returns true if a clusterAccessor exists for cluster.
@@ -335,11 +348,20 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl
335348
return nil, err
336349
}
337350

351+
// Generating a new private key to be used for generating temporary certificates to connect to
352+
// etcd on the target cluster.
353+
// NOTE: Generating a private key is an expensive operation, so we store it in the cluster accessor.
354+
etcdKey, err := certs.NewPrivateKey()
355+
if err != nil {
356+
return nil, errors.Wrapf(err, "error creating etcd client key for remote cluster %q", cluster.String())
357+
}
358+
338359
return &clusterAccessor{
339-
cache: cache,
340-
config: config,
341-
client: delegatingClient,
342-
watches: sets.Set[string]{},
360+
cache: cache,
361+
config: config,
362+
client: delegatingClient,
363+
watches: sets.Set[string]{},
364+
etcdClientCertificateKey: etcdKey,
343365
}, nil
344366
}
345367

controlplane/kubeadm/internal/cluster.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ func (m *Management) GetWorkloadCluster(ctx context.Context, clusterKey client.O
141141
// TODO: consider if we can detect if we are using external etcd in a more explicit way (e.g. looking at the config instead of deriving from the existing certificates)
142142
var clientCert tls.Certificate
143143
if keyData != nil {
144-
clientCert, err = generateClientCert(crtData, keyData)
144+
clientKey, err := m.Tracker.GetEtcdClientCertificateKey(ctx, clusterKey)
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
clientCert, err = generateClientCert(crtData, keyData, clientKey)
145150
if err != nil {
146151
return nil, err
147152
}

controlplane/kubeadm/internal/workload_cluster.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,7 @@ func calculateAPIServerPort(config *bootstrapv1.KubeadmConfig) int32 {
489489
return 6443
490490
}
491491

492-
func generateClientCert(caCertEncoded, caKeyEncoded []byte) (tls.Certificate, error) {
493-
privKey, err := certs.NewPrivateKey()
494-
if err != nil {
495-
return tls.Certificate{}, err
496-
}
492+
func generateClientCert(caCertEncoded, caKeyEncoded []byte, clientKey *rsa.PrivateKey) (tls.Certificate, error) {
497493
caCert, err := certs.DecodeCertPEM(caCertEncoded)
498494
if err != nil {
499495
return tls.Certificate{}, err
@@ -502,11 +498,11 @@ func generateClientCert(caCertEncoded, caKeyEncoded []byte) (tls.Certificate, er
502498
if err != nil {
503499
return tls.Certificate{}, err
504500
}
505-
x509Cert, err := newClientCert(caCert, privKey, caKey)
501+
x509Cert, err := newClientCert(caCert, clientKey, caKey)
506502
if err != nil {
507503
return tls.Certificate{}, err
508504
}
509-
return tls.X509KeyPair(certs.EncodeCertPEM(x509Cert), certs.EncodePrivateKeyPEM(privKey))
505+
return tls.X509KeyPair(certs.EncodeCertPEM(x509Cert), certs.EncodePrivateKeyPEM(clientKey))
510506
}
511507

512508
func newClientCert(caCert *x509.Certificate, key *rsa.PrivateKey, caKey crypto.Signer) (*x509.Certificate, error) {

0 commit comments

Comments
 (0)