apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: keycloakidentity.auth.yourdomain.com
spec:
  writeConnectionSecretsToNamespace: crossplane-system
  compositeTypeRef:
    apiVersion: auth.yourdomain.com/v1alpha1
    kind: KeycloakIdentity
  resources:
    # 1. First create the realm
    - name: realm
      base:
        apiVersion: realm.keycloak.crossplane.io/v1alpha1
        kind: Realm
        metadata:
          annotations:
            crossplane.io/external-name: "{{ index .metadata.annotations \"keycloak/realm-name\" }}"
        spec:
          forProvider:
            realm: ""
            enabled: true
            displayName: ""
            registrationAllowed: false
            resetPasswordAllowed: true
            rememberMe: true
            loginWithEmailAllowed: true
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: realm-connection-{{ index .metadata.annotations "keycloak/realm-name" }}
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: metadata.annotations[keycloak/realm-name]
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realm
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.displayName
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.writeConnectionSecretToRef.name
          transforms:
            - type: string
              string:
                fmt: realm-connection-%s

    # 2. Create the k8s-admins group
    - name: admins-group
      base:
        apiVersion: group.keycloak.crossplane.io/v1alpha1
        kind: Group
        spec:
          forProvider:
            name: k8s-admins
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: admins-group-secret
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
      connectionDetails:
        - fromConnectionSecretKey: id
          name: adminsGroupId

    # 3. Create the users group
    - name: users-group
      base:
        apiVersion: group.keycloak.crossplane.io/v1alpha1
        kind: Group
        spec:
          forProvider:
            name: users
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: users-group-secret
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
      connectionDetails:
        - fromConnectionSecretKey: id
          name: usersGroupId

    # 4. Create the developers group
    - name: developers-group
      base:
        apiVersion: group.keycloak.crossplane.io/v1alpha1
        kind: Group
        spec:
          forProvider:
            name: developers
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: developers-group-secret
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
      connectionDetails:
        - fromConnectionSecretKey: id
          name: developersGroupId

    # 5. Create the admin user with password
    - name: admin-user
      base:
        apiVersion: user.keycloak.crossplane.io/v1alpha1
        kind: User
        spec:
          forProvider:
            emailVerified: true
            enabled: true
            firstName: Admin
            lastName: User
            initialPassword:
              - temporary: true
                valueSecretRef:
                  namespace: crossplane-system
                  name: admin-password-secret
                  key: password
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: admin-user-secret
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
        - type: FromCompositeFieldPath
          fromFieldPath: spec.adminUsername
          toFieldPath: spec.forProvider.username
        - type: FromCompositeFieldPath
          fromFieldPath: spec.adminEmail
          toFieldPath: spec.forProvider.email
      connectionDetails:
        - fromConnectionSecretKey: id
          name: adminUserId

    # 6. Create admin-user to k8s-admins group membership
    - name: admin-to-admins-membership
      base:
        apiVersion: user.keycloak.crossplane.io/v1alpha1
        kind: Groups
        spec:
          forProvider:
            exhaustive: false
          providerConfigRef:
            name: keycloak-provider
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
        - type: PatchSet
          patchSetName: adminUserId-patching
        - type: PatchSet
          patchSetName: adminsGroupId-patching

    # 7. Create admin-user to users group membership
    - name: admin-to-users-membership
      base:
        apiVersion: user.keycloak.crossplane.io/v1alpha1
        kind: Groups
        spec:
          forProvider:
            exhaustive: false
          providerConfigRef:
            name: keycloak-provider
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
        - type: PatchSet
          patchSetName: adminUserId-patching
        - type: PatchSet
          patchSetName: usersGroupId-patching

    # 8. Create Pomerium client
    - name: pomerium-client
      base:
        apiVersion: openidclient.keycloak.crossplane.io/v1alpha1
        kind: Client
        spec:
          forProvider:
            clientId: pomerium
            name: "Pomerium Identity-Aware Proxy"
            description: "Client for Pomerium IAP"
            enabled: true
            clientAuthenticatorType: client-secret
            accessType: "CONFIDENTIAL"
            standardFlowEnabled: true
            directAccessGrantsEnabled: false
            serviceAccountsEnabled: false
            validRedirectUris: []
            webOrigins:
              - "+"
          providerConfigRef:
            name: keycloak-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
            name: pomerium-client-secret
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.realmName
          toFieldPath: spec.forProvider.realmId
        - type: FromCompositeFieldPath
          fromFieldPath: spec.pomeriumRedirectUri
          toFieldPath: spec.forProvider.validRedirectUris[0]
      connectionDetails:
        - fromConnectionSecretKey: clientSecret
          name: pomeriumClientSecret

  patchSets:
    - name: adminUserId-patching
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: connectionDetails.adminUserId
          toFieldPath: spec.forProvider.userId
    
    - name: adminsGroupId-patching
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: connectionDetails.adminsGroupId
          toFieldPath: spec.forProvider.groupIds[0]
    
    - name: usersGroupId-patching
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: connectionDetails.usersGroupId
          toFieldPath: spec.forProvider.groupIds[0]
