Skip to content

Commit 1890a46

Browse files
authored
Merge pull request #29 from coroot/sso_oidc
add OIDC SSO support
2 parents 59ebc21 + ae9a796 commit 1890a46

4 files changed

Lines changed: 110 additions & 4 deletions

File tree

api/v1/config.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ type CorootCloudRCASpec struct {
2121

2222
type SSOSpec struct {
2323
Enabled bool `json:"enabled,omitempty"`
24+
// Provider is set automatically based on which configuration section (saml or oidc) is defined.
25+
Provider string `json:"provider,omitempty"`
2426
// Default role for authenticated users (Admin, Editor, Viewer, or a custom role).
2527
DefaultRole string `json:"defaultRole,omitempty"`
26-
// SAML configuration.
28+
// SAML configuration. Define this section to use SAML SSO.
2729
SAML *SSOSAMLSpec `json:"saml,omitempty"`
30+
// OIDC configuration. Define this section to use OIDC SSO.
31+
OIDC *SSOOIDCSpec `json:"oidc,omitempty"`
2832
}
2933

3034
type SSOSAMLSpec struct {
@@ -34,6 +38,18 @@ type SSOSAMLSpec struct {
3438
MetadataSecret *corev1.SecretKeySelector `json:"metadataSecret,omitempty"`
3539
}
3640

41+
type SSOOIDCSpec struct {
42+
// OIDC provider issuer URL (e.g., https://accounts.google.com).
43+
// +kubebuilder:validation:Pattern="^https?://.+$"
44+
IssuerURL string `json:"issuerURL,omitempty"`
45+
// OAuth client ID.
46+
ClientID string `json:"clientID,omitempty"`
47+
// OAuth client secret.
48+
ClientSecret string `json:"clientSecret,omitempty"`
49+
// Secret containing the client secret.
50+
ClientSecretSecret *corev1.SecretKeySelector `json:"clientSecretSecret,omitempty"`
51+
}
52+
3753
type AISpec struct {
3854
// AI model provider (anthropic, openai, or openai_compatible).
3955
// +kubebuilder:validation:Enum=anthropic;openai;openai_compatible

api/v1/zz_generated.deepcopy.go

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

config/crd/coroot.com_coroots.yaml

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8118,8 +8118,52 @@ spec:
81188118
type: string
81198119
enabled:
81208120
type: boolean
8121+
oidc:
8122+
description: OIDC configuration. Define this section to use OIDC
8123+
SSO.
8124+
properties:
8125+
clientID:
8126+
description: OAuth client ID.
8127+
type: string
8128+
clientSecret:
8129+
description: OAuth client secret.
8130+
type: string
8131+
clientSecretSecret:
8132+
description: Secret containing the client secret.
8133+
properties:
8134+
key:
8135+
description: The key of the secret to select from. Must
8136+
be a valid secret key.
8137+
type: string
8138+
name:
8139+
default: ""
8140+
description: |-
8141+
Name of the referent.
8142+
This field is effectively required, but due to backwards compatibility is
8143+
allowed to be empty. Instances of this type with an empty value here are
8144+
almost certainly wrong.
8145+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
8146+
type: string
8147+
optional:
8148+
description: Specify whether the Secret or its key must
8149+
be defined
8150+
type: boolean
8151+
required:
8152+
- key
8153+
type: object
8154+
x-kubernetes-map-type: atomic
8155+
issuerURL:
8156+
description: OIDC provider issuer URL (e.g., https://accounts.google.com).
8157+
pattern: ^https?://.+$
8158+
type: string
8159+
type: object
8160+
provider:
8161+
description: Provider is set automatically based on which configuration
8162+
section (saml or oidc) is defined.
8163+
type: string
81218164
saml:
8122-
description: SAML configuration.
8165+
description: SAML configuration. Define this section to use SAML
8166+
SSO.
81238167
properties:
81248168
metadata:
81258169
description: Identity Provider Metadata XML.

controller/coroot.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,23 @@ func (r *CorootReconciler) validateCoroot(ctx context.Context, cr *corootv1.Coro
196196
}
197197
}
198198
if sso := cr.Spec.SSO; sso != nil && sso.Enabled {
199-
if saml := sso.SAML; saml != nil {
199+
valid := false
200+
if oidc := sso.OIDC; oidc != nil {
201+
if oidc.ClientSecretSecret != nil {
202+
if _, err = r.GetSecret(ctx, cr, oidc.ClientSecretSecret); err != nil {
203+
logErr("Failed to get OIDC Client Secret: %s", err.Error())
204+
} else {
205+
oidc.ClientSecret = configEnvs.Add(oidc.ClientSecretSecret)
206+
}
207+
oidc.ClientSecretSecret = nil
208+
}
209+
if oidc.IssuerURL != "" && oidc.ClientID != "" && oidc.ClientSecret != "" {
210+
sso.Provider = "oidc"
211+
valid = true
212+
} else {
213+
logErr("OIDC SSO requires issuerURL, clientID, and clientSecret")
214+
}
215+
} else if saml := sso.SAML; saml != nil {
200216
metadata := saml.Metadata
201217
if saml.MetadataSecret != nil {
202218
if metadata, err = r.GetSecret(ctx, cr, saml.MetadataSecret); err != nil {
@@ -210,10 +226,15 @@ func (r *CorootReconciler) validateCoroot(ctx context.Context, cr *corootv1.Coro
210226
if err = ValidateSamlIdentityProviderMetadata(metadata); err != nil {
211227
logErr("Invalid SAML Identity Provider Metadata: %s", err.Error())
212228
saml.Metadata = ""
229+
} else {
230+
sso.Provider = "saml"
231+
valid = true
213232
}
214233
}
234+
} else {
235+
logErr("SSO is enabled but neither saml nor oidc configuration is provided")
215236
}
216-
if sso.SAML == nil || sso.SAML.Metadata == "" {
237+
if !valid {
217238
sso.Enabled = false
218239
}
219240
}

0 commit comments

Comments
 (0)