From c3e886c6cc1838488f18e1baa1360f0d7897610d Mon Sep 17 00:00:00 2001 From: Xiangjing Li Date: Tue, 20 Feb 2024 13:32:44 -0500 Subject: [PATCH] Add missing Fields to RosaControlPlane - tags, etcdEncryption Signed-off-by: Xiangjing Li --- ...ne.cluster.x-k8s.io_rosacontrolplanes.yaml | 10 ++++++++ .../api/v1beta2/rosacontrolplane_types.go | 9 ++++++++ .../api/v1beta2/rosacontrolplane_webhook.go | 23 +++++++++++++++++++ .../rosa/api/v1beta2/zz_generated.deepcopy.go | 7 ++++++ .../rosacontrolplane_controller.go | 20 +++++++++++++++- go.mod | 3 ++- go.sum | 6 +++-- .../cluster-template-rosa-machinepool.yaml | 2 -- templates/cluster-template-rosa.yaml | 2 -- 9 files changed, 74 insertions(+), 8 deletions(-) diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml index 245d9d72a6..afabff7f2b 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml @@ -45,6 +45,11 @@ spec: type: object spec: properties: + additionalTags: + additionalProperties: + type: string + description: User-defined tags for AWS resources + type: object availabilityZones: description: AWS AvailabilityZones of the worker nodes should match the AvailabilityZones of the Subnets. @@ -78,6 +83,11 @@ spec: type: string type: object x-kubernetes-map-type: atomic + etcdEncryptionKMSArn: + description: The etcd encryption kms key ARN is the key used to encrypt + etcd. It is only allowed for hosted cp and it needs to be pre-created + in AWS KMS with tag red-hat:true. + type: string identityRef: description: IdentityRef is a reference to an identity to be used when reconciling the managed control plane. If no identity is specified, diff --git a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go index 91728fc04b..ff81c21146 100644 --- a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go +++ b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go @@ -79,6 +79,15 @@ type RosaControlPlaneSpec struct { //nolint: maligned // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. // If no identity is specified, the default identity for this controller will be used. IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"` + + // User-defined tags for AWS resources + // +optional + AdditionalTags infrav1.Tags `json:"additionalTags,omitempty"` + + // The etcd encryption kms key ARN is the key used to encrypt etcd. + // It is only allowed for hosted cp and it needs to be pre-created in AWS KMS with tag red-hat:true. + // +optional + EtcdEncryptionKMSArn string `json:"etcdEncryptionKMSArn,omitempty"` } // AWSRolesRef contains references to various AWS IAM roles required for operators to make calls against the AWS API. diff --git a/controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go b/controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go index 13562167e5..1237610ef6 100644 --- a/controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go +++ b/controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go @@ -2,6 +2,7 @@ package v1beta2 import ( "github.com/blang/semver" + kmsArnRegexpValidator "github.com/openshift-online/ocm-common/pkg/resource/validations" apierrors "k8s.io/apimachinery/pkg/api/errors" runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" @@ -31,6 +32,12 @@ func (r *ROSAControlPlane) ValidateCreate() (warnings admission.Warnings, err er allErrs = append(allErrs, err) } + if err := r.validateKMSKeyARN(); err != nil { + allErrs = append(allErrs, err) + } + + allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...) + if len(allErrs) == 0 { return nil, nil } @@ -50,6 +57,12 @@ func (r *ROSAControlPlane) ValidateUpdate(old runtime.Object) (warnings admissio allErrs = append(allErrs, err) } + if err := r.validateKMSKeyARN(); err != nil { + allErrs = append(allErrs, err) + } + + allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...) + if len(allErrs) == 0 { return nil, nil } @@ -75,6 +88,16 @@ func (r *ROSAControlPlane) validateVersion() *field.Error { return nil } +func (r *ROSAControlPlane) validateKMSKeyARN() *field.Error { + // validate Etcd Encryption KMS Arn + err := kmsArnRegexpValidator.ValidateKMSKeyARN(&r.Spec.EtcdEncryptionKMSArn) + if err != nil { + return field.Invalid(field.NewPath("spec.EtcdEncryptionKMSArn"), r.Spec.EtcdEncryptionKMSArn, err.Error()) + } + + return nil +} + // Default implements admission.Defaulter. func (r *ROSAControlPlane) Default() { SetObjectDefaults_ROSAControlPlane(r) diff --git a/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go b/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go index 68ab8bae6c..aa16a1d40d 100644 --- a/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go +++ b/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go @@ -156,6 +156,13 @@ func (in *RosaControlPlaneSpec) DeepCopyInto(out *RosaControlPlaneSpec) { *out = new(apiv1beta2.AWSIdentityReference) **out = **in } + if in.AdditionalTags != nil { + in, out := &in.AdditionalTags, &out.AdditionalTags + *out = make(apiv1beta2.Tags, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RosaControlPlaneSpec. diff --git a/controlplane/rosa/controllers/rosacontrolplane_controller.go b/controlplane/rosa/controllers/rosacontrolplane_controller.go index 34a28ae4c8..c5b8b67971 100644 --- a/controlplane/rosa/controllers/rosacontrolplane_controller.go +++ b/controlplane/rosa/controllers/rosacontrolplane_controller.go @@ -269,7 +269,6 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc ID(*rosaScope.ControlPlane.Spec.Region), ). FIPS(false). - EtcdEncryption(false). DisableUserWorkloadMonitoring(true). Version( cmv1.NewVersion(). @@ -279,6 +278,14 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc ExpirationTimestamp(time.Now().Add(1 * time.Hour)). Hypershift(cmv1.NewHypershift().Enabled(true)) + etcdEncryption := false + // If EtcdEncryptionKMSArn is set, etcdEncryption is true. + if rosaScope.ControlPlane.Spec.EtcdEncryptionKMSArn != "" { + etcdEncryption = true + } + + clusterBuilder = clusterBuilder.EtcdEncryption(etcdEncryption) + networkBuilder := cmv1.NewNetwork() networkBuilder = networkBuilder.Type("OVNKubernetes") networkBuilder = networkBuilder.MachineCIDR(*rosaScope.ControlPlane.Spec.MachineCIDR) @@ -353,6 +360,17 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc BillingAccountID(*rosaScope.Identity.Account). SubnetIDs(rosaScope.ControlPlane.Spec.Subnets...). STS(stsBuilder) + + // specify additional tags + if len(rosaScope.ControlPlane.Spec.AdditionalTags) > 0 { + awsBuilder = awsBuilder.Tags(rosaScope.ControlPlane.Spec.AdditionalTags) + } + + // etcd encryption kms key arn + if rosaScope.ControlPlane.Spec.EtcdEncryptionKMSArn != "" { + awsBuilder = awsBuilder.EtcdEncryption(cmv1.NewAwsEtcdEncryption().KMSKeyARN(rosaScope.ControlPlane.Spec.EtcdEncryptionKMSArn)) + } + clusterBuilder = clusterBuilder.AWS(awsBuilder) clusterNodesBuilder := cmv1.NewClusterNodes() diff --git a/go.mod b/go.mod index 046be3cb9f..f3f885aebe 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,8 @@ require ( github.com/google/gofuzz v1.2.0 github.com/onsi/ginkgo/v2 v2.13.1 github.com/onsi/gomega v1.30.0 - github.com/openshift-online/ocm-sdk-go v0.1.388 + github.com/openshift-online/ocm-common v0.0.0-20240129111424-ff8c6c11d909 + github.com/openshift-online/ocm-sdk-go v0.1.391 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/sergi/go-diff v1.3.1 diff --git a/go.sum b/go.sum index 95c736aaff..71e1256e72 100644 --- a/go.sum +++ b/go.sum @@ -466,8 +466,10 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/openshift-online/ocm-sdk-go v0.1.388 h1:c8yPCUQwJm3QhcVmnyMPFpeDtxPBaPeYh5hLv1vg9YQ= -github.com/openshift-online/ocm-sdk-go v0.1.388/go.mod h1:/+VFIw1iW2H0jEkFH4GnbL/liWareyzsL0w7mDIudB4= +github.com/openshift-online/ocm-common v0.0.0-20240129111424-ff8c6c11d909 h1:WV67GNazQuGDaLX3kBbz0859NYPOQCsDCY5XUScF85M= +github.com/openshift-online/ocm-common v0.0.0-20240129111424-ff8c6c11d909/go.mod h1:7FaAb07S63RF4sFMLSLtQaJLvPdaRnhAT4dBLD8/5kM= +github.com/openshift-online/ocm-sdk-go v0.1.391 h1:BCC/sM1gVooxCL76MiPux2kng8MUbwM1IQr62hMPXeU= +github.com/openshift-online/ocm-sdk-go v0.1.391/go.mod h1:/+VFIw1iW2H0jEkFH4GnbL/liWareyzsL0w7mDIudB4= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= diff --git a/templates/cluster-template-rosa-machinepool.yaml b/templates/cluster-template-rosa-machinepool.yaml index ce5d04a728..4df420ab27 100644 --- a/templates/cluster-template-rosa-machinepool.yaml +++ b/templates/cluster-template-rosa-machinepool.yaml @@ -30,8 +30,6 @@ spec: rosaClusterName: ${CLUSTER_NAME:0:15} version: "${OPENSHIFT_VERSION}" region: "${AWS_REGION}" - accountID: "${AWS_ACCOUNT_ID}" - creatorARN: "${AWS_CREATOR_ARN}" machineCIDR: "10.0.0.0/16" rolesRef: ingressARN: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/${OPERATOR_ROLES_PREFIX}-openshift-ingress-operator-cloud-credentials" diff --git a/templates/cluster-template-rosa.yaml b/templates/cluster-template-rosa.yaml index 8fd60b9a5f..da2143030e 100644 --- a/templates/cluster-template-rosa.yaml +++ b/templates/cluster-template-rosa.yaml @@ -30,8 +30,6 @@ spec: rosaClusterName: ${CLUSTER_NAME:0:15} version: "${OPENSHIFT_VERSION}" region: "${AWS_REGION}" - accountID: "${AWS_ACCOUNT_ID}" - creatorARN: "${AWS_CREATOR_ARN}" machineCIDR: "10.0.0.0/16" rolesRef: ingressARN: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/${OPERATOR_ROLES_PREFIX}-openshift-ingress-operator-cloud-credentials"