Repository navigation
Declarative configuration API #33049
Replies: 6 comments 2 replies
|
I created some Python application for keycloak configuration called rdynacloak https://gitlab.com/C-X1/rdynacloak/. In the Keycloak pod we have two additional containers the rdynacloak and a k8s-sidecar (https://github.com/kiwigrid/k8s-sidecar) The k8s-sidecar picks up any Secret or ConfigMap inside the current namespace with label and value “keycloak: keycloak_release-namespace” and puts the files from each of those inside a directory shared with rdynacloak. rdynacloak watches this directory and on a update uses the existing Keycloak modules from Ansible (in https://docs.ansible.com/ansible/latest/collections/community/general by using the Python Ansible runner) to apply the as settings given in the files to a realm called like the current namespace. Additional settings are just applied, but for deletions or changes the realm is deleted and recreated - so no need to undo the changes also in some cases undoing changes like deleting roles would break things. When a client helm chart is installed (e.g. Grafana, Jenkins, etc), it creates a secret containing the openid-client and the roles and role-bindings and its client secret. Here is an explanation of such config file: service_id: grafana # an id for it to be able to be checked for readiness on the rest api of rdynacloak (not used by use atm)
# Each other entry in the yaml file is an array
# The key name of that array matches the name of the ansible
# module - without the "keycloak_" prefix plus a "s" in the end.
#
# Example: clients is for keylcoak_client
# https://docs.ansible.com/ansible/latest/collections/community/general/keycloak_client_module.html
#
# The keycloak modules I am using are applied in a specific order
# (groups -> roles -> users -> clients -> client_rolemappings)
# assuring that everything is already in place and it does not produce
# errors like if a client is not there for the client_rolemappings
# Each array entry is consistent with the values for the ansible module.
# auth_token, auth_user, auth_url, realm etc is set by rdynacloak
client_rolemappings:
- ...
clients:
- ...
roles:
- ...
- ...Bigger setup and IssuesEach tenant (internal customer project) has its own namespace and Keycloak. We by default have LDAP and Microsoft Azure AD. Mostly they are called like PROJECTNAME_admin (Admins) That and the to work around the Azure redirect URL security (needs to be added by our IT department – that can take days … mostly one or two) led to the following setup: Azure AD -> Main Cluster Keycloak -> Tenant Keycloak The LDAP groups are synced to the main Keycloak and the Azure AD is used as OpenID Identity Provider, login is automatically forwarded from Tenant to Main Keycloak to Azure AD. Open Problems:
Solved Problems:
|
|
Sounds really great. Looking forward to it. I wrote a configurer service that is deployed togehter with our main application that automatically configures Keycloak, creates clients, roles, users and so on. But it is a real pain at the moment, because I wrote our own API client to the REST API (the default Java Keycloak API has a very bad documentation and obscure error/ exception handling and I wanted to have full control). But the REST API itself is very tedious to use, because of its design. Esspacially if you want to create a new resource or update it and that resource has links to other resource, every relationship has to be created using a seperate HTTP request to the API. For example, if you want to update a user and update its roles, you need 2 extra requests to add and remove roles. And also sometimes the POST endpoint that creates a resource also creates existing relationships that are present in the sent DTOs, but the PUT endpoint to the same resource ignores that relationships to other resources. So creating resources can sometimes be done with 1 request, but updating it requires several requests. So you never really know how to handle a new resource/ what attributes in the DTOs are actually supported by the endpoints. Having different DTOs for POST/PUT/GET would help here, because then you know what fields are actually supported. Plus, it should be mentioned which fields can be null/not available and which not. |
|
An updated Admin API should allow much easier configuration of Keycloak entities without search query lookups, which are necessary with the current API. Here is a real-life example which could be optimized: Create a new realm and an admin user at master realm. The admin user should be allowed to manage the new realm but not any other. A use case with existing Admin APICreate realm with realmName example Create admin user at master realm, extract userId from location header of response: Get realm management client and extract clientId of this client: Get roles defined by realm management client: In a loop for every of these roles, assign it to the realm admin user: The use case with API proposed in next sectionAn admin API v2 could allow addressing by unique name, to make declarative creation very easy. Proposals for upcoming admin APIThe upcoming API could support declarative creation of entities with by-name addressing and create or update semantics with PUT. Addressing by nameWhen the name of an entity is unique (like realm name, username, client ID) address the entity via that name by default. Example: Create or update a realm by name and get the realm by name Support addressing by UUID as a migration path for existing API calls. A special name like "id=5d22cdc5-dc40-4751-a69e-4dfb112d67fd" could be used to indicate that an entity should be resolved by id Creation with a provided ID would not be supported. Also creation with providing the name only in the representation and not in the URL wouldn't be supported. Name scheme for rolesAddressing hierarchical entities by name needs a naming scheme. Groups have the group path which can be used. Roles need a scheme with OAuth Client ID and role name like . or just the role name in case of a realm role: realmRoleName Examples: Get role of client example-realm named view-users This is preferred over Create or update semanticsPOST for creation is not needed in API v2. It's always "create or update" with PUT and with name (where unique name in current entity model). A URL with name is also returned at the location header, when entity was created (supports HATEOAS). When creating a resource, the name in the representation is ignored. When it is update, it depends on the resource if it allows the name to be updated via representation. Entities should allow to update individual parts, e.g. a single realm-attribute. Addressing relations like role assignmentsFor relations put all identifiers (names) in the URL. If the relation isn't an entity with own data stored, there is no need for a body. Example: Assign a role to a user Example: Get all directly assigned roles of a user |
What you POST is what you GET(credit goes to @s-urbaniak for the title) Problem descriptionAll Controller-based software (Kubernetes Operators, Terraform running in a loop etc) act only if the Desired State is different than Current State. This adds limitations to the future REST interface - it simply cannot manipulate the resources it created. It needs to either completely accept or reject them. A good illustration of this problem is Keycloak Terraform Provider Users section. With the following TF definition: The Terraform detects changes over and over again: This happens because Keycloak puts Solution ideasOne way of addressing this problem is to separate the "Desired" from "Runtime" Configuration. The Desired Configuration should should always be exactly what was requested without. The Runtime Configuration will contain defaults and other Runtime bits. Below is an imaginary example how this could work: |
|
Small issue that I was able to work around, but I ran into an API deficiency when I was trying to configure the dedicated client scope of a client. As far as I can tell, there's no way to access that via the API. Instead I created some global client scopes and attached them, but it was a source of confusion when converting our clickops runbook with an api connected script. |
|
Declarative config will be a cornerstone in designing the new Admin API v2. As we're starting the work on this area, we'd like to collect some feedback on drawbacks of the current API. Feel free to share your thoughts on that in a dedicated discussion. |
Uh oh!
There was an error while loading. Please reload this page.
The Keycloak team is working on a new REST API to support declarative configuration. The current Admin REST API is confusing, inconsistent and overall not really ready for a declarative style of communication. The main thoughts for the new API are:
This discussion is to continuously gather feedback as the design and a PoC evolves.
All reactions