• 12
    • 9
    • We collect Confluence feedback from various sources, and we evaluate what we've collected when planning our product roadmap. To understand how this piece of feedback will be reviewed, see our Implementation of New Features Policy.

      NOTE: This suggestion is for Confluence Server. Using Confluence Cloud? See the corresponding suggestion.

      It is common to have an LDAP directory that does not support incremental syncs and is moderately sized. These directories don't have the option to lower the sync interval to pick up group membership changes for known users, so admins currently have to trigger syncs from the UI if the sync interval is not an acceptable time to wait for the change to reach Confluence. If the REST API had a means of triggering a sync remotely, it would give admins an easy (and scriptable) way to pick up changes to a directory.

            [CONFSERVER-26737] Trigger Directory Syncs using the REST API

            Raphael R added a comment -

            Hi, the excellent script that was posted here stopped working for us after upgrading to Confluence 7.19.

            Apparently the GET request for the sync now needs to be a POST, with the payload being atl_token.

            Replacing the last for.. loop with these lines worked for us with 7.19.6:

            # extract atl_token from RESP
            ATL_TOKEN=$(grep atl_token $RESP | grep value | head -1 | awk -F'"' '{print $6}')
            # look for all of the available sync operations and call each one-by-one
            for sync_path in $(grep /sync $RESP | grep directoryId | grep -v "{id}" | sed 's/^.*href="//; s/"//') ; do
                    curl -n -k -b $COOKIE -s --header "application/x-www-form-urlencoded" -X POST --data "atl_token=${ATL_TOKEN}" "${BASEURL}${sync_path}"
            done
             

            Raphael R added a comment - Hi, the excellent script that was posted here stopped working for us after upgrading to Confluence 7.19. Apparently the GET request for the sync now needs to be a POST, with the payload being atl_token. Replacing the last for.. loop with these lines worked for us with 7.19.6: # extract atl_token from RESP ATL_TOKEN=$(grep atl_token $RESP | grep value | head -1 | awk -F '"' '{print $6}' ) # look for all of the available sync operations and call each one-by-one for sync_path in $(grep /sync $RESP | grep directoryId | grep -v "{id}" | sed 's/^.*href= " //; s/" //' ) ; do         curl -n -k -b $COOKIE -s --header "application/x-www-form-urlencoded" -X POST --data "atl_token=${ATL_TOKEN}" "${BASEURL}${sync_path}" done

            Adam Labus added a comment -

            Adam Labus added a comment - Hi guys, as a workaround please check  Extender for Confluence app and documentation https://it-lab-site.atlassian.net/wiki/spaces/RAEC/pages/1904836644/REST+API+-+User+Directories   Cheers Adam

            Andreas Hochsteger added a comment - - edited

            Hi, this a shell script version (based on the script from JRASERVER-68724) that is tested with Confluence 6.15.10.

            Example Usage:

            USERNAME=myusername PASSWORD=mypassword ./confluence-directory-sync.sh https://confluence.domain.com

            Contents of file confluence-directory-sync.sh:

            #!/bin/bash
            
            # Source: https://jira.atlassian.com/browse/CONFSERVER-26737
            
            #set -x
            
            # USERNAME and PASSWORD are expected to be set as environment variables.
            # The base URL of the app is given on the command line (ie: https://confluence.domain.com)
            BASEURL=$1
            [ -z "$BASEURL" ] && echo "usage: USERNAME=myusername PASSWORD=mypassword $0 BASEURL" && exit 1
            
            # Required URLs and paths:
            WEB_START_URL="${BASEURL}/login.action"
            WEB_LOGIN_URL="${BASEURL}/dologin.action"
            WEB_SUDO_URL="${BASEURL}/doauthenticate.action"
            WEB_DIRLIST_PATH="/plugins/servlet/embedded-crowd/directories/list"
            
            # store the cookie as a temp file that is deleted as we finish
            COOKIE=/tmp/GetRest.$$
            RESP=/tmp/GetToken.$$
            
            # Render the login page to get some cookies
            curl -k -c $COOKIE -s "${WEB_START_URL}" -o /dev/null
            
            # login and save the cookie
            curl -k -b $COOKIE -c $COOKIE -s -X POST \
             --data-urlencode "os_username=${USERNAME}" \
             --data-urlencode "os_password=${PASSWORD}" \
             --data "login='Log In'" \
             --data "os_destination=${WEB_DIRLIST_PATH}" \
             "${WEB_LOGIN_URL}" -o /dev/null
            
            # Do web sudo
            curl -k -b $COOKIE -c $COOKIE -s -X POST \
             --data-urlencode "password=${PASSWORD}" \
             --data "authenticate=Confirm" \
             --data "destination=${WEB_DIRLIST_PATH}" \
             "${WEB_SUDO_URL}" -o /dev/null
            
            # get the list of sync opertaions by getting the URL with the cookie
            curl -k -b $COOKIE -c $COOKIE -s -X GET "${BASEURL}${WEB_DIRLIST_PATH}" > $RESP
            
            # look for all of the available sync operations and call each one-by-one
            for sync_path in $(grep /sync $RESP | grep atl_token= | grep -v "{id}" | sed 's/^.*href="//; s/".$//') ; do
                    curl -k -b $COOKIE -s -X GET "${BASEURL}${sync_path}"
            done
            
            # delete the temp files
            rm -f $COOKIE $RESP
            

            To trigger the directory sync for Jira Server and Bitbucket Server have a look similar scripts in the comments of these issues:

            Andreas Hochsteger added a comment - - edited Hi, this a shell script version (based on the script from JRASERVER-68724 ) that is tested with Confluence 6.15.10. Example Usage: USERNAME=myusername PASSWORD=mypassword ./confluence-directory-sync.sh https://confluence.domain.com Contents of file confluence-directory-sync.sh: #!/bin/bash # Source: https://jira.atlassian.com/browse/CONFSERVER-26737 #set -x # USERNAME and PASSWORD are expected to be set as environment variables. # The base URL of the app is given on the command line (ie: https://confluence.domain.com) BASEURL= $1 [ -z " $BASEURL " ] && echo "usage: USERNAME=myusername PASSWORD=mypassword $0 BASEURL" && exit 1 # Required URLs and paths: WEB_START_URL= "${BASEURL}/login.action" WEB_LOGIN_URL= "${BASEURL}/dologin.action" WEB_SUDO_URL= "${BASEURL}/doauthenticate.action" WEB_DIRLIST_PATH= "/plugins/servlet/embedded-crowd/directories/list" # store the cookie as a temp file that is deleted as we finish COOKIE=/tmp/GetRest.$$ RESP=/tmp/GetToken.$$ # Render the login page to get some cookies curl -k -c $COOKIE -s "${WEB_START_URL}" -o /dev/null # login and save the cookie curl -k -b $COOKIE -c $COOKIE -s -X POST \ --data-urlencode "os_username=${USERNAME}" \ --data-urlencode "os_password=${PASSWORD}" \ --data "login= 'Log In' " \ --data "os_destination=${WEB_DIRLIST_PATH}" \ "${WEB_LOGIN_URL}" -o /dev/null # Do web sudo curl -k -b $COOKIE -c $COOKIE -s -X POST \ --data-urlencode "password=${PASSWORD}" \ --data "authenticate=Confirm" \ --data "destination=${WEB_DIRLIST_PATH}" \ "${WEB_SUDO_URL}" -o /dev/null # get the list of sync opertaions by getting the URL with the cookie curl -k -b $COOKIE -c $COOKIE -s -X GET "${BASEURL}${WEB_DIRLIST_PATH}" > $RESP # look for all of the available sync operations and call each one-by-one for sync_path in $(grep /sync $RESP | grep atl_token= | grep -v "{id}" | sed 's/^.*href= "//; s/" .$//' ) ; do curl -k -b $COOKIE -s -X GET "${BASEURL}${sync_path}" done # delete the temp files rm -f $COOKIE $RESP To trigger the directory sync for Jira Server and Bitbucket Server have a look similar scripts in the comments of these issues: https://jira.atlassian.com/browse/JRASERVER-68724?focusedCommentId=2394947&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-2394947 https://jira.atlassian.com/browse/BSERV-5533?focusedCommentId=2395934&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-2395934

            Hi Scott, Did you ever get to the solution with Bitbucket and JIRA?

            Richard Heasman added a comment - Hi Scott, Did you ever get to the solution with Bitbucket and JIRA?

            Scott Selberg added a comment - - edited

            I wrote my own because it was helpful - I'm presently digging thorough the documentation because we need it for JIRA and Bitbucket as well.

             

            Here's the java part of the code:

             

            {{}}

            package com.keysight.confluence.support.rest;

            import java.util.Map;
            import java.util.List;
            import javax.ws.rs.*;
            import javax.ws.rs.core.MediaType;
            import javax.ws.rs.core.Response;

            import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
            import com.atlassian.crowd.manager.directory.DirectoryManager;
            import com.atlassian.crowd.embedded.api.Directory;
            import com.atlassian.crowd.manager.directory.SynchronisationMode;

            @Path("/directory")
            public class ADRestService
            {
            private final DirectoryManager directoryManager;

            public ADRestService( DirectoryManager directoryManager)
            {
            this.directoryManager = directoryManager;
            }

            @GET
            @AnonymousAllowed
            @Path("sync")
            public Response syncAllDirectories( ){
            String response = "<p>Syncing</p>";

            List directories = directoryManager.findAllDirectories();
            for( Directory directory : directoryManager.findAllDirectories() ){
            try{
            if( directoryManager.isSynchronisable( directory.getId() )
            && !directoryManager.isSynchronising( directory.getId() )){
            directoryManager.synchroniseCache( directory.getId(), SynchronisationMode.INCREMENTAL );
            }
            } catch( Exception e ){
            // com.atlassian.crowd.exception.DirectoryInstantiationException
            // com.atlassian.crowd.exception.OperationFailedException
            }
            }

            return Response.ok( new RestResponse( response ) ).build();
            }
            }

             

            Scott Selberg added a comment - - edited I wrote my own because it was helpful - I'm presently digging thorough the documentation because we need it for JIRA and Bitbucket as well.   Here's the java part of the code:   {{}} package com.keysight.confluence.support.rest; import java.util.Map; import java.util.List; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.atlassian.plugins.rest.common.security.AnonymousAllowed; import com.atlassian.crowd.manager.directory.DirectoryManager; import com.atlassian.crowd.embedded.api.Directory; import com.atlassian.crowd.manager.directory.SynchronisationMode; @Path("/directory") public class ADRestService { private final DirectoryManager directoryManager; public ADRestService( DirectoryManager directoryManager) { this.directoryManager = directoryManager; } @GET @AnonymousAllowed @Path("sync") public Response syncAllDirectories( ){ String response = "<p>Syncing</p>"; List directories = directoryManager.findAllDirectories(); for( Directory directory : directoryManager.findAllDirectories() ){ try{ if( directoryManager.isSynchronisable( directory.getId() ) && !directoryManager.isSynchronising( directory.getId() )){ directoryManager.synchroniseCache( directory.getId(), SynchronisationMode.INCREMENTAL ); } } catch( Exception e ){ // com.atlassian.crowd.exception.DirectoryInstantiationException // com.atlassian.crowd.exception.OperationFailedException } } return Response.ok( new RestResponse( response ) ).build(); } }  

            It would be useful for a couple of our clients, especially during on boarding where otherwise they have to wait for a directory sync.

            Martin Cleaver added a comment - It would be useful for a couple of our clients, especially during on boarding where otherwise they have to wait for a directory sync.

            I can't say that a lot of customers have asked for it via support, but there have been several times where I have wished I could recommend it as an option to admins that aren't able to or don't want to decrease the interval, but want a way to easily have Confluence pull changes to group memberships (most of the time it's when they remove an employee from a permissible group and want the change effective immediately).

            I don't think it will make a noticeable impact on the number support requests, however.

            Adam Laskowski (Inactive) added a comment - I can't say that a lot of customers have asked for it via support, but there have been several times where I have wished I could recommend it as an option to admins that aren't able to or don't want to decrease the interval, but want a way to easily have Confluence pull changes to group memberships (most of the time it's when they remove an employee from a permissible group and want the change effective immediately). I don't think it will make a noticeable impact on the number support requests, however.

            BillA added a comment -

            Adam, are a lot of customers asking for this? Would it reduce support burden?

            BillA added a comment - Adam, are a lot of customers asking for this? Would it reduce support burden?

              Unassigned Unassigned
              alaskowski Adam Laskowski (Inactive)
              Votes:
              80 Vote for this issue
              Watchers:
              46 Start watching this issue

                Created:
                Updated: