Skip to content

Commit

Permalink
Add workload cluster kubeconfig certs rotation
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Pedriza <adripedriza@gmail.com>
  • Loading branch information
AdrianPedriza committed Dec 18, 2024
1 parent 20f08e2 commit c5e736d
Showing 1 changed file with 37 additions and 4 deletions.
41 changes: 37 additions & 4 deletions internal/controller/controlplane/k0s_controlplane_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
kubeadmbootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
capiutil "sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/annotations"
"sigs.k8s.io/cluster-api/util/certs"
"sigs.k8s.io/cluster-api/util/collections"
"sigs.k8s.io/cluster-api/util/failuredomains"
"sigs.k8s.io/cluster-api/util/kubeconfig"
Expand Down Expand Up @@ -201,23 +202,50 @@ func (c *K0sController) Reconcile(ctx context.Context, req ctrl.Request) (res ct
}

func (c *K0sController) reconcileKubeconfig(ctx context.Context, cluster *clusterv1.Cluster, kcp *cpv1beta1.K0sControlPlane) error {
logger := log.FromContext(ctx, "cluster", cluster.Name, "kcp", kcp.Name)

if cluster.Spec.ControlPlaneEndpoint.IsZero() {
return fmt.Errorf("control plane endpoint is not set: %w", ErrNotReady)
}

secretName := secret.Name(cluster.Name, secret.Kubeconfig)
err := c.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: secretName}, &corev1.Secret{})
kubeconfigSecrets := []*corev1.Secret{}

// Always rotate certificates if needed.
defer func() {
for _, kc := range kubeconfigSecrets {
needsRotation, err := kubeconfig.NeedsClientCertRotation(kc, certs.ClientCertificateRenewalDuration)
if err != nil {
logger.Error(err, "Failed to check if certificate needs rotation.")
return
}

if needsRotation {
logger.Info("Rotating kubeconfig secret", "Secret", kc.GetName())
if err := kubeconfig.RegenerateSecret(ctx, c.Client, kc); err != nil {
logger.Error(err, "Failed to regenerate kubeconfig")
return
}
}
}
}()

workloadClusterKubeconfigSecret, err := secret.GetFromNamespacedName(ctx, c.Client, capiutil.ObjectKey(cluster), secret.Kubeconfig)
if err != nil {
if apierrors.IsNotFound(err) {
return kubeconfig.CreateSecret(ctx, c.Client, cluster)
}

return err
}
kubeconfigSecrets = append(kubeconfigSecrets, workloadClusterKubeconfigSecret)

if kcp.Spec.K0sConfigSpec.Tunneling.Enabled {
if kcp.Spec.K0sConfigSpec.Tunneling.Mode == "proxy" {

secretName := secret.Name(cluster.Name+"-proxied", secret.Kubeconfig)
err := c.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: secretName}, &corev1.Secret{})

proxiedKubeconfig := &corev1.Secret{}
err := c.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: secretName}, proxiedKubeconfig)
if err != nil {
if apierrors.IsNotFound(err) {
kc, err := c.generateKubeconfig(ctx, cluster, fmt.Sprintf("https://%s", cluster.Spec.ControlPlaneEndpoint.String()))
Expand All @@ -236,9 +264,13 @@ func (c *K0sController) reconcileKubeconfig(ctx context.Context, cluster *cluste
}
return err
}
kubeconfigSecrets = append(kubeconfigSecrets, proxiedKubeconfig)

} else {
secretName := secret.Name(cluster.Name+"-tunneled", secret.Kubeconfig)
err := c.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: secretName}, &corev1.Secret{})

tunneledKubeconfig := &corev1.Secret{}
err := c.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: secretName}, tunneledKubeconfig)
if err != nil {
if apierrors.IsNotFound(err) {
kc, err := c.generateKubeconfig(ctx, cluster, fmt.Sprintf("https://%s:%d", kcp.Spec.K0sConfigSpec.Tunneling.ServerAddress, kcp.Spec.K0sConfigSpec.Tunneling.TunnelingNodePort))
Expand All @@ -253,6 +285,7 @@ func (c *K0sController) reconcileKubeconfig(ctx context.Context, cluster *cluste
}
return err
}
kubeconfigSecrets = append(kubeconfigSecrets, tunneledKubeconfig)
}
}

Expand Down

0 comments on commit c5e736d

Please sign in to comment.