Skip to content

Commit a428b51

Browse files
committed
Add OIDC id for Operator roles
1 parent 6640d97 commit a428b51

File tree

7 files changed

+157
-402
lines changed

7 files changed

+157
-402
lines changed

config/crd/bases/infrastructure.cluster.x-k8s.io_rosaroleconfigs.yaml

Lines changed: 6 additions & 291 deletions
Large diffs are not rendered by default.

controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import (
1515
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
1616
)
1717

18+
// log is for logging in this package.
19+
var rosacpLog = ctrl.Log.WithName("rosacontrolplane-resource")
20+
1821
// SetupWebhookWithManager will setup the webhooks for the ROSAControlPlane.
1922
func (r *ROSAControlPlane) SetupWebhookWithManager(mgr ctrl.Manager) error {
2023
w := new(rosaControlPlaneWebhook)
@@ -184,25 +187,54 @@ func (r *ROSAControlPlane) validateExternalAuthProviders() *field.Error {
184187
}
185188

186189
func (r *ROSAControlPlane) validateRosaRoleConfig() *field.Error {
187-
hasRosaRoleConfigRef := r.Spec.RosaRoleConfigRef != nil
188190
hasAnyDirectRoleFields := r.Spec.OIDCID != "" || r.Spec.InstallerRoleARN != "" || r.Spec.SupportRoleARN != "" || r.Spec.WorkerRoleARN != "" ||
189191
r.Spec.RolesRef.IngressARN != "" || r.Spec.RolesRef.ImageRegistryARN != "" || r.Spec.RolesRef.StorageARN != "" ||
190192
r.Spec.RolesRef.NetworkARN != "" || r.Spec.RolesRef.KubeCloudControllerARN != "" || r.Spec.RolesRef.NodePoolManagementARN != "" ||
191193
r.Spec.RolesRef.ControlPlaneOperatorARN != "" || r.Spec.RolesRef.KMSProviderARN != ""
192194

193-
hasAllDirectRoleFields := r.Spec.OIDCID != "" && r.Spec.InstallerRoleARN != "" && r.Spec.SupportRoleARN != "" && r.Spec.WorkerRoleARN != "" &&
194-
r.Spec.RolesRef.IngressARN != "" && r.Spec.RolesRef.ImageRegistryARN != "" && r.Spec.RolesRef.StorageARN != "" &&
195-
r.Spec.RolesRef.NetworkARN != "" && r.Spec.RolesRef.KubeCloudControllerARN != "" && r.Spec.RolesRef.NodePoolManagementARN != "" &&
196-
r.Spec.RolesRef.ControlPlaneOperatorARN != "" && r.Spec.RolesRef.KMSProviderARN != ""
197-
198-
if hasRosaRoleConfigRef && hasAnyDirectRoleFields {
199-
return field.Invalid(field.NewPath("spec.rosaRoleConfigRef"), r.Spec.RosaRoleConfigRef, "rosaRoleConfigRef and direct role fields (oidcID, installerRoleARN, supportRoleARN, workerRoleARN, rolesRef) are mutually exclusive")
195+
if r.Spec.RosaRoleConfigRef != nil {
196+
if hasAnyDirectRoleFields {
197+
rosacpLog.Info("rosaRoleConfigRef and direct role fields (oidcID, installerRoleARN, supportRoleARN, workerRoleARN, rolesRef) are mutually exclusive")
198+
}
199+
return nil
200200
}
201201

202-
if !hasRosaRoleConfigRef && !hasAllDirectRoleFields {
203-
return field.Invalid(field.NewPath("spec"), r.Spec, "either rosaRoleConfigRef or direct role fields (oidcID, installerRoleARN, supportRoleARN, workerRoleARN, rolesRef) must be specified")
202+
if r.Spec.OIDCID == "" {
203+
return field.Invalid(field.NewPath("spec.oidcID"), r.Spec.OIDCID, "must be specified")
204+
}
205+
if r.Spec.InstallerRoleARN == "" {
206+
return field.Invalid(field.NewPath("spec.installerRoleARN"), r.Spec.InstallerRoleARN, "must be specified")
207+
}
208+
if r.Spec.SupportRoleARN == "" {
209+
return field.Invalid(field.NewPath("spec.supportRoleARN"), r.Spec.SupportRoleARN, "must be specified")
210+
}
211+
if r.Spec.WorkerRoleARN == "" {
212+
return field.Invalid(field.NewPath("spec.workerRoleARN"), r.Spec.WorkerRoleARN, "must be specified")
213+
}
214+
if r.Spec.RolesRef.IngressARN == "" {
215+
return field.Invalid(field.NewPath("spec.rolesRef.ingressARN"), r.Spec.RolesRef.IngressARN, "must be specified")
216+
}
217+
if r.Spec.RolesRef.ImageRegistryARN == "" {
218+
return field.Invalid(field.NewPath("spec.rolesRef.imageRegistryARN"), r.Spec.RolesRef.ImageRegistryARN, "must be specified")
219+
}
220+
if r.Spec.RolesRef.StorageARN == "" {
221+
return field.Invalid(field.NewPath("spec.rolesRef.storageARN"), r.Spec.RolesRef.StorageARN, "must be specified")
222+
}
223+
if r.Spec.RolesRef.NetworkARN == "" {
224+
return field.Invalid(field.NewPath("spec.rolesRef.networkARN"), r.Spec.RolesRef.NetworkARN, "must be specified")
225+
}
226+
if r.Spec.RolesRef.KubeCloudControllerARN == "" {
227+
return field.Invalid(field.NewPath("spec.rolesRef.kubeCloudControllerARN"), r.Spec.RolesRef.KubeCloudControllerARN, "must be specified")
228+
}
229+
if r.Spec.RolesRef.NodePoolManagementARN == "" {
230+
return field.Invalid(field.NewPath("spec.rolesRef.nodePoolManagementARN"), r.Spec.RolesRef.NodePoolManagementARN, "must be specified")
231+
}
232+
if r.Spec.RolesRef.ControlPlaneOperatorARN == "" {
233+
return field.Invalid(field.NewPath("spec.rolesRef.controlPlaneOperatorARN"), r.Spec.RolesRef.ControlPlaneOperatorARN, "must be specified")
234+
}
235+
if r.Spec.RolesRef.KMSProviderARN == "" {
236+
return field.Invalid(field.NewPath("spec.rolesRef.kmsProviderARN"), r.Spec.RolesRef.KMSProviderARN, "must be specified")
204237
}
205-
206238
return nil
207239
}
208240

controlplane/rosa/controllers/rosacontrolplane_controller.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ func (r *ROSAControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Req
171171
}
172172

173173
log = log.WithValues("cluster", klog.KObj(cluster))
174-
175174
if isPaused, conditionChanged, err := paused.EnsurePausedCondition(ctx, r.Client, cluster, rosaControlPlane); err != nil || isPaused || conditionChanged {
176175
return ctrl.Result{}, err
177176
}
@@ -202,10 +201,10 @@ func (r *ROSAControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Req
202201
}
203202

204203
// Handle normal reconciliation loop.
205-
return r.reconcileNormal(ctx, rosaScope)
204+
return r.reconcileNormal(ctx, rosaScope, log)
206205
}
207206

208-
func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaScope *scope.ROSAControlPlaneScope) (res ctrl.Result, reterr error) {
207+
func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaScope *scope.ROSAControlPlaneScope, log *logger.Logger) (res ctrl.Result, reterr error) {
209208
rosaScope.Info("Reconciling ROSAControlPlane")
210209

211210
if controllerutil.AddFinalizer(rosaScope.ControlPlane, ROSAControlPlaneFinalizer) {
@@ -245,9 +244,11 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc
245244
rosacontrolplanev1.ROSARoleConfigNotFoundReason,
246245
clusterv1.ConditionSeverityError,
247246
"RosaRoleConfig %s/%s not found", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name)
248-
return ctrl.Result{}, fmt.Errorf("RosaRoleConfig %s/%s not found: %w", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name, err)
247+
log.Error(err, fmt.Sprintf("RosaRoleConfig %s/%s not found: %w", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name, err))
248+
return ctrl.Result{RequeueAfter: time.Second * 60}, nil
249249
}
250-
return ctrl.Result{}, fmt.Errorf("failed to get RosaRoleConfig %s/%s: %w", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name, err)
250+
log.Error(err, fmt.Sprintf("failed to get RosaRoleConfig %s/%s: %w", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name, err))
251+
return ctrl.Result{RequeueAfter: time.Second * 60}, nil
251252
}
252253

253254
// Check if RosaRoleConfig is ready
@@ -257,7 +258,9 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc
257258
rosacontrolplanev1.ROSARoleConfigNotReadyReason,
258259
clusterv1.ConditionSeverityWarning,
259260
"RosaRoleConfig %s/%s is not ready", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name)
260-
return ctrl.Result{}, fmt.Errorf("RosaRoleConfig %s/%s is not ready", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name)
261+
log.Error(err, fmt.Sprintf("RosaRoleConfig %s/%s is not ready", rosaScope.ControlPlane.Namespace, rosaScope.ControlPlane.Spec.RosaRoleConfigRef.Name))
262+
263+
return ctrl.Result{RequeueAfter: time.Second * 60}, nil
261264
}
262265

263266
conditions.MarkTrue(rosaScope.ControlPlane, rosacontrolplanev1.ROSARoleConfigReadyCondition)
@@ -267,7 +270,6 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc
267270
rosaRoleConfig.Status.AccountRolesRef.SupportRoleARN = rosaScope.ControlPlane.Spec.SupportRoleARN
268271
rosaRoleConfig.Status.AccountRolesRef.WorkerRoleARN = rosaScope.ControlPlane.Spec.WorkerRoleARN
269272
rosaRoleConfig.Status.OperatorRolesRef = rosaScope.ControlPlane.Spec.RolesRef
270-
rosaRoleConfig.Spec.OIDCConfig.ExternalAuthProviders = rosaScope.ControlPlane.Spec.ExternalAuthProviders
271273
}
272274

273275
validationMessage, err := validateControlPlaneSpec(ocmClient, rosaScope)

exp/api/v1beta2/rosaroleconfig_types.go

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,9 @@ import (
3232
type ROSARoleConfigSpec struct {
3333
AccountRoleConfig AccountRoleConfig `json:"accountRoleConfig"`
3434
OperatorRoleConfig OperatorRoleConfig `json:"operatorRoleConfig"`
35-
OIDCConfig OIDCConfig `json:"oidcConfig"`
3635
IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"`
3736
Region string `json:"region,omitempty"`
3837
// CredentialsSecretRef references a secret with necessary credentials to connect to the OCM API.
39-
// The secret should contain the following data keys:
40-
// - ocmToken: eyJhbGciOiJIUzI1NiIsI....
41-
// - ocmApiUrl: Optional, defaults to 'https://api.openshift.com'
4238
// +optional
4339
CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"`
4440
}
@@ -60,7 +56,7 @@ type ROSARoleConfig struct {
6056
// AccountRoleConfig defines account-wide IAM roles before creating your ROSA cluster.
6157
type AccountRoleConfig struct {
6258
// User-defined prefix for all generated AWS resources
63-
// +kubebuilder:validation:MaxLength:=40
59+
// +kubebuilder:validation:MaxLength:=4
6460
// +kubebuilder:validation:Required
6561
// +immutable
6662
Prefix string `json:"prefix"`
@@ -99,6 +95,10 @@ type OperatorRoleConfig struct {
9995
// +optional
10096
// +immutable
10197
SharedVPCConfig SharedVPCConfig `json:"sharedVPCConfig,omitempty"`
98+
// OIDCID is the ID of the OIDC config that will be used to create the operator roles.
99+
// +optional
100+
// +immutable
101+
OIDCID string `json:"oidcID,omitempty"`
102102
}
103103

104104
// SharedVPCConfig is used to set up shared VPC.
@@ -109,34 +109,6 @@ type SharedVPCConfig struct {
109109
VPCEndpointRoleARN string `json:"vpcEndpointRoleArn,omitempty"`
110110
}
111111

112-
// OIDCConfig creates OIDC config in a S3 bucket for the client AWS account and populates it to be compliant with OIDC protocol.
113-
// It also creates a Secret in Secrets Manager containing the private key.
114-
type OIDCConfig struct {
115-
// ManagedOIDC indicates whether it is a Red Hat managed or unmanaged (Customer hosted) OIDC Configuration. Default is true.
116-
// +kubebuilder:default=true
117-
// +immutable
118-
ManagedOIDC bool `json:"managedOIDC"`
119-
// ExternalAuthProviders are external OIDC identity providers that can issue tokens for this cluster.
120-
// Can only be set if "enableExternalAuthProviders" is set to "True".
121-
//
122-
// At most one provider can be configured.
123-
//
124-
// +listType=map
125-
// +listMapKey=name
126-
// +kubebuilder:validation:MaxItems=1
127-
// +immutable
128-
ExternalAuthProviders []rosacontrolplanev1.ExternalAuthProvider `json:"externalAuthProviders,omitempty"`
129-
// IdentityRef is the AWS identity reference for the OIDC config.
130-
// +immutable
131-
IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"`
132-
// Region is the AWS region for the OIDC config.
133-
// +immutable
134-
Region string `json:"region,omitempty"`
135-
// Prefix is the prefix for the OIDC config.
136-
// +immutable
137-
Prefix string `json:"prefix"`
138-
}
139-
140112
// ROSARoleConfigStatus defines the observed state of ROSARoleConfig
141113
type ROSARoleConfigStatus struct {
142114
// ID of created OIDC config

exp/api/v1beta2/zz_generated.deepcopy.go

Lines changed: 0 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)