diff --git a/charts/k3k/crds/k3k.io_clusters.yaml b/charts/k3k/crds/k3k.io_clusters.yaml index f54f0aeb..35295b6b 100644 --- a/charts/k3k/crds/k3k.io_clusters.yaml +++ b/charts/k3k/crds/k3k.io_clusters.yaml @@ -228,6 +228,7 @@ spec: certificates. properties: enabled: + default: true description: Enabled toggles this feature on or off. type: boolean sources: @@ -244,6 +245,8 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object etcdPeerCA: description: ETCDPeerCA specifies the etcd-peer-ca cert/key @@ -256,6 +259,8 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object etcdServerCA: description: ETCDServerCA specifies the etcd-server-ca cert/key @@ -268,6 +273,8 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object requestHeaderCA: description: RequestHeaderCA specifies the request-header-ca @@ -280,6 +287,8 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object serverCA: description: ServerCA specifies the server-ca cert/key pair. @@ -291,6 +300,8 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object serviceAccountToken: description: ServiceAccountToken specifies the service-account-token @@ -303,8 +314,20 @@ spec: - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. - For ServiceAccountTokenKey: 'tls.key'. type: string + required: + - secretName type: object + required: + - clientCA + - etcdPeerCA + - etcdServerCA + - requestHeaderCA + - serverCA + - serviceAccountToken type: object + required: + - enabled + - sources type: object expose: description: |- diff --git a/cli/cmds/cluster_create.go b/cli/cmds/cluster_create.go index 2e4f1797..e9c5da7c 100644 --- a/cli/cmds/cluster_create.go +++ b/cli/cmds/cluster_create.go @@ -211,7 +211,7 @@ func newCluster(name, namespace string, config *CreateConfig) *v1beta1.Cluster { } if config.customCertsPath != "" { - cluster.Spec.CustomCAs = v1beta1.CustomCAs{ + cluster.Spec.CustomCAs = &v1beta1.CustomCAs{ Enabled: true, Sources: v1beta1.CredentialSources{ ClientCA: v1beta1.CredentialSource{ diff --git a/docs/crds/crd-docs.md b/docs/crds/crd-docs.md index 5dab0ef2..1f5a4328 100644 --- a/docs/crds/crd-docs.md +++ b/docs/crds/crd-docs.md @@ -208,7 +208,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `enabled` _boolean_ | Enabled toggles this feature on or off. | | | +| `enabled` _boolean_ | Enabled toggles this feature on or off. | true | | | `sources` _[CredentialSources](#credentialsources)_ | Sources defines the sources for all required custom CA certificates. | | | diff --git a/pkg/apis/k3k.io/v1beta1/types.go b/pkg/apis/k3k.io/v1beta1/types.go index da4c9f7d..60a2473d 100644 --- a/pkg/apis/k3k.io/v1beta1/types.go +++ b/pkg/apis/k3k.io/v1beta1/types.go @@ -176,7 +176,7 @@ type ClusterSpec struct { // CustomCAs specifies the cert/key pairs for custom CA certificates. // // +optional - CustomCAs CustomCAs `json:"customCAs,omitempty"` + CustomCAs *CustomCAs `json:"customCAs,omitempty"` // Sync specifies the resources types that will be synced from virtual cluster to host cluster. // @@ -416,32 +416,34 @@ type NodePortConfig struct { // CustomCAs specifies the cert/key pairs for custom CA certificates. type CustomCAs struct { // Enabled toggles this feature on or off. - Enabled bool `json:"enabled,omitempty"` + // + // +kubebuilder:default=true + Enabled bool `json:"enabled"` // Sources defines the sources for all required custom CA certificates. - Sources CredentialSources `json:"sources,omitempty"` + Sources CredentialSources `json:"sources"` } // CredentialSources lists all the required credentials, including both // TLS key pairs and single signing keys. type CredentialSources struct { // ServerCA specifies the server-ca cert/key pair. - ServerCA CredentialSource `json:"serverCA,omitempty"` + ServerCA CredentialSource `json:"serverCA"` // ClientCA specifies the client-ca cert/key pair. - ClientCA CredentialSource `json:"clientCA,omitempty"` + ClientCA CredentialSource `json:"clientCA"` // RequestHeaderCA specifies the request-header-ca cert/key pair. - RequestHeaderCA CredentialSource `json:"requestHeaderCA,omitempty"` + RequestHeaderCA CredentialSource `json:"requestHeaderCA"` // ETCDServerCA specifies the etcd-server-ca cert/key pair. - ETCDServerCA CredentialSource `json:"etcdServerCA,omitempty"` + ETCDServerCA CredentialSource `json:"etcdServerCA"` // ETCDPeerCA specifies the etcd-peer-ca cert/key pair. - ETCDPeerCA CredentialSource `json:"etcdPeerCA,omitempty"` + ETCDPeerCA CredentialSource `json:"etcdPeerCA"` // ServiceAccountToken specifies the service-account-token key. - ServiceAccountToken CredentialSource `json:"serviceAccountToken,omitempty"` + ServiceAccountToken CredentialSource `json:"serviceAccountToken"` } // CredentialSource defines where to get a credential from. @@ -451,8 +453,7 @@ type CredentialSource struct { // The controller expects specific keys inside based on the credential type: // - For TLS pairs (e.g., ServerCA): 'tls.crt' and 'tls.key'. // - For ServiceAccountTokenKey: 'tls.key'. - // +optional - SecretName string `json:"secretName,omitempty"` + SecretName string `json:"secretName"` } // ClusterStatus reflects the observed state of a Cluster. diff --git a/pkg/apis/k3k.io/v1beta1/zz_generated.deepcopy.go b/pkg/apis/k3k.io/v1beta1/zz_generated.deepcopy.go index df75675c..d359555f 100644 --- a/pkg/apis/k3k.io/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/k3k.io/v1beta1/zz_generated.deepcopy.go @@ -163,7 +163,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { (*out)[key] = val.DeepCopy() } } - out.CustomCAs = in.CustomCAs + if in.CustomCAs != nil { + in, out := &in.CustomCAs, &out.CustomCAs + *out = new(CustomCAs) + **out = **in + } if in.Sync != nil { in, out := &in.Sync, &out.Sync *out = new(SyncConfig) diff --git a/pkg/controller/cluster/cluster.go b/pkg/controller/cluster/cluster.go index d5bc9c8b..fa34469a 100644 --- a/pkg/controller/cluster/cluster.go +++ b/pkg/controller/cluster/cluster.go @@ -736,8 +736,8 @@ func (c *ClusterReconciler) validate(cluster *v1beta1.Cluster, policy v1beta1.Vi return fmt.Errorf("%w: mode %q is not allowed by the policy %q", ErrClusterValidation, cluster.Spec.Mode, policy.Name) } - if cluster.Spec.CustomCAs.Enabled { - if err := c.validateCustomCACerts(cluster); err != nil { + if cluster.Spec.CustomCAs != nil && cluster.Spec.CustomCAs.Enabled { + if err := c.validateCustomCACerts(cluster.Spec.CustomCAs.Sources); err != nil { return fmt.Errorf("%w: %w", ErrClusterValidation, err) } } @@ -828,8 +828,7 @@ func (c *ClusterReconciler) lookupServiceCIDR(ctx context.Context) (string, erro } // validateCustomCACerts will make sure that all the cert secrets exists -func (c *ClusterReconciler) validateCustomCACerts(cluster *v1beta1.Cluster) error { - credentialSources := cluster.Spec.CustomCAs.Sources +func (c *ClusterReconciler) validateCustomCACerts(credentialSources v1beta1.CredentialSources) error { if credentialSources.ClientCA.SecretName == "" || credentialSources.ServerCA.SecretName == "" || credentialSources.ETCDPeerCA.SecretName == "" || diff --git a/pkg/controller/cluster/cluster_test.go b/pkg/controller/cluster/cluster_test.go index d531e89f..2c00f308 100644 --- a/pkg/controller/cluster/cluster_test.go +++ b/pkg/controller/cluster/cluster_test.go @@ -53,6 +53,8 @@ var _ = Describe("Cluster Controller", Label("controller"), Label("Cluster"), fu Expect(cluster.Spec.Servers).To(Equal(ptr.To[int32](1))) Expect(cluster.Spec.Version).To(BeEmpty()) + Expect(cluster.Spec.CustomCAs).To(BeNil()) + Expect(cluster.Spec.Persistence.Type).To(Equal(v1beta1.DynamicPersistenceMode)) Expect(cluster.Spec.Persistence.StorageRequestSize).To(Equal("2G")) diff --git a/pkg/controller/cluster/server/server.go b/pkg/controller/cluster/server/server.go index 893df0ff..359f608a 100644 --- a/pkg/controller/cluster/server/server.go +++ b/pkg/controller/cluster/server/server.go @@ -330,7 +330,7 @@ func (s *Server) StatefulServer(ctx context.Context) (*apps.StatefulSet, error) volumeMounts = append(volumeMounts, volumeMount) } - if s.cluster.Spec.CustomCAs.Enabled { + if s.cluster.Spec.CustomCAs != nil && s.cluster.Spec.CustomCAs.Enabled { vols, mounts, err := s.loadCACertBundle(ctx) if err != nil { return nil, err @@ -434,6 +434,10 @@ func (s *Server) setupStartCommand() (string, error) { } func (s *Server) loadCACertBundle(ctx context.Context) ([]v1.Volume, []v1.VolumeMount, error) { + if s.cluster.Spec.CustomCAs == nil { + return nil, nil, fmt.Errorf("customCAs not found") + } + customCerts := s.cluster.Spec.CustomCAs.Sources caCertMap := map[string]string{ "server-ca": customCerts.ServerCA.SecretName, diff --git a/tests/cluster_certs_test.go b/tests/cluster_certs_test.go index dc629df8..8ab0dd14 100644 --- a/tests/cluster_certs_test.go +++ b/tests/cluster_certs_test.go @@ -56,7 +56,7 @@ var _ = When("a cluster with custom certificates is installed with individual ce cluster := NewCluster(namespace.Name) - cluster.Spec.CustomCAs = v1beta1.CustomCAs{ + cluster.Spec.CustomCAs = &v1beta1.CustomCAs{ Enabled: true, Sources: v1beta1.CredentialSources{ ServerCA: v1beta1.CredentialSource{