Draft: Crossplane / Keycloak study

This MR looks into managing Keycloak resources using Crossplane with the crossplane keycloak-provider and function-keycloak-builtin-objects.

  • keycloak-provider is used to create/take into management resources
  • function-keycloak-builtin-objects is needed to get the builtin keycloak objects in k8s so we can reference them as external resources for objects that need a mapping with them (infra-admins-view-users-roles mapping for example).

Units Added

  • crossplane Helmrelease to install Crossplane

  • crossplane-init - Installs keycloak crds and keycloak-provider

  • get-keycloak-resources: KubeJob that gets existing keycloak resources id's . (Client id's , Group id's etc..). Motivation: crossplane-resources needs to refer to externally created resources that it can take into management via the resource id. Input: keycloak-initial-admin secret for the script to authenticate Output: keycloak-uuid-resources

  • crossplane-resources:

    • Installs extra functions and creates compositions to pull already created (default) keycloak resources into k8s objects
    • configures the provider to point to the keycloak instance
    • creates keycloak-resources (Realm, Clients, Mappings, Groups, etc...) OR Imports them based on keycloak-uuid-resources values
  • crossplane-external-secrets Moves keycloak-initial-admin , keycloak-internal-tls from keycloak ns to crossplane-system and sylva-system

Units removed

  • keycloak-add-client-scope
  • keycloak-add-realm-role
  • keycloak-legacy-operator
  • keycloak-resources
  • some related to gitea that i did not get to it yet.

Other changes

  • created a new secret store for crossplane and pointed everything under keycloak-oidc-external-secrets to the new secret store

Keycloak resources structure overview

|-- keycloak-resources
|   |-- clients
|   |   |-- flux
|   |   |   |-- flux-client-scope.yaml
|   |   |   |-- flux-role-mappings.yaml
|   |   |   `-- flux-webui-client.yaml
|   |   |-- grafana
|   |   |   |-- grafana-client-scope.yaml
|   |   |   |-- grafana-client.yaml
|   |   |   |-- grafana-role-mappings.yaml
|   |   |   `-- kustomization.yaml
|   |   |-- harbor
|   |   |   |-- harbor-client-scope.yaml
|   |   |   |-- harbor-client.yaml
|   |   |   |-- harbor-role-mappings.yaml
|   |   |   `-- kustomization.yaml
|   |   |-- neuvector
|   |   |   |-- kustomization.yaml
|   |   |   |-- neuvector-client-scope.yaml
|   |   |   |-- neuvector-client.yaml
|   |   |   `-- neuvector-role-mappings.yaml
|   |   |-- rancher
|   |   |   |-- rancher-client-scope.yaml
|   |   |   |-- rancher-client.yaml
|   |   |   `-- rancher-role-mappings.yaml
|   |   `-- vault
|   |       |-- vault-client-scope.yaml
|   |       |-- vault-client.yaml
|   |       `-- vault-role-mappings.yaml
|   |-- groups
|   |   |-- infra-admins.yaml
|   |   |-- infra-base-users.yaml
|   |   |-- infra-restricted-admins.yaml
|   |   `-- infra-standard-users.yaml
|   |-- realm
|   |   |-- realm.yaml
|   |   |-- roles
|   |   |   |-- grafana-admin-role.yaml
|   |   |   `-- view-users-role-mapping.yaml
|   |   `-- scopes
|   |       `-- groups-client-scope.yaml
|   `-- sylva-user
|       |-- sylva-group-membership.yaml
|       |-- sylva-user-password.yaml
|       `-- sylva-user.yaml

Vs Old Keycloak operator:

|-- keycloak-resources
|   |-- components
|   |   |-- grafana
|   |   |   |-- grafana-client.yaml
|   |   |   `-- kustomization.yaml
|   |   |-- harbor
|   |   |   |-- harbor-client.yaml
|   |   |   `-- kustomization.yaml
|   |   `-- neuvector
|   |       |-- kustomization.yaml
|   |       `-- neuvector-client.yaml
|   |-- flux-webui-client.yaml
|   |-- keycloak-realm.yaml
|   |-- keycloak-user.yaml
|   |-- kustomization.yaml
|   |-- rancher-client.yaml
|   `-- vault-client.yaml

Crossplane-system overview

NAME                                                              READY   STATUS    RESTARTS      AGE
crossplane-76bb844bf8-mfwgk                                       1/1     Running   0             4m27s
crossplane-rbac-manager-74f65f498c-rjzkh                          1/1     Running   0             4m27s
function-auto-ready-ad9454a37aa7-dcfbd7df5-sc5kf                  1/1     Running   0             3m52s
function-extra-resources-fa66e8ab9f79-7476d98f54-bwcqr            1/1     Running   0             3m51s
function-keycloak-builtin-objects-07d5cc1b7eda-54bd878d6b-wkttr   1/1     Running   0             3m51s
provider-keycloak-c9534585a3b3-7978d6bb79-ln946                   1/1     Running   1 (86s ago)   4m

get keycloak resources initial install:

If only the master realm exists (on a fresh install), then the script does nothing

root@otc-caas:/opt/sylva-core/kustomize-units/keycloak-oidc-external-secrets (crossplane)# kubectl logs -f get-keycloak-resource-uuids-zmntf -n sylva-system
INFO: get_initial_password: Getting Keycloak initial password...
INFO: get_access_token: Get Keycloak access token...
INFO: <module>: This is a fresh install with only the master realm.

If ran again, the script will create the configmap with the keycloak resource uuids.

INFO: get_initial_password: Getting Keycloak initial password...
INFO: get_access_token: Get Keycloak access token...
INFO: <module>: This Keycloak instance has additional realms, proceeding to get resource UUIDS
INFO: get_client_and_mappers_uuids: Getting KeycloakClients uuids...
INFO: get_groups_ids: Getting KeycloakGroups uuids...
INFO: get_user_ids: Getting KeycloakUsers uuids...
INFO: get_realm_roles: Getting KeycloakRealmRoles uuids...
INFO: get_client_scopes: Getting KeycloakClientScopes uuids...
INFO: create_k8s_configmap: Creating configmap...
INFO: create_k8s_configmap: Configmap keycloak-uuid-resources already exists, will update it...
INFO: create_k8s_configmap: ConfigMap updated successfully.

Configmap example:

root@otc-caas:/opt/sylva-core (crossplane)# kubectl get configmap keycloak-uuid-resources -n sylva-system -o yaml
apiVersion: v1
data:
  CLIENT_FLUX_WEBUI: 40e7e3be-ada8-4e10-9872-aa4361b251d8
  CLIENT_GRAFANA: f53f8727-059e-484d-903d-0ef61ad35f60
  CLIENT_HARBOR: 2ef39926-8663-4389-9baf-e3ee51447fff
  .....

k8s resources

root@otc-caas:/opt/sylva-core (crossplane)# kubectl get realms.realm.keycloak.crossplane.io
NAME          SYNCED   READY   EXTERNAL-NAME   AGE
sylva-realm   True     True    sylva           6m44s


root@otc-caas:/opt/sylva-core (crossplane)# kubectl get clients.openidclient.keycloak.crossplane.io
NAME                                   SYNCED   READY   EXTERNAL-NAME                          AGE
builtin-sylva-account                  True     True    d438c2ce-f6f1-470d-ad00-98fa88ea941d   7m48s
builtin-sylva-account-console          True     True    2ad25197-e08d-4f92-bdc6-27d8d662f32a   7m48s
builtin-sylva-admin-cli                True     True    61b92ad9-828c-4b9b-9a4a-c8ac6a5099ea   7m48s
builtin-sylva-broker                   True     True    e92417f1-462a-4cda-b09f-5194e9e12774   7m47s
builtin-sylva-realm-management         True     True    643dacad-9d47-44f5-bfc2-2f8be4356df4   7m48s
builtin-sylva-security-admin-console   True     True    75b77161-fb0a-4f14-9ddc-17c824350319   7m47s
flux-webui                             True     True    40e7e3be-ada8-4e10-9872-aa4361b251d8   9m2s
grafana                                True     True    f53f8727-059e-484d-903d-0ef61ad35f60   9m2s
harbor                                 True     True    2ef39926-8663-4389-9baf-e3ee51447fff   9m2s
rancher                                True     True    fd760e4e-eb18-4ca9-8aeb-3d1632277e75   9m2s
vault                                  True     True    8e7062a2-c29c-455e-992b-07cff2a2098a   9m2s

Gets us all resources from the provider

kubectl get providerconfigusages.keycloak.crossplane.io

For a complete crd list

kubectl get crds | grep keycloak.crossplane

Related to #1231 (closed)

Edited by Mihai Zaharia

Merge request reports

Loading