Skip to content

Commit 1a34518

Browse files
rwhundleyrashmi43
andauthored
Reintroduce idauth Route for SAML (#1070)
* Update containers.go to add MASTER_PATH (#1009) If the `platform-auth-idp` ConfigMap does not have the `MASTER_PATH` field, the reconciler will look for an existing SAML connection in the database. If one exists, then the non-unified set of Routes is used for completing the OAuth flows. If no SAML has been configured, then the idauth unified Route is used instead. --------- Signed-off-by: rashmi_kh <[email protected]> Signed-off-by: Rob Hundley <[email protected]> Co-authored-by: Rob Hundley <[email protected]> * Fix testing Signed-off-by: Rob Hundley <[email protected]> * Correct MASTER_PATH field Signed-off-by: Rob Hundley <[email protected]> * Order migration earlier Signed-off-by: Rob Hundley <[email protected]> --------- Signed-off-by: rashmi_kh <[email protected]> Signed-off-by: Rob Hundley <[email protected]> Co-authored-by: Rashmi Khanna <[email protected]>
1 parent 1276d4a commit 1a34518

File tree

9 files changed

+250
-144
lines changed

9 files changed

+250
-144
lines changed

internal/controller/operator/authentication_controller.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
certmgr "github.com/IBM/ibm-iam-operator/internal/api/certmanager/v1"
2727
ctrlcommon "github.com/IBM/ibm-iam-operator/internal/controller/common"
28+
dbconn "github.com/IBM/ibm-iam-operator/internal/database/connectors"
2829
"github.com/IBM/ibm-iam-operator/internal/database/migration"
2930
"github.com/IBM/ibm-iam-operator/internal/version"
3031
routev1 "github.com/openshift/api/route/v1"
@@ -175,6 +176,8 @@ type AuthenticationReconciler struct {
175176
clusterType ctrlcommon.ClusterType
176177
dbSetupChan chan *migration.Result
177178
needsRollout bool
179+
GetPostgresDB func(client.Client, context.Context, ctrl.Request) (dbconn.DBConn, error)
180+
GetMongoDB func(client.Client, context.Context, ctrl.Request) (dbconn.DBConn, error)
178181
}
179182

180183
// Reconcile is part of the main kubernetes reconciliation loop which aims to
@@ -277,6 +280,23 @@ func (r *AuthenticationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
277280
return subreconciler.Evaluate(subResult, err)
278281
}
279282

283+
if subResult, err := r.ensureDatastoreSecretAndCM(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
284+
return subreconciler.Evaluate(subResult, err)
285+
}
286+
287+
// perform any migrations that may be needed before Deployments run
288+
if subResult, err := r.handleMigrations(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
289+
return subreconciler.Evaluate(subResult, err)
290+
}
291+
292+
if subResult, err := r.setMigrationCompleteStatus(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
293+
return subreconciler.Evaluate(subResult, err)
294+
}
295+
296+
if result, err := r.handleMongoDBCleanup(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(result, err) {
297+
return subreconciler.Evaluate(result, err)
298+
}
299+
280300
reqLogger.Info("Creating ibm-iam-operand-restricted serviceaccount")
281301
currentSA := &corev1.ServiceAccount{}
282302
err = r.createSA(instance, currentSA, &needToRequeue)
@@ -331,23 +351,6 @@ func (r *AuthenticationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
331351
// updates redirecturi annotations to serviceaccount
332352
r.handleServiceAccount(instance, &needToRequeue)
333353

334-
if subResult, err := r.ensureDatastoreSecretAndCM(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
335-
return subreconciler.Evaluate(subResult, err)
336-
}
337-
338-
// perform any migrations that may be needed before Deployments run
339-
if subResult, err := r.handleMigrations(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
340-
return subreconciler.Evaluate(subResult, err)
341-
}
342-
343-
if subResult, err := r.setMigrationCompleteStatus(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
344-
return subreconciler.Evaluate(subResult, err)
345-
}
346-
347-
if result, err := r.handleMongoDBCleanup(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(result, err) {
348-
return subreconciler.Evaluate(result, err)
349-
}
350-
351354
if subResult, err := r.handleDeployments(reconcileCtx, req); subreconciler.ShouldHaltOrRequeue(subResult, err) {
352355
return subreconciler.Evaluate(subResult, err)
353356
}
@@ -444,6 +447,12 @@ func (r *AuthenticationReconciler) SetupWithManager(mgr ctrl.Manager) error {
444447
return o.GetLabels()[ctrlcommon.ManagerVersionLabel] == version.Version
445448
})
446449

450+
r.GetPostgresDB = func(c client.Client, ctx context.Context, req ctrl.Request) (d dbconn.DBConn, err error) {
451+
return GetPostgresDB(c, ctx, req)
452+
}
453+
r.GetMongoDB = func(c client.Client, ctx context.Context, req ctrl.Request) (d dbconn.DBConn, err error) {
454+
return GetMongoDB(c, ctx, req)
455+
}
447456
authCtrl.Watches(&operatorv1alpha1.Authentication{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(bootstrappedPred))
448457
return authCtrl.Named("controller_authentication").
449458
Complete(r)

internal/controller/operator/configmap.go

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import (
3333
"text/template"
3434

3535
operatorv1alpha1 "github.com/IBM/ibm-iam-operator/api/operator/v1alpha1"
36-
ctrlcommon "github.com/IBM/ibm-iam-operator/internal/controller/common"
36+
"github.com/IBM/ibm-iam-operator/internal/controller/common"
37+
dbconn "github.com/IBM/ibm-iam-operator/internal/database/connectors"
3738
"github.com/opdev/subreconciler"
3839
routev1 "github.com/openshift/api/route/v1"
3940
batchv1 "k8s.io/api/batch/v1"
@@ -71,27 +72,27 @@ func (r *AuthenticationReconciler) handleConfigMaps(ctx context.Context, req ctr
7172
return subreconciler.RequeueWithDelay(defaultLowerWait)
7273
}
7374

74-
builders := []*ctrlcommon.SecondaryReconcilerBuilder[*corev1.ConfigMap]{
75-
ctrlcommon.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
75+
builders := []*common.SecondaryReconcilerBuilder[*corev1.ConfigMap]{
76+
common.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
7677
WithName("platform-auth-idp").
77-
WithGenerateFns(generateAuthIdpConfigMap(ibmCloudClusterInfoCM)).
78+
WithGenerateFns(r.generateAuthIdpConfigMap(ibmCloudClusterInfoCM)).
7879
WithModifyFns(updatePlatformAuthIDP).
7980
WithOnWriteFns(signalNeedRolloutFn[*corev1.ConfigMap](r)),
80-
ctrlcommon.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
81+
common.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
8182
WithName("registration-json").
8283
WithGenerateFns(generateRegistrationJsonConfigMap(ibmCloudClusterInfoCM)).
8384
WithModifyFns(updateRegistrationJSON).
8485
WithOnWriteFns(replaceOIDCClientRegistrationJob),
85-
ctrlcommon.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
86+
common.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
8687
WithName("oauth-client-map").
8788
WithGenerateFns(generateOAuthClientConfigMap(ibmCloudClusterInfoCM)).
8889
WithModifyFns(updateOAuthClientConfigMap),
89-
ctrlcommon.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
90+
common.NewSecondaryReconcilerBuilder[*corev1.ConfigMap]().
9091
WithName("registration-script").
9192
WithGenerateFns(generateRegistrationScriptConfigMap()),
9293
}
9394

94-
subRecs := []ctrlcommon.SecondaryReconciler{}
95+
subRecs := []common.SecondaryReconciler{}
9596
for i := range builders {
9697
subRecs = append(subRecs, builders[i].
9798
WithNamespace(authCR.Namespace).
@@ -108,7 +109,7 @@ func (r *AuthenticationReconciler) handleConfigMaps(ctx context.Context, req ctr
108109
errs = append(errs, err)
109110
}
110111

111-
return ctrlcommon.ReduceSubreconcilerResultsAndErrors(subresults, errs)
112+
return common.ReduceSubreconcilerResultsAndErrors(subresults, errs)
112113
}
113114

114115
// getConfigMapDataSHA1Sum calculates the SHA1 of the `.data` field.
@@ -130,7 +131,7 @@ func getConfigMapDataSHA1Sum(cm *corev1.ConfigMap) (sha string, err error) {
130131
// set.
131132
func getCNCFDomain(ctx context.Context, cl client.Client, authCR *operatorv1alpha1.Authentication) (domainName string, err error) {
132133
logger := logf.FromContext(ctx)
133-
cmName := ctrlcommon.GlobalConfigMapName
134+
cmName := common.GlobalConfigMapName
134135
cmNs := authCR.Namespace
135136
cm := &corev1.ConfigMap{}
136137
err = cl.Get(ctx, types.NamespacedName{Name: cmName, Namespace: cmNs}, cm)
@@ -151,12 +152,12 @@ func getCNCFDomain(ctx context.Context, cl client.Client, authCR *operatorv1alph
151152

152153
// handleIBMCloudClusterInfo creates the ibmcloud-cluster-info configmap if not created already
153154
func (r *AuthenticationReconciler) handleIBMCloudClusterInfo(ctx context.Context, authCR *operatorv1alpha1.Authentication, observed *corev1.ConfigMap) (result *ctrl.Result, err error) {
154-
reqLogger := logf.FromContext(ctx).WithValues("ConfigMap.Namespace", authCR.Namespace, "ConfigMap.Name", ctrlcommon.IBMCloudClusterInfoCMName)
155+
reqLogger := logf.FromContext(ctx).WithValues("ConfigMap.Namespace", authCR.Namespace, "ConfigMap.Name", common.IBMCloudClusterInfoCMName)
155156
generated := &corev1.ConfigMap{}
156157
if err = r.generateIBMCloudClusterInfoConfigMap(ctx, authCR, generated); err != nil {
157158
return subreconciler.RequeueWithError(err)
158159
}
159-
cmKey := types.NamespacedName{Name: ctrlcommon.IBMCloudClusterInfoCMName, Namespace: authCR.Namespace}
160+
cmKey := types.NamespacedName{Name: common.IBMCloudClusterInfoCMName, Namespace: authCR.Namespace}
160161
if err = r.Client.Get(ctx, cmKey, observed); k8sErrors.IsNotFound(err) {
161162
reqLogger.Info("Create new ConfigMap")
162163
if err = r.Client.Create(ctx, generated); err != nil {
@@ -171,7 +172,7 @@ func (r *AuthenticationReconciler) handleIBMCloudClusterInfo(ctx context.Context
171172
}
172173

173174
updated := false
174-
controllerKind := ctrlcommon.GetControllerKind(observed)
175+
controllerKind := common.GetControllerKind(observed)
175176
if controllerKind == "ManagementIngress" {
176177
reqLogger.Info("Configmap is already created by managementingress, IM installation may not proceed further until the configmap is removed")
177178
return subreconciler.RequeueWithDelay(defaultLowerWait)
@@ -220,7 +221,7 @@ func (r *AuthenticationReconciler) handleIBMCloudClusterInfo(ctx context.Context
220221
return subreconciler.RequeueWithDelay(defaultLowerWait)
221222
}
222223

223-
func replaceOIDCClientRegistrationJob(s ctrlcommon.SecondaryReconciler, ctx context.Context) (err error) {
224+
func replaceOIDCClientRegistrationJob(s common.SecondaryReconciler, ctx context.Context) (err error) {
224225
job := &batchv1.Job{
225226
ObjectMeta: metav1.ObjectMeta{
226227
Name: "oidc-client-registration",
@@ -233,7 +234,7 @@ func replaceOIDCClientRegistrationJob(s ctrlcommon.SecondaryReconciler, ctx cont
233234
return
234235
}
235236

236-
func updateRegistrationJSON(_ ctrlcommon.SecondaryReconciler, ctx context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
237+
func updateRegistrationJSON(_ common.SecondaryReconciler, ctx context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
237238
observedJSON := &registrationJSONData{}
238239
if err = json.Unmarshal([]byte(observed.Data["platform-oidc-registration.json"]), observedJSON); err != nil {
239240
return
@@ -258,7 +259,7 @@ func updateRegistrationJSON(_ ctrlcommon.SecondaryReconciler, ctx context.Contex
258259
return
259260
}
260261

261-
func updateOAuthClientConfigMap(_ ctrlcommon.SecondaryReconciler, _ context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
262+
func updateOAuthClientConfigMap(_ common.SecondaryReconciler, _ context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
262263
updateFns := []func(*corev1.ConfigMap, *corev1.ConfigMap) bool{
263264
updatesValuesWhen(not(observedKeyValueSetTo[*corev1.ConfigMap]("MASTER_IP", generated.Data["MASTER_IP"])),
264265
"MASTER_IP",
@@ -275,7 +276,7 @@ func updateOAuthClientConfigMap(_ ctrlcommon.SecondaryReconciler, _ context.Cont
275276
return
276277
}
277278

278-
func updatePlatformAuthIDP(_ ctrlcommon.SecondaryReconciler, _ context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
279+
func updatePlatformAuthIDP(_ common.SecondaryReconciler, _ context.Context, observed, generated *corev1.ConfigMap) (updated bool, err error) {
279280
updateFns := []func(*corev1.ConfigMap, *corev1.ConfigMap) bool{
280281
updatesAlways[*corev1.ConfigMap](
281282
"ROKS_URL",
@@ -342,6 +343,8 @@ func updatePlatformAuthIDP(_ ctrlcommon.SecondaryReconciler, _ context.Context,
342343
"LDAP_CTX_POOL_TIMEOUT",
343344
"LDAP_CTX_POOL_WAITTIME",
344345
"LDAP_CTX_POOL_PREFERREDSIZE"),
346+
updatesValuesWhen(not(observedKeySet[*corev1.ConfigMap]("MASTER_PATH")),
347+
"MASTER_PATH"),
345348
}
346349

347350
if v, ok := generated.Data["IS_OPENSHIFT_ENV"]; ok {
@@ -391,8 +394,8 @@ type registrationJSONData struct {
391394
RedirectURIs []string `json:"redirect_uris"`
392395
}
393396

394-
func generateAuthIdpConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.GenerateFn[*corev1.ConfigMap] {
395-
return func(s ctrlcommon.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
397+
func (r *AuthenticationReconciler) generateAuthIdpConfigMap(clusterInfo *corev1.ConfigMap) common.GenerateFn[*corev1.ConfigMap] {
398+
return func(s common.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
396399
reqLogger := logf.FromContext(ctx)
397400
authCR, ok := s.GetPrimary().(*operatorv1alpha1.Authentication)
398401
if !ok {
@@ -434,6 +437,14 @@ func generateAuthIdpConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.Generate
434437
}
435438
}
436439

440+
// Set the path for SAML connections
441+
var masterPath string
442+
if masterPath, err = r.getMasterPath(ctx, ctrl.Request{NamespacedName: common.GetObjectKey(s.GetPrimary())}); err != nil {
443+
reqLogger.Error(err, "Failed to determine whether a preexisting SAML exists")
444+
err = fmt.Errorf("could not set MASTER_PATH")
445+
return
446+
}
447+
437448
*generated = corev1.ConfigMap{
438449
ObjectMeta: metav1.ObjectMeta{
439450
Name: s.GetName(),
@@ -449,6 +460,7 @@ func generateAuthIdpConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.Generate
449460
"IDENTITY_PROVIDER_URL": "https://platform-identity-provider:4300",
450461
"IDENTITY_MGMT_URL": "https://platform-identity-management:4500",
451462
"MASTER_HOST": clusterInfo.Data["cluster_address"],
463+
"MASTER_PATH": masterPath,
452464
"NODE_ENV": "production",
453465
"ENABLE_JIT_EXTRA_ATTR": "false",
454466
"AUDIT_ENABLED_IDPROVIDER": "false",
@@ -536,8 +548,8 @@ func generateAuthIdpConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.Generate
536548
}
537549
}
538550

539-
func generateRegistrationJsonConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.GenerateFn[*corev1.ConfigMap] {
540-
return func(s ctrlcommon.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
551+
func generateRegistrationJsonConfigMap(clusterInfo *corev1.ConfigMap) common.GenerateFn[*corev1.ConfigMap] {
552+
return func(s common.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
541553
reqLogger := logf.FromContext(ctx)
542554
authCR, ok := s.GetPrimary().(*operatorv1alpha1.Authentication)
543555
if !ok {
@@ -602,8 +614,8 @@ func generateRegistrationJsonConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon
602614
}
603615
}
604616

605-
func generateRegistrationScriptConfigMap() ctrlcommon.GenerateFn[*corev1.ConfigMap] {
606-
return func(s ctrlcommon.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
617+
func generateRegistrationScriptConfigMap() common.GenerateFn[*corev1.ConfigMap] {
618+
return func(s common.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
607619
reqLogger := logf.FromContext(ctx)
608620

609621
*generated = corev1.ConfigMap{
@@ -626,8 +638,8 @@ func generateRegistrationScriptConfigMap() ctrlcommon.GenerateFn[*corev1.ConfigM
626638

627639
}
628640

629-
func generateOAuthClientConfigMap(clusterInfo *corev1.ConfigMap) ctrlcommon.GenerateFn[*corev1.ConfigMap] {
630-
return func(s ctrlcommon.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
641+
func generateOAuthClientConfigMap(clusterInfo *corev1.ConfigMap) common.GenerateFn[*corev1.ConfigMap] {
642+
return func(s common.SecondaryReconciler, ctx context.Context, generated *corev1.ConfigMap) (err error) {
631643
reqLogger := logf.FromContext(ctx)
632644
icpConsoleURL := clusterInfo.Data["cluster_address"]
633645
icpProxyURL := clusterInfo.Data["proxy_address"]
@@ -697,7 +709,7 @@ func (r *AuthenticationReconciler) getDomain(ctx context.Context, authCR *operat
697709
reqLogger := logf.FromContext(ctx)
698710

699711
commonLabel := map[string]string{"app": "im"}
700-
routeLabels := ctrlcommon.MergeMap(commonLabel, authCR.Spec.Labels)
712+
routeLabels := common.MergeMap(commonLabel, authCR.Spec.Labels)
701713

702714
imRoutes := &routev1.RouteList{}
703715
listOpts := []client.ListOption{
@@ -775,7 +787,7 @@ func (r *AuthenticationReconciler) generateCNCFClusterInfo(ctx context.Context,
775787

776788
*generated = corev1.ConfigMap{
777789
ObjectMeta: metav1.ObjectMeta{
778-
Name: ctrlcommon.IBMCloudClusterInfoCMName,
790+
Name: common.IBMCloudClusterInfoCMName,
779791
Namespace: authCR.Namespace,
780792
Labels: map[string]string{"app": "auth-idp"},
781793
},
@@ -838,7 +850,7 @@ func (r *AuthenticationReconciler) generateOCPClusterInfo(ctx context.Context, a
838850

839851
*generated = corev1.ConfigMap{
840852
ObjectMeta: metav1.ObjectMeta{
841-
Name: ctrlcommon.IBMCloudClusterInfoCMName,
853+
Name: common.IBMCloudClusterInfoCMName,
842854
Namespace: authCR.Namespace,
843855
Labels: map[string]string{"app": "auth-idp"},
844856
},
@@ -932,7 +944,7 @@ func (r *AuthenticationReconciler) generateIBMCloudClusterInfoConfigMap(ctx cont
932944
// isHostedOnIBMCloud checks the
933945
func isHostedOnIBMCloud(ctx context.Context, cl client.Client, namespace string) (isPublicCloud bool, err error) {
934946
reqLogger := logf.FromContext(ctx).V(1)
935-
cmName := ctrlcommon.IBMCloudClusterInfoCMName
947+
cmName := common.IBMCloudClusterInfoCMName
936948
cm := &corev1.ConfigMap{}
937949
if err = cl.Get(ctx, types.NamespacedName{Name: cmName, Namespace: namespace}, cm); err != nil {
938950
reqLogger.Info("Error getting ConfigMap", "ConfigMap.Name", cmName, "ConfigMap.Namespace", namespace, "msg", err.Error())
@@ -992,3 +1004,26 @@ func readROKSURL(ctx context.Context) (issuer string, err error) {
9921004

9931005
return issuer, nil
9941006
}
1007+
1008+
func (r *AuthenticationReconciler) getMasterPath(ctx context.Context, req ctrl.Request) (path string, err error) {
1009+
p, err := r.GetPostgresDB(r.Client, ctx, req)
1010+
if err != nil {
1011+
return
1012+
}
1013+
var has bool
1014+
if err = p.Connect(ctx); err != nil {
1015+
return
1016+
}
1017+
defer p.Disconnect(ctx)
1018+
1019+
samlChecker, ok := p.(dbconn.SAMLChecker)
1020+
if !ok {
1021+
return "", fmt.Errorf("DB unable to check for SAML connection")
1022+
}
1023+
if has, err = samlChecker.HasSAML(ctx); err != nil {
1024+
return
1025+
} else if has {
1026+
return "", err
1027+
}
1028+
return "/idauth", nil
1029+
}

0 commit comments

Comments
 (0)