Skip to content

Implement LDAP Map storage for users (first implementation stage)#10700

Closed
ahus1 wants to merge 1 commit intokeycloak:mainfrom
ahus1:9930-ldap-read-write-support-for-users
Closed

Implement LDAP Map storage for users (first implementation stage)#10700
ahus1 wants to merge 1 commit intokeycloak:mainfrom
ahus1:9930-ldap-read-write-support-for-users

Conversation

@ahus1
Copy link
Copy Markdown
Member

@ahus1 ahus1 commented Mar 10, 2022

This is how the implementation can be tested:

  • Automated: Running UserModelTest with parameters
-Dkeycloak.profile.feature.map_storage=enabled
-Dkeycloak.model.parameters=Jpa,Map,LdapMapStorage
  • Run LDAP as described on Deprecated: LDAP Map Storage: How To and Q&A #10254, with the following additions:
    • after starting the LDAP server, remove the existing users bwilson and jbrown, as Keycloak would otherwise not create the admin user
    • when starting Keycloak, enable the ldap map store by adding -Dkeycloak.user.map.storage.provider=ldap-map-storage

When running a local Keycloak, the following works:

  • login with the admin user
  • create a new user
  • update the user ("cn" (firstname), "sn" (lastname) and "mail" (email) are stored in LDAP; also the attribute "description" can be set as an attribute and will be stored in LDAP)
  • search for the new user
  • list all users
  • log in with the new user

The password for the user is stored and validated against LDAP.

@ahus1 ahus1 added area/storage Indicates an issue that touches storage (change in data layout or data manipulation) keycloak.x labels Mar 10, 2022
@ahus1 ahus1 marked this pull request as draft March 10, 2022 16:24
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Mar 10, 2022

@hmlnarik - this is the first draft for a LDAP Map storage for users. It implements a partial storage for users with username, firstname, lastname and email address. All other fields are delegated to a ConcurrentHashMap.

I updated the description above on how to run it; I'm looking forward to your feedback on how to proceed.

UPDATED: Besides looking for general feedback, I look for answers to the following questions:

  • can this be merged before tree store in place and with the delegate, or would we rather "hold" this PR?
  • Adding support for roles in users: currently this is delegated. If I would add implementation for user's roles, this would all be part of LdapUserMapKeycloakTransaction, and shouldn't use any of the LdapRoleMapKeycloakTransaction, as they don't relate to each other. Please confirm (or reject).

@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from c383bf6 to c935cfd Compare March 10, 2022 16:48
@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from cc54f65 to 174d35f Compare March 23, 2022 17:41
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Mar 23, 2022

@hmlnarik - I gave it another try to extract the federation specific logic from DefaultSingleUserCredentialManager to DefaultSingleUserCredentialManagerStrategy but failed. I put my findings in the JavaDoc:

I tried to extract the federation specific parts to the {@link DefaultSingleUserCredentialManagerStrategy} but the control
flow in the existing logic: if model == null || !model.isEnabled(), the code will directly return, while
the behavior of the strategy is to continue if it returns false and it will then try other providers.

If you have additional input to that how this could be handled, please provide me with a hint. If not, this will stay as is until there is the legacy module where the code will eventually move to.

@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from 166c6eb to 75aed4d Compare March 25, 2022 12:53
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Mar 25, 2022

@hmlnarik - I've rebased the branch. The latest commits include moving moving all methods of UserCredentialStore to the new SingleUserCredentialManager. Due to that, MapUserProvider doesn't implement that interface any more. Looking forward to discuss this next week.

@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from c2c060c to 814c700 Compare March 31, 2022 07:12
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Apr 5, 2022

@hmlnarik - this PR now contains two additional commits:

(1) 7cf8afe3adc2c22047ae203896ecfbd85fbe04e5 - how to implement the authentication at the "bottom" in the map storage and also to look up the user there. With the data found in LDAP the entity "bubbles up" and it then returned as a User in CredentialValidationOutput.

(2) 4a114488de243b16c1cf0a07fd31035928919af6 - minimal changes to KerberosFederationProvider authentication work "at the top", and then it calls findOrCreateAuthenticatedUser() on the store to look up an existing user (can be provided by LDAP with the right attributes already), or to create one. Conflicting users will be deleted. I only tested looking up an existing matching user, I didn't use the creation of a user. Still I would think that this would work with a standard Map provider where it would then create the user if it doesn't exist there.

To run the example:

  • first build and install all modules as otherwise the changed ldif files will not be used with the ApacheDS
  • start ApacheDS with Kerberos with mvn -pl testsuite/utils exec:java -Pkerberos
  • configure Kerberos locally for Apache DS, for example for Firefox
  • after Keycloak has initialized LDAP, move user hnelson to the "Internal" dc to use it as a test user - Option 1 should then run.
  • For option 2, add user federation "by the book" in the GUI and select just "Kerberos"

I'd actually prefer option (2) as it only passes in the username. As the username needs to be unique within a realm, the KerberosFederationProvider already does a lot of things the right way.

I'm sure there are other things that need to be considered, I'd be happy to hear your thoughts. Thanks!

@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from 4a11448 to 3ed12a5 Compare April 14, 2022 09:10
@mhajas mhajas self-requested a review April 14, 2022 13:05
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Apr 22, 2022

Hi @hmlnarik - I've been playing around with Active Directory here df792bf on top of this branch's changes. I can now get Keycloak to setup all roles and the admin user via LDAP including setting the password of the admin user and enabling it. Once we've checked LDAP for ApacheDS and Kerberos, that will be next.

This includes SPNEGO for ApacheDS and ActiveDirectory

Closes keycloak#9930
@ahus1 ahus1 force-pushed the 9930-ldap-read-write-support-for-users branch from 3ed12a5 to 85e009c Compare June 29, 2022 10:07
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Jun 29, 2022

@hmlnarik - I've now rebased this PR as the parts of the user credential handling have been implemented when moving over the legacy store. I tested this successfully with Kerberos authentication with Firefox, Keycloak, and ApacheDS.

To be able to close #9932, the only change I would need to move over would be the one in MapCredentialValidationOutput.java - this is just about Java generics handling.

All other changes around LDAP would need to wait for the tree store. The changes in keycloak-kerberos-federation will need to be revisited, from what I see this could be done after map storage is in the preview phase.

Please comment if the way to proceed is:

Thanks.

@ahus1 ahus1 removed the request for review from mhajas July 11, 2022 07:04
@ahus1 ahus1 added the kind/feature Categorizes a PR related to a new feature label Sep 8, 2022
@ahus1 ahus1 mentioned this pull request Aug 18, 2023
@ahus1
Copy link
Copy Markdown
Member Author

ahus1 commented Nov 9, 2023

As announced to the community in this blog post, we are no longer developing the Map Store, and it will be removed from Keycloak's code base. Follow #24111 for the removal steps.

@ahus1 ahus1 closed this Nov 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage Indicates an issue that touches storage (change in data layout or data manipulation) kind/feature Categorizes a PR related to a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Password validation for LDAP users Read-write LDAP implementation for users

2 participants