Skip to content

Commit

Permalink
feat(dex): create connector and client to sql along with the CRDs
Browse files Browse the repository at this point in the history
  • Loading branch information
kengou committed Jan 9, 2025
1 parent 1e045d3 commit cd6b3e5
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 0 deletions.
5 changes: 5 additions & 0 deletions cmd/greenhouse/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func startOrganizationReconciler(name string, mgr ctrl.Manager) error {
}
return (&organizationcontrollers.OrganizationReconciler{
Namespace: namespace,
PGDB: pgDB,
PGHost: pgHost,
PGPort: pgPort,
PGUser: pgUser,
PGPasswd: pgPasswd,
}).SetupWithManager(name, mgr)
}

Expand Down
9 changes: 9 additions & 0 deletions cmd/greenhouse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ var (
remoteClusterBearerTokenValidity,
renewRemoteClusterBearerTokenAfter time.Duration
kubeClientOpts clientutil.RuntimeOptions
// DB connection parameters
pgDB, pgHost, pgUser, pgPasswd string
pgPort uint16
)

func init() {
Expand Down Expand Up @@ -91,6 +94,12 @@ func main() {
flag.StringVar(&common.DNSDomain, "dns-domain", "",
"The DNS domain to use for the Greenhouse central cluster")

flag.StringVar(&pgDB, "database", os.Getenv("DB_NAME"), "Database name")
flag.StringVar(&pgHost, "dbHost", os.Getenv("DB_HOST"), "Database host")
flag.Uint16Var(&pgPort, "dbPort", 5432, "Database port")
flag.StringVar(&pgUser, "dbUser", os.Getenv("DB_USER"), "Database user")
flag.StringVar(&pgPasswd, "dbPassword", os.Getenv("DB_PASSWORD"), "Database password")

opts := zap.Options{
Development: true,
TimeEncoder: zapcore.RFC3339TimeEncoder,
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ require (
cloud.google.com/go/auth v0.9.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
dario.cat/mergo v1.0.1 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Microsoft/hcsshim v0.12.6 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
Expand All @@ -64,11 +65,13 @@ require (
github.com/creack/pty v1.1.23 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
Expand Down
64 changes: 64 additions & 0 deletions pkg/controllers/organization/dex.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"

"github.com/dexidp/dex/connector/oidc"
"github.com/dexidp/dex/storage"
"github.com/pkg/errors"
"golang.org/x/text/cases"
"golang.org/x/text/language"
Expand Down Expand Up @@ -88,6 +89,33 @@ func (r *OrganizationReconciler) reconcileDexConnector(ctx context.Context, org
log.FromContext(ctx).Info("updated dex connector", "namespace", dexConnector.Namespace, "name", dexConnector.GetName())
r.recorder.Eventf(org, corev1.EventTypeNormal, "UpdatedDexConnector", "Updated dex connector %s/%s", dexConnector.Namespace, dexConnector.GetName())
}

// Create the connectors also in SQL storage
var oidcConnector storage.Connector
if oidcConnector, err = r.sqlDexStorage.GetConnector(org.Name); err != nil {
if err = r.sqlDexStorage.CreateConnector(ctx, storage.Connector{
ID: org.Name,
Type: dexConnectorTypeGreenhouse,
Name: cases.Title(language.English).String(org.Name),
Config: configByte,
}); err != nil {
return err
}
log.FromContext(ctx).Info("created dex connector in SQL storage", "name", org.Name)
r.recorder.Eventf(org, corev1.EventTypeNormal, "CreatedDexConnectorSQL", "Created dex connector in SQL storage %s", org.Name)
}
if err = r.sqlDexStorage.UpdateConnector(oidcConnector.ID, func(c storage.Connector) (storage.Connector, error) {
c.ID = org.Name
c.Type = dexConnectorTypeGreenhouse
c.Name = cases.Title(language.English).String(org.Name)
c.Config = configByte
return c, nil
}); err != nil {
return err
}
log.FromContext(ctx).Info("updated dex connector in SQL storage", "name", org.Name)
r.recorder.Eventf(org, corev1.EventTypeNormal, "UpdatedDexConnectorSQL", "Updated dex connector in SQL storage %s", org.Name)

return nil
}

Expand Down Expand Up @@ -118,6 +146,42 @@ func (r *OrganizationReconciler) discoverOIDCRedirectURL(ctx context.Context, or
}

func (r *OrganizationReconciler) reconcileOAuth2Client(ctx context.Context, org *greenhousesapv1alpha1.Organization) error {
var oAuthClient storage.Client
var err error
if oAuthClient, err = r.sqlDexStorage.GetClient(org.Name); err != nil {
if err = r.sqlDexStorage.CreateClient(ctx, storage.Client{
Public: true,
ID: org.Name,
Name: org.Name,
RedirectURIs: []string{
"https://dashboard." + common.DNSDomain,
fmt.Sprintf("https://%s.dashboard.%s", org.Name, common.DNSDomain),
},
}); err != nil {
return err
}
log.FromContext(ctx).Info("created oauth2client", "name", org.Name)
r.recorder.Eventf(org, corev1.EventTypeNormal, "CreatedOAuth2Client", "Created oauth2client %s", org.Name)
return nil
}

if err = r.sqlDexStorage.UpdateClient(oAuthClient.Name, func(authClient storage.Client) (storage.Client, error) {
authClient.Public = true
authClient.ID = org.Name
authClient.Name = org.Name
for _, requiredRedirectURL := range []string{
"https://dashboard." + common.DNSDomain,
fmt.Sprintf("https://%s.dashboard.%s", org.Name, common.DNSDomain),
} {
authClient.RedirectURIs = util.AppendStringToSliceIfNotContains(requiredRedirectURL, authClient.RedirectURIs)
}
return authClient, nil
}); err != nil {
return err
}
log.FromContext(ctx).Info("updated oauth2client", "name", org.Name)
r.recorder.Eventf(org, corev1.EventTypeNormal, "UpdatedOAuth2Client", "Updated oauth2client %s", org.Name)

var oAuth2Client = new(dexapi.OAuth2Client)
oAuth2Client.ObjectMeta.Name = encodedOAuth2ClientName(org.Name)
oAuth2Client.ObjectMeta.Namespace = r.Namespace
Expand Down
23 changes: 23 additions & 0 deletions pkg/controllers/organization/organization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ package organization

import (
"context"
"log/slog"
"os"

"github.com/cloudoperators/greenhouse/pkg/idproxy"
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/sql"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
Expand Down Expand Up @@ -45,6 +50,10 @@ type OrganizationReconciler struct {
client.Client
recorder record.EventRecorder
Namespace string
// Database related configuration
PGDB, PGHost, PGUser, PGPasswd string
PGPort uint16
sqlDexStorage storage.Storage
}

//+kubebuilder:rbac:groups=greenhouse.sap,resources=organizations,verbs=get;list;watch;create;update;patch;delete
Expand All @@ -64,6 +73,20 @@ type OrganizationReconciler struct {
func (r *OrganizationReconciler) SetupWithManager(name string, mgr ctrl.Manager) error {
r.Client = mgr.GetClient()
r.recorder = mgr.GetEventRecorderFor(name)

var err error
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
r.sqlDexStorage, err = idproxy.NewPostgresStorage(sql.SSL{Mode: "disable"}, sql.NetworkDB{
Host: r.PGHost,
Port: r.PGPort,
User: r.PGUser,
Password: r.PGPasswd,
Database: r.PGDB,
}, logger.With("component", "storage"))
if err != nil {
return err
}

return ctrl.NewControllerManagedBy(mgr).
Named(name).
For(&greenhousesapv1alpha1.Organization{}).
Expand Down
26 changes: 26 additions & 0 deletions pkg/idproxy/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,35 @@ import (
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/kubernetes"
"github.com/dexidp/dex/storage/kubernetes/k8sapi"
"github.com/dexidp/dex/storage/sql"
"github.com/ghodss/yaml"
)

// NewPostgresStorage creates a new Postgres storage.
func NewPostgresStorage(sslConfig sql.SSL, dbConfig sql.NetworkDB, logger *slog.Logger) (storage.Storage, error) {
sqlStorage, err := postgresStorage(sslConfig, sql.NetworkDB{
Host: dbConfig.Host,
Port: dbConfig.Port,
User: dbConfig.User,
Password: dbConfig.Password,
Database: dbConfig.Database,
}, logger.With("component", "storage"))
if err != nil {
return nil, err
}
return sqlStorage, nil
}

// postgresStorage creates a new Postgres storage.
func postgresStorage(sslConfig sql.SSL, dbConfig sql.NetworkDB, logger *slog.Logger) (storage.Storage, error) {
var storageConfig = sql.Postgres{
SSL: sslConfig,
NetworkDB: dbConfig,
}
return storageConfig.Open(logger)
}

// NewKubernetesStorage creates a new Kubernetes storage.
func NewKubernetesStorage(kubeconfig, kubecontext, namespace string, logger *slog.Logger) (storage.Storage, error) {
var storageConfig = kubernetes.Config{InCluster: true}
if kubeconfig != "" {
Expand Down

0 comments on commit cd6b3e5

Please sign in to comment.