URL: https://github.com/SSSD/sssd/pull/5610
Author: pbrezina
 Title: #5610: sudo improvements
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5610/head:pr5610
git checkout pr5610
From 7c44a3b034e6866248c5f135f4083535996eca29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Mon, 26 Apr 2021 12:43:30 +0200
Subject: [PATCH 1/5] man: document how to disable sudo smart and full refresh

Resolves: https://github.com/SSSD/sssd/issues/5601
---
 src/man/sssd-ldap.5.xml | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 0977a8dc2d..3550e140c6 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1531,6 +1531,11 @@ ldap_access_filter = (employeeType=admin)
                             <emphasis>ldap_sudo_smart_refresh_interval
                             </emphasis>
                         </para>
+                        <para>
+                            You can disable full refresh by setting this option
+                            to 0. However, either smart or full refresh must
+                            be enabled.
+                        </para>
                         <para>
                             Default: 21600 (6 hours)
                         </para>
@@ -1561,6 +1566,11 @@ ldap_access_filter = (employeeType=admin)
                             (by default every 15 minutes, see
                             <emphasis>ldap_connection_expire_timeout</emphasis>).
                         </para>
+                        <para>
+                            You can disable smart refresh by setting this option
+                            to 0. However, either smart or full refresh must
+                            be enabled.
+                        </para>
                         <para>
                             Default: 900 (15 minutes)
                         </para>

From 4bd7194eabd7f6fffc85d6a2689e99e4036727fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Mon, 26 Apr 2021 13:20:57 +0200
Subject: [PATCH 2/5] man: document how to tune sudo performance

Resolves: https://github.com/SSSD/sssd/issues/5603
---
 src/man/sssd-sudo.5.xml | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/man/sssd-sudo.5.xml b/src/man/sssd-sudo.5.xml
index 5bc56c4633..3dc5b77876 100644
--- a/src/man/sssd-sudo.5.xml
+++ b/src/man/sssd-sudo.5.xml
@@ -209,6 +209,36 @@ ldap_sudo_search_base = ou=sudoers,dc=example,dc=com
         </para>
     </refsect1>
 
+    <refsect1 id='performance'>
+        <title>Tuning the performance</title>
+        <para>
+            SSSD uses different kinds of mechanisms with more or less complex
+            LDAP filters to keep the cached sudo rules up to date. The default
+            configuration is set to values that should satisfy most of our
+            users, but the following paragraps contains few tips on how to fine
+            tune the configuration to your requirements.
+        </para>
+        <para>
+            1. <emphasis>Index LDAP attributes</emphasis>. Make sure that
+            following LDAP attributes are indexed: objectClass, cn, entryUSN or
+            modifyTimestamp.
+        </para>
+        <para>
+            2. <emphasis>Set ldap_sudo_search_base</emphasis>. Set the search
+            base to the container that holds the sudo rules to limit the scope
+            of the lookup.
+        </para>
+        <para>
+            3. <emphasis>Set full and smart refresh interval</emphasis>. If your
+            sudo rules do not change often and you do not require quick update
+            of cached rules on your clients, you may consider increasing the
+            <emphasis>ldap_sudo_full_refresh_interval</emphasis> and
+            <emphasis>ldap_sudo_smart_refresh_interval</emphasis>. You may also
+            consider disabling the smart refresh by setting
+            <emphasis>ldap_sudo_smart_refresh_interval = 0</emphasis>.
+        </para>
+    </refsect1>
+
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; href="include/seealso.xml" />
 
 </refentry>

From 2e72149e7d4fb74ca1f86258b63dc508f54e4bec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Mon, 26 Apr 2021 13:49:04 +0200
Subject: [PATCH 3/5] be: add be_ptask_postpone

This will cancel the next event and schedule it to now + period.
---
 src/providers/be_ptask.c         | 15 +++++++++++++++
 src/providers/be_ptask.h         |  1 +
 src/tests/cmocka/test_be_ptask.c | 27 +++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)

diff --git a/src/providers/be_ptask.c b/src/providers/be_ptask.c
index fab9e21b80..5bc9c3f791 100644
--- a/src/providers/be_ptask.c
+++ b/src/providers/be_ptask.c
@@ -417,6 +417,21 @@ void be_ptask_disable(struct be_ptask *task)
     }
 }
 
+/* Cancel current timer and schedule new one. */
+void be_ptask_postpone(struct be_ptask *task)
+{
+    if (task == NULL) {
+        return;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: rescheduling task\n", task->name);
+    talloc_zfree(task->timer);
+    talloc_zfree(task->req);
+    task->period = task->orig_period;
+
+    be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW);
+}
+
 void be_ptask_destroy(struct be_ptask **task)
 {
     talloc_zfree(*task);
diff --git a/src/providers/be_ptask.h b/src/providers/be_ptask.h
index e011079d3f..bec7a2a11e 100644
--- a/src/providers/be_ptask.h
+++ b/src/providers/be_ptask.h
@@ -142,6 +142,7 @@ errno_t be_ptask_create_sync(TALLOC_CTX *mem_ctx,
 
 void be_ptask_enable(struct be_ptask *task);
 void be_ptask_disable(struct be_ptask *task);
+void be_ptask_postpone(struct be_ptask *task);
 void be_ptask_destroy(struct be_ptask **task);
 
 time_t be_ptask_get_period(struct be_ptask *task);
diff --git a/src/tests/cmocka/test_be_ptask.c b/src/tests/cmocka/test_be_ptask.c
index b30775306a..a968b332b9 100644
--- a/src/tests/cmocka/test_be_ptask.c
+++ b/src/tests/cmocka/test_be_ptask.c
@@ -588,6 +588,32 @@ void test_be_ptask_enable_delay(void **state)
     assert_null(ptask);
 }
 
+void test_be_ptask_postpone(void **state)
+{
+    struct test_ctx *test_ctx = (struct test_ctx *)(*state);
+    struct be_ptask *ptask = NULL;
+    time_t now;
+    errno_t ret;
+
+    now = get_current_time();
+    ret = be_ptask_create(test_ctx, test_ctx->be_ctx, 30, 10, 0, 0, 0,
+                          0, test_be_ptask_send,
+                          test_be_ptask_recv, test_ctx, "Test ptask",
+                          BE_PTASK_OFFLINE_SKIP | BE_PTASK_SCHEDULE_FROM_LAST,
+                          &ptask);
+    assert_int_equal(ret, ERR_OK);
+    assert_non_null(ptask);
+    assert_non_null(ptask->timer);
+    assert_true(now + 10 <= ptask->next_execution);
+    assert_true(now + 30 > ptask->next_execution);
+
+    be_ptask_postpone(ptask);
+    assert_true(now + 30 <= ptask->next_execution);
+
+    be_ptask_destroy(&ptask);
+    assert_null(ptask);
+}
+
 void test_be_ptask_offline_skip(void **state)
 {
     struct test_ctx *test_ctx = (struct test_ctx *)(*state);
@@ -1108,6 +1134,7 @@ int main(int argc, const char *argv[])
         new_test(be_ptask_disable),
         new_test(be_ptask_enable),
         new_test(be_ptask_enable_delay),
+        new_test(be_ptask_postpone),
         new_test(be_ptask_offline_skip),
         new_test(be_ptask_offline_disable),
         new_test(be_ptask_offline_execute),

From c556e2543148792e05f435d25458f5309be74838 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Mon, 26 Apr 2021 15:48:24 +0200
Subject: [PATCH 4/5] sudo: reschedule periodic tasks when full refresh is
 finished

We postpone periodic full and smart refresh tasks when full refresh
(either per-request or periodic) is finished.

Resolves: https://github.com/SSSD/sssd/issues/5604

:feature: Completing a sudo full refresh now postpones the smart refresh
  by `ldap_sudo_smart_refresh_interval` value. This ensure that the smart
  refresh is not run too soon after a successful full refresh.
---
 src/providers/ipa/ipa_sudo.c           | 8 ++++++++
 src/providers/ipa/ipa_sudo.h           | 2 ++
 src/providers/ipa/ipa_sudo_refresh.c   | 7 ++++++-
 src/providers/ldap/sdap_sudo.c         | 8 ++++++++
 src/providers/ldap/sdap_sudo.h         | 2 ++
 src/providers/ldap/sdap_sudo_refresh.c | 7 ++++++-
 src/providers/ldap/sdap_sudo_shared.c  | 8 +++++---
 src/providers/ldap/sdap_sudo_shared.h  | 4 +++-
 8 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/providers/ipa/ipa_sudo.c b/src/providers/ipa/ipa_sudo.c
index 1b881d0855..78b56efc4f 100644
--- a/src/providers/ipa/ipa_sudo.c
+++ b/src/providers/ipa/ipa_sudo.c
@@ -28,6 +28,7 @@
 struct ipa_sudo_handler_state {
     uint32_t type;
     struct dp_reply_std reply;
+    struct ipa_sudo_ctx *sudo_ctx;
 };
 
 static void ipa_sudo_handler_done(struct tevent_req *subreq);
@@ -50,6 +51,7 @@ ipa_sudo_handler_send(TALLOC_CTX *mem_ctx,
     }
 
     state->type = data->type;
+    state->sudo_ctx = sudo_ctx;
 
     switch (data->type) {
     case BE_REQ_SUDO_FULL:
@@ -102,6 +104,12 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq)
     case BE_REQ_SUDO_FULL:
         ret = ipa_sudo_full_refresh_recv(subreq, &dp_error);
         talloc_zfree(subreq);
+
+        /* Postpone the periodic task since the refresh was just finished
+         * per user request. */
+        if (ret == EOK && dp_error == DP_ERR_OK) {
+            be_ptask_postpone(state->sudo_ctx->full_refresh);
+        }
         break;
     case BE_REQ_SUDO_RULES:
         ret = ipa_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
diff --git a/src/providers/ipa/ipa_sudo.h b/src/providers/ipa/ipa_sudo.h
index 9a2c5dfd65..026fc290d9 100644
--- a/src/providers/ipa/ipa_sudo.h
+++ b/src/providers/ipa/ipa_sudo.h
@@ -27,6 +27,8 @@ struct ipa_sudo_ctx {
     struct sdap_id_ctx *id_ctx;
     struct ipa_options *ipa_opts;
     struct sdap_options *sdap_opts;
+    struct be_ptask *full_refresh;
+    struct be_ptask *smart_refresh;
 
     /* sudo */
     struct sdap_attr_map *sudocmdgroup_map;
diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c
index 0a21960b34..60a47bda85 100644
--- a/src/providers/ipa/ipa_sudo_refresh.c
+++ b/src/providers/ipa/ipa_sudo_refresh.c
@@ -119,6 +119,9 @@ ipa_sudo_full_refresh_done(struct tevent_req *subreq)
         return;
     }
 
+    /* We just finished full request, we can postpone smart refresh. */
+    be_ptask_postpone(state->sudo_ctx->smart_refresh);
+
     tevent_req_done(req);
 }
 
@@ -456,5 +459,7 @@ ipa_sudo_ptask_setup(struct be_ctx *be_ctx, struct ipa_sudo_ctx *sudo_ctx)
                                          ipa_sudo_ptask_full_refresh_recv,
                                          ipa_sudo_ptask_smart_refresh_send,
                                          ipa_sudo_ptask_smart_refresh_recv,
-                                         sudo_ctx);
+                                         sudo_ctx,
+                                         &sudo_ctx->full_refresh,
+                                         &sudo_ctx->smart_refresh);
 }
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index 26e8e014d3..3bbf9b885e 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -32,6 +32,7 @@
 struct sdap_sudo_handler_state {
     uint32_t type;
     struct dp_reply_std reply;
+    struct sdap_sudo_ctx *sudo_ctx;
 };
 
 static void sdap_sudo_handler_done(struct tevent_req *subreq);
@@ -54,6 +55,7 @@ sdap_sudo_handler_send(TALLOC_CTX *mem_ctx,
     }
 
     state->type = data->type;
+    state->sudo_ctx = sudo_ctx;
 
     switch (data->type) {
     case BE_REQ_SUDO_FULL:
@@ -105,6 +107,12 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq)
     case BE_REQ_SUDO_FULL:
         ret = sdap_sudo_full_refresh_recv(subreq, &dp_error);
         talloc_zfree(subreq);
+
+        /* Reschedule the periodic task since the refresh was just finished
+         * per user request. */
+        if (ret == EOK && dp_error == DP_ERR_OK) {
+            be_ptask_postpone(state->sudo_ctx->full_refresh);
+        }
         break;
     case BE_REQ_SUDO_RULES:
         ret = sdap_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h
index d001f895bd..85eeccf268 100644
--- a/src/providers/ldap/sdap_sudo.h
+++ b/src/providers/ldap/sdap_sudo.h
@@ -26,6 +26,8 @@
 
 struct sdap_sudo_ctx {
     struct sdap_id_ctx *id_ctx;
+    struct be_ptask *full_refresh;
+    struct be_ptask *smart_refresh;
 
     char **hostnames;
     char **ip_addr;
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
index 83f944ccfb..4a3ade54d0 100644
--- a/src/providers/ldap/sdap_sudo_refresh.c
+++ b/src/providers/ldap/sdap_sudo_refresh.c
@@ -134,6 +134,9 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
         return;
     }
 
+    /* We just finished full request, we can postpone smart refresh. */
+    be_ptask_postpone(state->sudo_ctx->smart_refresh);
+
     tevent_req_done(req);
 }
 
@@ -471,5 +474,7 @@ sdap_sudo_ptask_setup(struct be_ctx *be_ctx, struct sdap_sudo_ctx *sudo_ctx)
                                          sdap_sudo_ptask_full_refresh_recv,
                                          sdap_sudo_ptask_smart_refresh_send,
                                          sdap_sudo_ptask_smart_refresh_recv,
-                                         sudo_ctx);
+                                         sudo_ctx,
+                                         &sudo_ctx->full_refresh,
+                                         &sudo_ctx->smart_refresh);
 }
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
index 75d1bc3d85..526304e730 100644
--- a/src/providers/ldap/sdap_sudo_shared.c
+++ b/src/providers/ldap/sdap_sudo_shared.c
@@ -35,7 +35,9 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
                               be_ptask_recv_t full_recv_fn,
                               be_ptask_send_t smart_send_fn,
                               be_ptask_recv_t smart_recv_fn,
-                              void *pvt)
+                              void *pvt,
+                              struct be_ptask **_full_refresh,
+                              struct be_ptask **_smart_refresh)
 {
     time_t smart;
     time_t full;
@@ -95,7 +97,7 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
                               "SUDO Full Refresh",
                               BE_PTASK_OFFLINE_DISABLE |
                               BE_PTASK_SCHEDULE_FROM_LAST,
-                              NULL);
+                              _full_refresh);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup full refresh ptask "
                   "[%d]: %s\n", ret, sss_strerror(ret));
@@ -115,7 +117,7 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
                               "SUDO Smart Refresh",
                               BE_PTASK_OFFLINE_DISABLE |
                               BE_PTASK_SCHEDULE_FROM_LAST,
-                              NULL);
+                              _smart_refresh);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup smart refresh ptask "
                   "[%d]: %s\n", ret, sss_strerror(ret));
diff --git a/src/providers/ldap/sdap_sudo_shared.h b/src/providers/ldap/sdap_sudo_shared.h
index dd49a67566..846f3f8d88 100644
--- a/src/providers/ldap/sdap_sudo_shared.h
+++ b/src/providers/ldap/sdap_sudo_shared.h
@@ -31,7 +31,9 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
                               be_ptask_recv_t full_recv_fn,
                               be_ptask_send_t smart_send_fn,
                               be_ptask_recv_t smart_recv_fn,
-                              void *pvt);
+                              void *pvt,
+                              struct be_ptask **_full_refresh,
+                              struct be_ptask **_smart_refresh);
 
 void
 sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,

From 3973e3f231dbe4c344ded9d4fdbf3effd3ae32be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Tue, 27 Apr 2021 13:11:06 +0200
Subject: [PATCH 5/5] sudo: add ldap_sudo_random_offset

Resolves: https://github.com/SSSD/sssd/issues/5609

:feature: Backround sudo periodic tasks (smart and full refresh) periods
  are now extended by a random offset to spread the load on the server in
  environments with many clients. The random offset can be changed with
  `ldap_sudo_random_offset`.

:config: Added `ldap_sudo_random_offset` (default to `30`) to add a
  random offset to backround sudo periodic tasks (smart and full
  refresh).
---
 src/config/SSSDConfig/sssdoptions.py     |  1 +
 src/config/cfg_rules.ini                 |  1 +
 src/config/etc/sssd.api.d/sssd-ad.conf   |  1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf  |  1 +
 src/config/etc/sssd.api.d/sssd-ldap.conf |  1 +
 src/man/sssd-ldap.5.xml                  | 19 +++++++++++++++++++
 src/man/sssd-sudo.5.xml                  |  5 +++++
 src/providers/ad/ad_opts.c               |  1 +
 src/providers/ipa/ipa_opts.c             |  1 +
 src/providers/ldap/ldap_opts.c           |  1 +
 src/providers/ldap/sdap.h                |  1 +
 src/providers/ldap/sdap_sudo_shared.c    |  9 +++++----
 src/tests/intg/test_sudo.py              |  1 +
 src/tests/multihost/basic/conftest.py    |  1 +
 14 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py
index 696857c1d9..c4ce2588bd 100644
--- a/src/config/SSSDConfig/sssdoptions.py
+++ b/src/config/SSSDConfig/sssdoptions.py
@@ -515,6 +515,7 @@ def __init__(self):
         'ldap_sudo_search_base': _('Base DN for sudo rules lookups'),
         'ldap_sudo_full_refresh_interval': _('Automatic full refresh period'),
         'ldap_sudo_smart_refresh_interval': _('Automatic smart refresh period'),
+        'ldap_sudo_random_offset': _('Smart and full refresh random offset'),
         'ldap_sudo_use_host_filter': _('Whether to filter rules by hostname, IP addresses and network'),
         'ldap_sudo_hostnames': _('Hostnames and/or fully qualified domain names of this machine to filter sudo rules'),
         'ldap_sudo_ip': _('IPv4 or IPv6 addresses or network of this machine to filter sudo rules'),
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index 149b4d78ef..226c7d0a8e 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -754,6 +754,7 @@ option = ldap_sudorule_runasuser
 option = ldap_sudorule_user
 option = ldap_sudo_search_base
 option = ldap_sudo_smart_refresh_interval
+option = ldap_sudo_random_offset
 option = ldap_sudo_use_host_filter
 option = ldap_tls_cacertdir
 option = ldap_tls_cacert
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 962c7ae696..41b1a8546e 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -167,6 +167,7 @@ krb5_backup_kpasswd = str, None, false
 ldap_sudo_search_base = str, None, false
 ldap_sudo_full_refresh_interval = int, None, false
 ldap_sudo_smart_refresh_interval = int, None, false
+ldap_sudo_random_offset = int, None, false
 ldap_sudo_use_host_filter = bool, None, false
 ldap_sudo_hostnames = str, None, false
 ldap_sudo_ip = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index b79d1a3afd..9a81389ca8 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -225,6 +225,7 @@ ipa_subdomains_search_base = str, None, false
 ldap_sudo_search_base = str, None, false
 ldap_sudo_full_refresh_interval = int, None, false
 ldap_sudo_smart_refresh_interval = int, None, false
+ldap_sudo_random_offset = int, None, false
 ldap_sudo_use_host_filter = bool, None, false
 ldap_sudo_hostnames = str, None, false
 ldap_sudo_ip = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 2600a20e79..1945d65524 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -150,6 +150,7 @@ ldap_chpass_update_last_change = bool, None, false
 ldap_sudo_search_base = str, None, false
 ldap_sudo_full_refresh_interval = int, None, false
 ldap_sudo_smart_refresh_interval = int, None, false
+ldap_sudo_random_offset = int, None, false
 ldap_sudo_use_host_filter = bool, None, false
 ldap_sudo_hostnames = str, None, false
 ldap_sudo_ip = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 3550e140c6..be0e9b5303 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1577,6 +1577,25 @@ ldap_access_filter = (employeeType=admin)
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>ldap_sudo_random_offset (integer)</term>
+                    <listitem>
+                        <para>
+                            Random offset between 0 and configured value is
+                            added to smart and full refresh periods each time
+                            the periodic task is scheduled. The value is in
+                            seconds.
+                        </para>
+                        <para>
+                            You can disable this offset by setting the value to
+                            0.
+                        </para>
+                        <para>
+                            Default: 30
+                        </para>
+                    </listitem>
+                </varlistentry>
+
                 <varlistentry>
                     <term>ldap_sudo_use_host_filter (boolean)</term>
                     <listitem>
diff --git a/src/man/sssd-sudo.5.xml b/src/man/sssd-sudo.5.xml
index 3dc5b77876..3ad89dde3c 100644
--- a/src/man/sssd-sudo.5.xml
+++ b/src/man/sssd-sudo.5.xml
@@ -237,6 +237,11 @@ ldap_sudo_search_base = ou=sudoers,dc=example,dc=com
             consider disabling the smart refresh by setting
             <emphasis>ldap_sudo_smart_refresh_interval = 0</emphasis>.
         </para>
+        <para>
+            4. If you have large number of clients, you may consider increasing
+            the value of <emphasis>ldap_sudo_random_offset</emphasis> to
+            distribute the load on the server better.
+        </para>
     </refsect1>
 
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; href="include/seealso.xml" />
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index 7b069d6760..e7295567a0 100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -85,6 +85,7 @@ struct dp_option ad_def_ldap_opts[] = {
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER }, /* 360 mins */
     { "ldap_sudo_smart_refresh_interval", DP_OPT_NUMBER, { .number = 900 }, NULL_NUMBER }, /* 15 mins */
+    { "ldap_sudo_random_offset", DP_OPT_NUMBER, { .number = 30 }, NULL_NUMBER }, /* 30 seconds */
     { "ldap_sudo_use_host_filter", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ldap_sudo_hostnames", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_ip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
index 710bd2613e..90fd42c3d8 100644
--- a/src/providers/ipa/ipa_opts.c
+++ b/src/providers/ipa/ipa_opts.c
@@ -91,6 +91,7 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER },
     { "ldap_sudo_smart_refresh_interval", DP_OPT_NUMBER, { .number = 900 }, NULL_NUMBER }, /* 15 mins */
+    { "ldap_sudo_random_offset", DP_OPT_NUMBER, { .number = 30 }, NULL_NUMBER }, /* 30 seconds */
     { "ldap_sudo_use_host_filter", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ldap_sudo_hostnames", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_ip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c
index 3b8b4b53b7..c1209e5907 100644
--- a/src/providers/ldap/ldap_opts.c
+++ b/src/providers/ldap/ldap_opts.c
@@ -52,6 +52,7 @@ struct dp_option default_basic_opts[] = {
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER }, /* 360 mins */
     { "ldap_sudo_smart_refresh_interval", DP_OPT_NUMBER, { .number = 900 }, NULL_NUMBER }, /* 15 mins */
+    { "ldap_sudo_random_offset", DP_OPT_NUMBER, { .number = 30 }, NULL_NUMBER }, /* 30 seconds */
     { "ldap_sudo_use_host_filter", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ldap_sudo_hostnames", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_ip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index bcc65fd46c..f254b52c75 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -168,6 +168,7 @@ enum sdap_basic_opt {
     SDAP_SUDO_SEARCH_BASE,
     SDAP_SUDO_FULL_REFRESH_INTERVAL,
     SDAP_SUDO_SMART_REFRESH_INTERVAL,
+    SDAP_SUDO_RANDOM_OFFSET,
     SDAP_SUDO_USE_HOST_FILTER,
     SDAP_SUDO_HOSTNAMES,
     SDAP_SUDO_IP,
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
index 526304e730..2a6888c5b2 100644
--- a/src/providers/ldap/sdap_sudo_shared.c
+++ b/src/providers/ldap/sdap_sudo_shared.c
@@ -43,10 +43,12 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
     time_t full;
     time_t delay;
     time_t last_refresh;
+    time_t offset;
     errno_t ret;
 
     smart = dp_opt_get_int(opts, SDAP_SUDO_SMART_REFRESH_INTERVAL);
     full = dp_opt_get_int(opts, SDAP_SUDO_FULL_REFRESH_INTERVAL);
+    offset = dp_opt_get_int(opts, SDAP_SUDO_RANDOM_OFFSET);
 
     if (smart == 0 && full == 0) {
         /* We don't allow both types to be disabled. At least smart refresh
@@ -91,8 +93,7 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
      * Since we have periodical online check we don't have to run this task
      * when offline. */
     if (full > 0) {
-        ret = be_ptask_create(be_ctx, be_ctx, full, delay, 0, 0, full,
-                              0,
+        ret = be_ptask_create(be_ctx, be_ctx, full, delay, 0, offset, full, 0,
                               full_send_fn, full_recv_fn, pvt,
                               "SUDO Full Refresh",
                               BE_PTASK_OFFLINE_DISABLE |
@@ -111,8 +112,8 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
      * Since we have periodical online check we don't have to run this task
      * when offline. */
     if (smart > 0) {
-        ret = be_ptask_create(be_ctx, be_ctx, smart, delay + smart, smart, 0,
-                              smart,                              0,
+        ret = be_ptask_create(be_ctx, be_ctx, smart, delay + smart, smart,
+                              offset, smart, 0,
                               smart_send_fn, smart_recv_fn, pvt,
                               "SUDO Smart Refresh",
                               BE_PTASK_OFFLINE_DISABLE |
diff --git a/src/tests/intg/test_sudo.py b/src/tests/intg/test_sudo.py
index 7e8c232edc..9424e56666 100644
--- a/src/tests/intg/test_sudo.py
+++ b/src/tests/intg/test_sudo.py
@@ -134,6 +134,7 @@ def format_basic_conf(ldap_conn, schema):
         ldap_uri            = {ldap_conn.ds_inst.ldap_url}
         ldap_search_base    = {ldap_conn.ds_inst.base_dn}
         ldap_sudo_use_host_filter = false
+        ldap_sudo_random_offset = 0
         debug_level=10
     """).format(**locals())
 
diff --git a/src/tests/multihost/basic/conftest.py b/src/tests/multihost/basic/conftest.py
index 413d1d7b18..d9b639646c 100644
--- a/src/tests/multihost/basic/conftest.py
+++ b/src/tests/multihost/basic/conftest.py
@@ -121,6 +121,7 @@ def setup_sssd(session_multihost, request):
     sssdConfig.set(domain_section, 'krb5_kpasswd', krb5_server)
     sssdConfig.set(domain_section, 'krb5_realm', 'EXAMPLE.TEST')
     sssdConfig.set(domain_section, 'debug_level', '9')
+    sssdConfig.set(domain_section, 'ldap_sudo_random_offset', '0')
     sssdConfig.add_section('nss')
     sssdConfig.set('nss', 'debug_level', '9')
     sssdConfig.add_section('pam')
_______________________________________________
sssd-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/[email protected]
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to