<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <br>
    <div class="moz-forward-container"><br>
      <br>
      -------- Original Message --------
      <table class="moz-email-headers-table" cellpadding="0"
        cellspacing="0" border="0">
        <tbody>
          <tr>
            <th align="RIGHT" nowrap="nowrap" valign="BASELINE">Subject:
            </th>
            <td>Re: [keycloak-dev] sync/federation requirements/ideas</td>
          </tr>
          <tr>
            <th align="RIGHT" nowrap="nowrap" valign="BASELINE">Date: </th>
            <td>Mon, 14 Jul 2014 09:20:00 +0200</td>
          </tr>
          <tr>
            <th align="RIGHT" nowrap="nowrap" valign="BASELINE">From: </th>
            <td>Marek Posolda <a class="moz-txt-link-rfc2396E" href="mailto:mposolda@redhat.com">&lt;mposolda@redhat.com&gt;</a></td>
          </tr>
          <tr>
            <th align="RIGHT" nowrap="nowrap" valign="BASELINE">To: </th>
            <td>Bill Burke <a class="moz-txt-link-rfc2396E" href="mailto:bburke@redhat.com">&lt;bburke@redhat.com&gt;</a>,
              <a class="moz-txt-link-rfc2396E" href="mailto:keycloak-dev@lists.jboss.org">"keycloak-dev@lists.jboss.org"</a>
              <a class="moz-txt-link-rfc2396E" href="mailto:keycloak-dev@lists.jboss.org">&lt;keycloak-dev@lists.jboss.org&gt;</a></td>
          </tr>
        </tbody>
      </table>
      <br>
      <br>
      <pre>On 11.7.2014 16:26, Bill Burke wrote:
&gt;
&gt;
&gt; On 7/10/2014 3:01 PM, Marek Posolda wrote:
&gt;&gt;&gt; The problem with this approach is that new users don't get imported
&gt;&gt;&gt; into Keycloak until the sync gets invoked.  Syncing more than once per
&gt;&gt;&gt; day, or even once per week may not be feasible.  If the external
&gt;&gt;&gt; storage does not have a changelog, syncing would involve iterating
&gt;&gt;&gt; through each and every user in external storage and syncing it with
&gt;&gt;&gt; the keycloak database.  A full sync could take hours.
&gt;&gt; Yes, but how to do it differently?
&gt;&gt; (a) For methods like: UserProvider.getUsers(), UserProvider.searchFor***
&gt;&gt; we can either:
&gt;&gt; 1) retrieve users just from "local" store
&gt;&gt; 2) Federate users and merge them from both "local" and "external" store.
&gt;&gt;
&gt;&gt; Federation approach (2) has quite bad performance issues (especially
&gt;&gt; with pagination+sorting), so I would prefer (1). But this really
&gt;&gt; requires full sync from external store into KC IMO.
&gt;&gt;
&gt;&gt;
&gt;&gt; (b) Then we have methods for retrieve single user:
&gt;&gt; getUserBy*** --- here we can try to retrieve user from 'local' store and
&gt;&gt; fallback to 'external'. In that case, user will be synced on demand to
&gt;&gt; KC database (similar approach like AuthenticationProvider), but then we
&gt;&gt; have the issue that just those users, who were retrieved from
&gt;&gt; externalStore will be available in KC.
&gt;&gt;
&gt;&gt; I think that we can either:
&gt;&gt; (1) Federate users from both stores
&gt;&gt; (2) Temporarily allow that just some users from LDAP are available in KC
&gt;&gt; database (those who were authenticated or for which getUserBy*** was
&gt;&gt; called)
&gt;&gt; (3) Do full sync
&gt;&gt;
&gt;&gt; I don't know if you see some other solution, but I would say that if we
&gt;&gt; want to avoid (1) and (2) we really need to do full sync. So I would
&gt;&gt; imagine that if someone configure externalStore, he will also need to
&gt;&gt; trigger full sync to KC to have all users added to Keycloak.
&gt;
&gt;
&gt; Really depends on the UserProvider implementation IMO.  The 
&gt; UserProvider doesn't have to import the users on search/getAll 
&gt; operations. The UserModels returned could be proxies.  Probably harder 
&gt; than I'm stating, but its quite possible its not.
&gt;
&gt;
&gt;&gt; Personally I would prefer to always do sync from KC immediatelly as
&gt;&gt; event queue doesn't always work.
&gt;
&gt; +1.  We'll probably eventually have to have an event queue, but I'd 
&gt; like to avoid it.
&gt;
&gt;&gt;
&gt;&gt; But fact is that if externalProvider doesn't support changelog, then how
&gt;&gt; to do sync without something like "getAllUsers" (or "syncAllUsers")? I
&gt;&gt; know that this is quite overhead, but I really don't see how to do
&gt;&gt; "partial" sync from 3rd party provider if it doesn't support 
&gt;&gt; changelogs...
&gt;&gt;
&gt;
&gt;
&gt; How do we do external store-&gt;Keycloak sync?  *WE* don't.  The user 
&gt; does! :)  Again  Have a very simple ChronJob that can be scheduled.  I 
&gt; don't think there's any detailed SPI we can write that will solve all 
&gt; user needs.
&gt;
&gt;&gt; Marek
&gt;&gt;&gt;
&gt;&gt;&gt;
&gt;&gt;&gt; IMO it would be something like this:
&gt;&gt;&gt;
&gt;&gt;&gt; public interface ChronJob {
&gt;&gt;&gt;
&gt;&gt;&gt;    void invoke(KeycloakSessionFactory factory);
&gt;&gt;&gt; }
&gt;&gt;&gt;
&gt;
&gt; The ChronJob has full access to local keycloak storage and can begin 
&gt; and end transactions as needed.  We can probably provide one out of 
&gt; the box for LDAP based on simple mapping metadata that can be 
&gt; configured, but anything more complex has to be written by the user.
&gt;
&gt;
ok, once I finish export/import I can take a look how it looks with LDAP 
and changelogs, but unfortunately I don't think that it's standardized 
way to support this for all LDAP servers... Will also take a look at 
pagination, which is surely supported by most of LDAP servers AFAIK. The 
point for pagination is, that for example sync large LDAP with 100K 
users is probably not going to happen in single Keycloak transaction, 
but ChronJob would likely need to do it paginated in more transactions.

Marek
</pre>
      <br>
    </div>
    <br>
  </body>
</html>