From 4ccaadc6d84bb8b5581b15c6a1b39571f8044e48 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Mon, 6 Jun 2011 15:05:16 -0400
Subject: [PATCH 6/8] Add ipa_hbac_refresh option

This option describes the time between refreshes of the HBAC rules
on the IPA server.
---
 src/config/SSSDConfig.py                |    1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf |    1 +
 src/man/sssd-ipa.5.xml                  |   15 +++++++++++++++
 src/providers/ipa/ipa_access.c          |   18 ++++++++++++++++++
 src/providers/ipa/ipa_access.h          |    1 +
 src/providers/ipa/ipa_common.c          |    3 ++-
 src/providers/ipa/ipa_common.h          |    1 +
 7 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 5114a178a5e2be2f4b78c984cfec7e27de25e41b..21a4d16c396faf98d9972e452b4d046da4eb0372 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -97,6 +97,7 @@ option_strings = {
     'ipa_dyndns_update' : _("Whether to automatically update the client's DNS entry in FreeIPA"),
     'ipa_dyndns_iface' : _("The interface whose IP should be used for dynamic DNS updates"),
     'ipa_hbac_search_base' : _("Search base for HBAC related objects"),
+    'ipa_hbac_refresh' : _("The amount of time between lookups of the HBAC rules against the IPA server"),
 
     # [provider/krb5]
     'krb5_kdcip' : _('Kerberos server address'),
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 752222508ed2767d1ac1b6444f6385e322ffd2ce..b1ca5027be61934cb37cfff9238544c22fa3c928 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -102,6 +102,7 @@ krb5_renew_interval = int, None, false
 krb5_use_fast = str, None, false
 
 [provider/ipa/access]
+ipa_hbac_refresh = int, None, false
 
 [provider/ipa/chpass]
 
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index 4604c55e2259a6fb4bbcdd1384b6cfa46e9f3766..f728e9ccf86df3e8a4f0ad6bc93c161747ea27f0 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -175,6 +175,21 @@
                         </para>
                     </listitem>
                 </varlistentry>
+                <varlistentry>
+                    <term>ipa_hbac_refresh (integer)</term>
+                    <listitem>
+                        <para>
+                            The amount of time between lookups of the HBAC
+                            rules against the IPA server. This will reduce the
+                            latency and load on the IPA server if there are
+                            many access-control requests made in a short
+                            period.
+                        </para>
+                        <para>
+                            Default: 5 (seconds)
+                        </para>
+                    </listitem>
+                </varlistentry>
 
             </variablelist>
         </para>
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index 22076215fe3409697660904723cfeec72fd89464..db15835c9b01ac0b8d09f1e1811a3ed89e146f9b 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -145,10 +145,25 @@ static int hbac_retry(struct hbac_ctx *hbac_ctx)
     struct tevent_req *subreq;
     int ret;
     bool offline;
+    time_t now, refresh_interval;
+    struct be_ctx *be_ctx = hbac_ctx->be_req->be_ctx;
+    struct ipa_access_ctx *access_ctx =
+            talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
+                            struct ipa_access_ctx);
 
     offline = be_is_offline(hbac_ctx->be_req->be_ctx);
     DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online"));
 
+    refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options,
+                                      IPA_HBAC_REFRESH);
+
+    now = time(NULL);
+    if (now < access_ctx->last_update + refresh_interval) {
+        /* Simulate offline mode and just go to the cache */
+        DEBUG(6, ("Performing cached HBAC evaluation\n"));
+        offline = true;
+    }
+
     if (!offline) {
         if (hbac_ctx->sdap_op == NULL) {
             hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx,
@@ -496,6 +511,9 @@ static void hbac_sysdb_save(struct tevent_req *req)
      */
     hbac_clear_rule_data(hbac_ctx);
 
+
+    access_ctx->last_update = time(NULL);
+
     /* Now evaluate the request against the rules */
     ipa_hbac_evaluate_rules(hbac_ctx);
 
diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h
index da43fea2b4cf5097b4c9616bc56f839feb030c13..c4edf5a02da84a59de97221197a4ee36876a3211 100644
--- a/src/providers/ipa/ipa_access.h
+++ b/src/providers/ipa/ipa_access.h
@@ -43,6 +43,7 @@ struct ipa_access_ctx {
     struct sdap_id_ctx *sdap_ctx;
     struct dp_option *ipa_options;
     struct time_rules_ctx *tr_ctx;
+    time_t last_update;
 };
 
 struct hbac_ctx {
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 9972c341133655d6c07659c08e4732cc43e7a957..0995e0f1a02fb3e985d821d1a7cc87c78b3dbb4d 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -37,7 +37,8 @@ struct dp_option ipa_basic_opts[] = {
     { "ipa_dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ipa_dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "ipa_hbac_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING},
-    { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING}
+    { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING},
+    { "ipa_hbac_refresh", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER }
 };
 
 struct dp_option ipa_def_ldap_opts[] = {
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 8f0f35a826aaf7063ac6bfa26f5b06d69019e9c4..1c1f722152de48a35d0ecbde2647a1df97d018cf 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -50,6 +50,7 @@ enum ipa_basic_opt {
     IPA_DYNDNS_IFACE,
     IPA_HBAC_SEARCH_BASE,
     IPA_KRB5_REALM,
+    IPA_HBAC_REFRESH,
 
     IPA_OPTS_BASIC /* opts counter */
 };
-- 
1.7.5.4

