crossplane-contrib / provider-keycloak

Apache License 2.0
21 stars 11 forks source link

Unable to set realm default roles #80

Open vladimirblahoz opened 5 months ago

vladimirblahoz commented 5 months ago

Hi! Is there any example of how to set default roles for crossplane managed realm? I have a keycloak v 24.0.2 deployed and a realm provisioned by keycloak-provider v 0.15.0. When this realm is created, it automatically creates a composite role named "default-roles-[realm-name]" into which I need to assign my default roles. Obviously the default-roles role is not managed by crossplane. I assumed looking at its name that the resource defaults.keycloak.crossplane.io/v1alpha1/roles is meant for this.

kind: Roles
metadata:
  name: default-roles
spec:
  forProvider:
    realmId: testrealm
    defaultRolesRefs:
      - name: default
  providerConfigRef:
    name: keycloak-provider-config

Applying this manifest results in quite strange error event:

image

I also tried another approach based on Import Existing Resource documentation and importing the automatically created role with:

kind: Role
metadata:
  name: imported-default-roles
  annotations:
    crossplane.io/external-name: default-roles-testrealm
spec:
  forProvider:
    realmId: testrealm
    name: default-roles-testrealm
    compositeRolesRefs:
      - name: default
  providerConfigRef:
    name: keycloak-provider-config

That fails on an attempt to newly create the existing role resulting in names conflict

image

I also tried just to test the importing works to add managementPolicies: [ "Observe" ] to the role manifest (being aware that with that I shouldn't be able to change the compositeRolesRefs) and that again fails on another error

image

This makes me feel that keycloak provider does not support the managementPolicies. And I am kind of out of ideas. Any help will be very appreciated.

QuadmanSWE commented 5 months ago

I ran into this just now, link to the findings. You can enable this but it will not help you to find the default realm role since you need to reference its external name by some random guid.

https://github.com/crossplane-contrib/provider-keycloak/issues/74#issuecomment-2061253814

QuadmanSWE commented 5 months ago

Even when importing the client and the roles from their random guids in keycloak to crossplane I was unable to actually make a user an admin. I tried to grant the role directly but I couldn't find what resource to use for that but then I found group roles but that apparently doesn't do anything. Membership worked fine and my user becomes member of my "realm-admin" group but the group doesn't get the proper role eventhough the roleidref seems to work fine?

image

Here is my entire attempt:

apiVersion: realm.keycloak.crossplane.io/v1alpha1
kind: Realm
metadata:
  name: developers-realm
spec:
  forProvider:
    realm: developers-realm
    enabled: true
    displayName: "Home of the Developers"
  providerConfigRef:
    name: keycloak-config
---
apiVersion: openidclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: realm-management-developers-realm
  annotations: 
    crossplane.io/external-name: developers-realm/0f84dce2-76b2-49ac-ba2e-681a604c78b7
spec:
  forProvider: {}
  providerConfigRef:
    name: keycloak-config
  managementPolicies: ["Observe"]
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: manage-realm-realm-management-developers-realm
  annotations: 
    crossplane.io/external-name: developers-realm/0acc58b1-3eb0-4ec1-9979-7a97fc10a89b
spec:
  forProvider: {}
  providerConfigRef:
    name: keycloak-config
  managementPolicies: ["Observe"]
---
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Group
metadata:
  name: developers-realm-admins
spec:
  forProvider:
    realmIdRef:
      name: developers-realm
    name: realm-admins
  providerConfigRef:
    name: keycloak-config
---
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Roles
metadata:
  name: developers-realm-admins-roles
spec:
  forProvider:
    groupIdRef:
      name: developers-realm-admins
      policy:
        resolution: Required
    realmIdRef:
      name: developers-realm
      policy:
        resolution: Required
    roleIdsRefs:
      - name: manage-realm-realm-management-developers-realm
        policy:
          resolution: Required
  providerConfigRef:
    name: keycloak-config
---
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Memberships
metadata:
  name: developers-realm-admins-memberships
spec:
  forProvider:
    groupIdRef:
      name: developers-realm-admins
    members:
      - guest
    realmIdRef:
      name: developers-realm
  providerConfigRef:
    name: keycloak-config
---
apiVersion: user.keycloak.crossplane.io/v1alpha1
kind: User
metadata:
  name: guest-user-developers-realm
spec:
  forProvider:
    realmIdRef:
      name: developers-realm
    username: "guest"
    email: "guest@somedomain.com"
    firstName: "Guest"
    lastName: "User"
    emailVerified: true
    initialPassword:
      - temporary: true
        valueSecretRef:
          key: default-password
          name: default-user-settings
          namespace: development
    requiredActions: # VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD, TERMS_AND_CONDITIONS
      - UPDATE_PROFILE
      - CONFIGURE_TOTP
  providerConfigRef:
    name: keycloak-config
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: default-user-settings
  namespace: development
spec:
  encryptedData:
    default-password: someencryptedpassword
  template:
    metadata:
      creationTimestamp: null
      name: default-user-settings
      namespace: development
    type: Opaque
mustafa-be commented 5 months ago

Hello , I had the same issue a while ago, I was able to make the default roles resource work by setting an appropriate ExternalNameConfig in config/external_name.go

You would be able to set default realm roles using this resource eg https://github.com/crossplane-contrib/provider-keycloak/blob/main/examples-generated/defaults/v1alpha1/roles.yaml

Problem with this resource is that you wouldnt be able to set default roles of a client because its not supported in upstream tf provider, Theres a pull request for it terraform-provider-keycloak repository thats waiting to be merged for a long time.

Edit: updated pull request link thanks @Breee

mustafa-be commented 5 months ago

I did have an alternative for it, but it might not be the best. We already have ansible provider on our clusters.

I simply used an AnsibleRun to configure default roles and it worked, The community general collection has module for keycloak API. This helped resolve my issue specifically https://docs.ansible.com/ansible/latest/collections/community/general/keycloak_role_module.html#ansible-collections-community-general-keycloak-role-module.

Obviously its way better to have it included in provider.

Breee commented 5 months ago

mustafa means this PR https://github.com/mrparkers/terraform-provider-keycloak/pull/764

Breee commented 5 months ago

Alright guys, the default roles are kinda trashy and we have no choice than writing our own controller for that.

I however found a good workaround for you which is in my opinion even better to manage. PR https://github.com/crossplane-contrib/provider-keycloak/pull/86 adds default_groups

--- 
apiVersion: defaults.keycloak.crossplane.io/v1alpha1
kind: DefaultGroups
metadata:
  name: default
spec:
  forProvider:
    groupIdsRefs:
    - name: my-group
    realmIdRef:
      name: my-realm
  providerConfigRef:
    name: keycloak-provider-config

Full Example:

---
apiVersion: realm.keycloak.crossplane.io/v1alpha1
kind: Realm
metadata:
  name: my-realm
spec:
  forProvider:
    enabled: true
    realm: my-realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: openidclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: test
spec:
  forProvider:
    realmIdRef:
      name: "my-realm"
    accessType: "CONFIDENTIAL"
    clientId: "test"
    serviceAccountsEnabled: false
  providerConfigRef:
    name: "keycloak-provider-config"
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: my-realm-role
spec:
  forProvider:
    description: My Realm Role
    name: my-realm-role
    realmIdRef:
      name: my-realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: my-client-role
spec:
  forProvider:
    description: My Client Role
    name: my-client-role
    realmIdRef:
      name: my-realm
    clientIdRef:
      name: test
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Group
metadata:
  name: my-group
spec:
  forProvider:
    name: my-group
    realmIdRef:
      name: my-realm
  providerConfigRef:
    name: keycloak-provider-config
--- 
# Example Role mapping: Using groupId and roleIds to assign roles to the default group
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Roles
metadata:
  name: dev-group-roles
spec:
  forProvider:
    realmIdRef:
      name: my-realm
    groupIdRef: 
      name: my-group
    roleIdsRefs:
      - name: my-realm-role
      - name: my-client-role
  providerConfigRef:
    name: keycloak-provider-config
--- 
apiVersion: defaults.keycloak.crossplane.io/v1alpha1
kind: DefaultGroups
metadata:
  name: default
spec:
  forProvider:
    groupIdsRefs:
    - name: my-group
    realmIdRef:
      name: my-realm
  providerConfigRef:
    name: keycloak-provider-config

I hope that helps you out until the controller is ready to roll.

You can test that out in version v0.18.0

https://marketplace.upbound.io/providers/crossplane-contrib/provider-keycloak/v0.18.0

b509 commented 1 month ago

Hey @vladimirblahoz, I needed this exact same feature and added it to @Breee's thankfully provided crossplane function. If you want to have a look at it, maybe it helps https://gitlab.com/corewire/images/crossplane/function-keycloak-builtin-objects#5-modified-default-config

(For a general documentation on how to make the function run, read the complete README)