diff --git a/k8s/infra/auth/keycloak-realms/homelab/builtin-objects.yaml b/k8s/infra/auth/keycloak-realms/homelab/builtin-objects.yaml index cdcae0d..92bfc18 100644 --- a/k8s/infra/auth/keycloak-realms/homelab/builtin-objects.yaml +++ b/k8s/infra/auth/keycloak-realms/homelab/builtin-objects.yaml @@ -6,6 +6,8 @@ spec: providerConfigName: default providerSecretName: keycloak-credentials realm: homelab + builtinAuthenticationFlows: + - browser builtinClients: - account - account-console diff --git a/k8s/infra/crossplane-crds/config/keycloak/composition.yaml b/k8s/infra/crossplane-crds/compositions/keycloak-builtin-objects.yaml similarity index 100% rename from k8s/infra/crossplane-crds/config/keycloak/composition.yaml rename to k8s/infra/crossplane-crds/compositions/keycloak-builtin-objects.yaml diff --git a/k8s/infra/crossplane-crds/compositions/keycloak-oidc-client.yaml b/k8s/infra/crossplane-crds/compositions/keycloak-oidc-client.yaml new file mode 100644 index 0000000..0f1d591 --- /dev/null +++ b/k8s/infra/crossplane-crds/compositions/keycloak-oidc-client.yaml @@ -0,0 +1,189 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: keycloak-oidc-client +spec: + compositeTypeRef: + apiVersion: oidc.homelab.olav.ninja/v1alpha1 + kind: XOidcClient + mode: Pipeline + pipeline: + - step: create-client + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + apiVersion: openidclient.keycloak.crossplane.io/v1alpha1 + kind: Client + metadata: + annotations: + gotemplating.fn.crossplane.io/composition-resource-name: {{ .observed.composite.resource.metadata.name }} + spec: + forProvider: + name: {{ .observed.composite.resource.spec.displayName }} + accessType: {{ .observed.composite.resource.spec.type }} + clientId: {{ .observed.composite.resource.spec.clientId }} + {{ with .observed.composite.resource.spec.clientSecretSecretRef }} + clientSecretSecretRef: {{ toYaml . | nindent 6 }} + {{ end }} + description: {{ .observed.composite.resource.spec.description }} + {{ with .observed.composite.resource.spec.baseUrl }} + baseUrl: {{ . }} + {{ end }} + {{ with .observed.composite.resource.spec.redirectUris }} + validRedirectUris: {{ toYaml . | nindent 6 }} + {{ end }} + {{ with .observed.composite.resource.spec.postLogoutRedirectUris }} + validPostLogoutRedirectUris: {{ toYaml . | nindent 6 }} + {{ end }} + {{ with .observed.composite.resource.spec.webOrigins }} + webOrigins: {{ toYaml . | nindent 6 }} + {{ end }} + {{ if has "client_credentials" .observed.composite.resource.spec.grantTypes }} + serviceAccountsEnabled: true + {{ end }} + {{ if has "code" .observed.composite.resource.spec.grantTypes }} + standardFlowEnabled: true + {{ end }} + {{ if has "device_code" .observed.composite.resource.spec.grantTypes }} + oauth2DeviceAuthorizationGrantEnabled: true + {{ end }} + {{ if has "password" .observed.composite.resource.spec.grantTypes }} + directAccessGrantsEnabled: true + {{- end }} + realmIdRef: + name: {{ .observed.composite.resource.spec.realm }} + - step: create-audience-mapper + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + {{ if ne $.observed.resources nil }} + apiVersion: client.keycloak.crossplane.io/v1alpha1 + kind: ProtocolMapper + metadata: + annotations: + gotemplating.fn.crossplane.io/composition-resource-name: {{ .observed.composite.resource.metadata.name }}-audience-mapper + spec: + forProvider: + name: Set token audience + protocol: openid-connect + protocolMapper: oidc-audience-mapper + config: + included.client.audience: "{{ .observed.composite.resource.spec.clientId }}" + id.token.claim: "false" + access.token.claim: "true" + introspection.token.claim: "true" + userinfo.token.claim: "false" + clientId: {{ ( index .observed.resources .observed.composite.resource.metadata.name ).resource.status.atProvider.id | default "null" }} + realmIdRef: + name: {{ .observed.composite.resource.spec.realm }} + {{ end }} + - step: create-usermodel-property-mapper + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + {{ if ne $.observed.resources nil }} + apiVersion: client.keycloak.crossplane.io/v1alpha1 + kind: ProtocolMapper + metadata: + annotations: + gotemplating.fn.crossplane.io/composition-resource-name: {{ .observed.composite.resource.metadata.name }}-sub-mapper + spec: + forProvider: + name: Username as sub claim + protocol: openid-connect + protocolMapper: oidc-usermodel-property-mapper + config: + user.attribute: username + id.token.claim: "true" + access.token.claim: "true" + claim.name: sub + userinfo.token.claim: "true" + clientId: {{ ( index .observed.resources .observed.composite.resource.metadata.name ).resource.status.atProvider.id | default "null" }} + realmIdRef: + name: {{ .observed.composite.resource.spec.realm }} + {{ end }} + - step: create-client-default-scopes + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + {{ if ne $.observed.resources nil }} + {{ if .observed.composite.resource.spec.defaultScopes }} + apiVersion: openidclient.keycloak.crossplane.io/v1alpha1 + kind: ClientDefaultScopes + metadata: + annotations: + gotemplating.fn.crossplane.io/composition-resource-name: {{ .observed.composite.resource.metadata.name }}-default-scopes + spec: + forProvider: + {{ with .observed.composite.resource.spec.defaultScopes }} + defaultScopes: {{ toYaml . | nindent 6 }} + {{ end }} + clientId: {{ ( index .observed.resources .observed.composite.resource.metadata.name ).resource.status.atProvider.id | default "null" }} + realmIdRef: + name: {{ .observed.composite.resource.spec.realm }} + {{ end }} + {{ end }} + - step: create-service-account-role + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + {{ range .observed.composite.resource.spec.serviceAccountRoles }} + --- + apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 + kind: ExtraResources + requirements: + client: + apiVersion: openidclient.keycloak.crossplane.io/v1alpha1 + kind: Client + matchName: {{ .client }} + realm: + apiVersion: realm.keycloak.crossplane.io/v1alpha1 + kind: Realm + matchName: {{ .realm }} + {{ end }} + {{ if and (ne .observed.resources nil) (ne .extraResources nil) }} + {{ range $i, $serviceAccountRole := .observed.composite.resource.spec.serviceAccountRoles }} + {{ $client := (index (index $.extraResources "client").items $i).resource }} + {{ $realm := (index (index $.extraResources "realm").items $i).resource }} + --- + apiVersion: openidclient.keycloak.crossplane.io/v1alpha1 + kind: ClientServiceAccountRole + metadata: + annotations: + gotemplating.fn.crossplane.io/composition-resource-name: {{ $.observed.composite.resource.metadata.name }}-{{ .role }} + spec: + forProvider: + clientId: {{ $client.status.atProvider.id }} + realmId: {{ $realm.status.atProvider.id }} + role: {{ $serviceAccountRole.role }} + serviceAccountUserId: {{ ( index $.observed.resources $.observed.composite.resource.metadata.name ).resource.status.atProvider.serviceAccountUserId | default "null" }} + {{ end }} + {{ end }} + - step: automatically-detect-ready-composed-resources + functionRef: + name: function-auto-ready diff --git a/k8s/infra/crossplane-crds/providers/keycloak/kustomization.yaml b/k8s/infra/crossplane-crds/compositions/kustomization.yaml similarity index 54% rename from k8s/infra/crossplane-crds/providers/keycloak/kustomization.yaml rename to k8s/infra/crossplane-crds/compositions/kustomization.yaml index 6e55eda..8410190 100644 --- a/k8s/infra/crossplane-crds/providers/keycloak/kustomization.yaml +++ b/k8s/infra/crossplane-crds/compositions/kustomization.yaml @@ -2,5 +2,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - keycloak-credentials.yaml - - config.yaml + - keycloak-builtin-objects.yaml + - keycloak-oidc-client.yaml diff --git a/k8s/infra/crossplane-crds/config/keycloak/functions.yaml b/k8s/infra/crossplane-crds/config/keycloak/functions.yaml deleted file mode 100644 index 5133a3b..0000000 --- a/k8s/infra/crossplane-crds/config/keycloak/functions.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: pkg.crossplane.io/v1beta1 -kind: Function -metadata: - name: function-extra-resources -spec: - package: xpkg.upbound.io/crossplane-contrib/function-extra-resources:v0.0.3 # renovate: github-releases=crossplane-contrib/function-extra-resources ---- -apiVersion: pkg.crossplane.io/v1beta1 -kind: Function -metadata: - name: function-auto-ready -spec: - package: xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.4.0 # renovate: github-releases=crossplane-contrib/function-auto-ready ---- -apiVersion: pkg.crossplane.io/v1beta1 -kind: Function -metadata: - name: function-keycloak-builtin-objects -spec: - package: registry.gitlab.com/corewire/images/crossplane/function-keycloak-builtin-objects:v3.0.0 # renovate: gitlab-releases=corewire/images/crossplane/function-keycloak-builtin-objects - packagePullPolicy: Always diff --git a/k8s/infra/crossplane-crds/providers/keycloak/keycloak-credentials.yaml b/k8s/infra/crossplane-crds/config/keycloak/keycloak-credentials.yaml similarity index 100% rename from k8s/infra/crossplane-crds/providers/keycloak/keycloak-credentials.yaml rename to k8s/infra/crossplane-crds/config/keycloak/keycloak-credentials.yaml diff --git a/k8s/infra/crossplane-crds/config/keycloak/kustomization.yaml b/k8s/infra/crossplane-crds/config/keycloak/kustomization.yaml index fc079dc..b021b7d 100644 --- a/k8s/infra/crossplane-crds/config/keycloak/kustomization.yaml +++ b/k8s/infra/crossplane-crds/config/keycloak/kustomization.yaml @@ -2,7 +2,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - provider.yaml - - functions.yaml - - composition.yaml - - xrd.yaml + - provider-config.yaml + - keycloak-credentials.yaml diff --git a/k8s/infra/crossplane-crds/providers/keycloak/config.yaml b/k8s/infra/crossplane-crds/config/keycloak/provider-config.yaml similarity index 100% rename from k8s/infra/crossplane-crds/providers/keycloak/config.yaml rename to k8s/infra/crossplane-crds/config/keycloak/provider-config.yaml diff --git a/k8s/infra/crossplane-crds/functions/auto-ready.yaml b/k8s/infra/crossplane-crds/functions/auto-ready.yaml new file mode 100644 index 0000000..08a4252 --- /dev/null +++ b/k8s/infra/crossplane-crds/functions/auto-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-auto-ready +spec: + package: xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.4.0 # renovate: github-releases=crossplane-contrib/function-auto-ready diff --git a/k8s/infra/crossplane-crds/functions/extra-resources.yaml b/k8s/infra/crossplane-crds/functions/extra-resources.yaml new file mode 100644 index 0000000..076c4e2 --- /dev/null +++ b/k8s/infra/crossplane-crds/functions/extra-resources.yaml @@ -0,0 +1,6 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-extra-resources +spec: + package: xpkg.upbound.io/crossplane-contrib/function-extra-resources:v0.0.3 # renovate: github-releases=crossplane-contrib/function-extra-resources diff --git a/k8s/infra/crossplane-crds/functions/go-templating.yaml b/k8s/infra/crossplane-crds/functions/go-templating.yaml new file mode 100644 index 0000000..1cbe56f --- /dev/null +++ b/k8s/infra/crossplane-crds/functions/go-templating.yaml @@ -0,0 +1,6 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-go-templating +spec: + package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.9.0 # renovate: github-releases=crossplane-contrib/function-go-templating \ No newline at end of file diff --git a/k8s/infra/crossplane-crds/functions/keycloak-builtin-objects.yaml b/k8s/infra/crossplane-crds/functions/keycloak-builtin-objects.yaml new file mode 100644 index 0000000..e170836 --- /dev/null +++ b/k8s/infra/crossplane-crds/functions/keycloak-builtin-objects.yaml @@ -0,0 +1,7 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-keycloak-builtin-objects +spec: + package: registry.gitlab.com/corewire/images/crossplane/function-keycloak-builtin-objects:v3.0.0 # renovate: gitlab-releases=corewire/images/crossplane/function-keycloak-builtin-objects + packagePullPolicy: Always diff --git a/k8s/infra/crossplane-crds/functions/kustomization.yaml b/k8s/infra/crossplane-crds/functions/kustomization.yaml new file mode 100644 index 0000000..4e27535 --- /dev/null +++ b/k8s/infra/crossplane-crds/functions/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - auto-ready.yaml + - extra-resources.yaml + - go-templating.yaml + - keycloak-builtin-objects.yaml diff --git a/k8s/infra/crossplane-crds/config/keycloak/provider.yaml b/k8s/infra/crossplane-crds/providers/keycloak.yaml similarity index 100% rename from k8s/infra/crossplane-crds/config/keycloak/provider.yaml rename to k8s/infra/crossplane-crds/providers/keycloak.yaml diff --git a/k8s/infra/crossplane-crds/providers/kustomization.yaml b/k8s/infra/crossplane-crds/providers/kustomization.yaml index 39bbd11..1bd1b72 100644 --- a/k8s/infra/crossplane-crds/providers/kustomization.yaml +++ b/k8s/infra/crossplane-crds/providers/kustomization.yaml @@ -2,4 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - keycloak + - keycloak.yaml diff --git a/k8s/infra/crossplane-crds/config/keycloak/xrd.yaml b/k8s/infra/crossplane-crds/xrds/keycloak-builtin-objects.yaml similarity index 100% rename from k8s/infra/crossplane-crds/config/keycloak/xrd.yaml rename to k8s/infra/crossplane-crds/xrds/keycloak-builtin-objects.yaml diff --git a/k8s/infra/crossplane-crds/xrds/keycloak-oidc-client.yaml b/k8s/infra/crossplane-crds/xrds/keycloak-oidc-client.yaml new file mode 100644 index 0000000..c25d0a0 --- /dev/null +++ b/k8s/infra/crossplane-crds/xrds/keycloak-oidc-client.yaml @@ -0,0 +1,110 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: CompositeResourceDefinition +metadata: + name: xoidcclients.oidc.homelab.olav.ninja +spec: + group: oidc.homelab.olav.ninja + names: + kind: XOidcClient + plural: xoidcclients + versions: + - name: v1alpha1 + served: true + referenceable: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + baseUrl: + description: Default URL to use when the auth server needs to + redirect or link back to the client. + type: string + displayName: + type: string + description: The display name of this client in the GUI + clientId: + type: string + description: The Client ID for this client, referenced in the URI during authentication and in issued tokens + clientSecretSecretRef: + description: |- + The client or client secret registered within the identity provider. This field is able to obtain its value from vault, use $${vault.ID} format. + Client Secret. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object + description: + type: string + description: The description of this client in the GUI + defaultScopes: + type: array + items: + type: string + description: |- + The default scopes to be requested when asking for authorization + grantTypes: + type: array + items: + type: string + description: |- + A list of grant types that should be enabled for the client + postLogoutRedirectUris: + type: array + items: + type: string + description: A list of valid URIs a browser is permitted to redirect + to after a successful logout. + realm: + type: string + description: The realm this client is attached to + redirectUris: + type: array + items: + type: string + description: |- + A list of valid URIs a browser is permitted to redirect to after a successful login or logout. Simple + wildcards in the form of an asterisk can be used here. This attribute must be set if either standard_flow_enabled or implicit_flow_enabled + is set to true. + serviceAccountRoles: + type: array + items: + type: object + properties: + client: + type: string + realm: + type: string + role: + type: string + description: |- + A list of roles to assign to the clients service account + type: + type: string + description: Specifies the type of client + webOrigins: + type: array + items: + type: string + description: |- + A list of allowed CORS origins. To permit all valid + redirect URIs, add +. Note that this will not include the * + wildcard. To permit all origins, explicitly add *. + required: + - clientId + - realm + required: + - spec diff --git a/k8s/infra/crossplane-crds/xrds/kustomization.yaml b/k8s/infra/crossplane-crds/xrds/kustomization.yaml new file mode 100644 index 0000000..8410190 --- /dev/null +++ b/k8s/infra/crossplane-crds/xrds/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - keycloak-builtin-objects.yaml + - keycloak-oidc-client.yaml