[SSSD] [PATCH] AD: add entry_cache_gpo_timeout option
Yassir Elley
yelley at redhat.com
Wed Jul 30 12:39:56 UTC 2014
----- Original Message -----
> On Thu, Jul 24, 2014 at 06:53:24AM -0400, Yassir Elley wrote:
> > Hi,
> >
> > The attached patch adds support for an "entry_cache_gpo_timeout" option,
> > which allows an admin to specify how many seconds the backend should
> > consider locally stored gpo policy files to be valid before asking the
> > backend again. This is an additional performance enhancement (along with
> > comparing gpo versions to avoid unnecessary downloads). The timeout is set
> > when a gpo entry is stored in the cache (which only happens after policy
> > files have been downloaded).
> >
> > During the processing of a gpo, if the gpo's cache timeout has not elapsed,
> > the backend does not interact with the gpo_child at all (and therefore
> > doesn't download any files from the smb server). Rather, it re-uses the
> > policy files that are already stored locally. Obviously, no gpo version
> > comparisons need to be made in this case. If the timeout has elapsed (or
> > there is no gpo entry in the cache), then the backend does interact with
> > the gpo child in the usual manner (including comparing gpo versions to
> > avoid unnecessary downloads). Note that the entry_cache_gpo_timeout option
> > is *not* an expiration for the data in the gpo cache entry (which includes
> > the cached_gpt_version). Indeed, the cached_gpt_version is never
> > considered to be "expired".
> >
> > Note that this patch does not add support for offline mode, which will be
> > implemented in a subsequent patch.
> >
> > Regards,
> > Yassir.
>
> Hi,
>
> I was wondering if it's a good idea to introduce the option as a global
> one, present in sssd.conf or a sssd-ad option? See for instance
> ipa_hbac_refresh in man sssd-ipa, I think that's quite natural
> counterpart.
>
> Also, the default timeout is way too big, for access control, I think we
> should go with a lower timeout, the one used is for identity lookups
> only where we care more about speed than precision.
>
> Some more comments inline:
>
> > From 8aff4445df5cf42e09cd8b521cbd5ff4d6e1a666 Mon Sep 17 00:00:00 2001
> > From: Yassir Elley <yelley at redhat.com>
> > Date: Tue, 22 Jul 2014 14:19:35 -0400
> > Subject: [PATCH] AD-GPO: add entry_cache_gpo_timeout option
> >
> > ---
> > src/confdb/confdb.c | 11 ++
> > src/confdb/confdb.h | 2 +
> > src/config/SSSDConfig/__init__.py.in | 1 +
> > src/config/SSSDConfigTest.py | 2 +
> > src/config/etc/sssd.api.conf | 1 +
> > src/db/sysdb.h | 14 +-
> > src/db/sysdb_gpo.c | 46 +++++-
> > src/man/sssd.conf.5.xml | 13 ++
>
> [...]
>
> > @@ -1305,6 +1311,12 @@ ad_gpo_cse_step(struct tevent_req *req)
> > struct tevent_req *subreq;
> > struct ad_gpo_access_state *state;
> > int i = 0;
> > + struct ldb_result *res;
> > + errno_t ret;
> > + bool found_in_cache = false;
> > + bool send_to_child = true;
> > + int cached_gpt_version = 0;
> > + time_t policy_file_timeout = 0;
> >
> > state = tevent_req_data(req, struct ad_gpo_access_state);
> >
> > @@ -1327,14 +1339,69 @@ ad_gpo_cse_step(struct tevent_req *req)
> > DEBUG(SSSDBG_TRACE_FUNC, "smb_path: %s\n",
> > cse_filtered_gpo->smb_path);
> > DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n",
> > cse_filtered_gpo->gpo_guid);
> >
> > + /* retrieve gpo cache entry; set cached_gpt_version to -1 if
> > unavailable */
> > + DEBUG(SSSDBG_TRACE_FUNC, "retrieving GPO from cache [%s]\n",
> > + cse_filtered_gpo->gpo_guid);
> > + ret = sysdb_gpo_get_gpo_by_guid(state,
> > + state->domain,
> > + cse_filtered_gpo->gpo_guid,
> > + &res);
> > + if (ret == EOK) {
> > + found_in_cache = true;
> > + } else {
> > + switch (ret) {
> > + case ENOENT:
> > + DEBUG(SSSDBG_TRACE_FUNC, "ENOENT\n");
> > + cached_gpt_version = -1;
> > + break;
> > + default:
> > + DEBUG(SSSDBG_FATAL_FAILURE, "Could not read GPO from cache:
> > [%s]\n",
> > + strerror(ret));
> > + return ret;
> > + }
> > + }
>
> I think the above is too complex, what about:
>
> if (ret == EOK) {
> /*
> * Note: if the timeout is valid, then we can later avoid
> downloading
> * the GPT.INI file, as well as any policy files (i.e. we don't
> need
> * to interact with the gpo_child at all). However, even if the
> timeout
> * is not valid, while we will have to interact with the gpo child
> to
> * download the GPT.INI file, we may still be able to avoid
> downloading
> * the policy files (if the cached_gpt_version is the same as the
> * GPT.INI version). In other words, the timeout is *not* an
> expiration
> * for the entire cache entry; the cached_gpt_version never
> expires.
> _ */
> cached_gpt_version = ldb_msg_find_attr_as_int(res->msgs[0],
> SYSDB_GPO_VERSION_ATTR,
> 0);
>
> policy_file_timeout = ldb_msg_find_attr_as_uint64
> (res->msgs[0], SYSDB_GPO_TIMEOUT_ATTR, 0);
>
> if (policy_file_timeout >= time(NULL)) {
> send_to_child = false;
> }
> } else if (ret == ENOENT) {
> DEBUG(SSSDBG_TRACE_FUNC, "ENOENT\n");
> cached_gpt_version = -1;
> } else {
> DEBUG(SSSDBG_FATAL_FAILURE, "Could not read GPO from cache: [%s]\n",
> strerror(ret));
> return ret;
> }
>
> That way you don't need the found_in_cache variable at all.
>
> > +
> > + DEBUG(SSSDBG_TRACE_FUNC, "found_in_cache: %d\n", found_in_cache);
> > + if (found_in_cache) {
> > +
> > + /*
> > + * Note: if the timeout is valid, then we can later avoid
> > downloading
> > + * the GPT.INI file, as well as any policy files (i.e. we don't
> > need
> > + * to interact with the gpo_child at all). However, even if the
> > timeout
> > + * is not valid, while we will have to interact with the gpo child
> > to
> > + * download the GPT.INI file, we may still be able to avoid
> > downloading
> > + * the policy files (if the cached_gpt_version is the same as the
> > + * GPT.INI version). In other words, the timeout is *not* an
> > expiration
> > + * for the entire cache entry; the cached_gpt_version never
> > expires.
> > + */
> > +
> > + cached_gpt_version = ldb_msg_find_attr_as_int(res->msgs[0],
> > +
> > SYSDB_GPO_VERSION_ATTR,
> > + 0);
> > +
> > + policy_file_timeout = ldb_msg_find_attr_as_uint64
> > + (res->msgs[0], SYSDB_GPO_TIMEOUT_ATTR, 0);
> > +
> > + if (policy_file_timeout >= time(NULL)) {
> > + send_to_child = false;
> > + }
> > + }
> > +
> > + DEBUG(SSSDBG_TRACE_FUNC, "send_to_child: %d\n", send_to_child);
> > + DEBUG(SSSDBG_TRACE_FUNC, "cached_gpt_version: %d\n",
> > cached_gpt_version);
> > +
> > + cse_filtered_gpo->send_to_child = send_to_child;
> > +
> > subreq = ad_gpo_process_cse_send(state,
> > state->ev,
> > - state->domain,
> > + send_to_child,
> > + state->domain->name,
> > + cse_filtered_gpo->gpo_guid,
> > cse_filtered_gpo->smb_server,
> > cse_filtered_gpo->smb_share,
> > cse_filtered_gpo->smb_path,
> > GP_EXT_GUID_SECURITY_SUFFIX,
> > - cse_filtered_gpo->gpo_guid);
> > + cached_gpt_version);
> >
> > tevent_req_set_callback(subreq, ad_gpo_cse_done, req);
> > return EAGAIN;
> > @@ -1356,10 +1423,12 @@ ad_gpo_cse_done(struct tevent_req *subreq)
> > struct ad_gpo_access_state *state;
> > int ret;
> > int sysvol_gpt_version;
> > + const char *policy_filename = NULL;
> > char **allowed_sids;
> > int allowed_size;
> > char **denied_sids;
> > int denied_size;
> > + time_t now;
> >
> > req = tevent_req_callback_data(subreq, struct tevent_req);
> > state = tevent_req_data(req, struct ad_gpo_access_state);
> > @@ -1372,8 +1441,7 @@ ad_gpo_cse_done(struct tevent_req *subreq)
> > DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n", gpo_guid);
> >
> > ret = ad_gpo_process_cse_recv(subreq, state, &sysvol_gpt_version,
> > - &allowed_size, &allowed_sids,
> > - &denied_size, &denied_sids);
> > + &policy_filename);
> >
> > talloc_zfree(subreq);
> >
> > @@ -1383,17 +1451,35 @@ ad_gpo_cse_done(struct tevent_req *subreq)
> > goto done;
> > }
> >
> > - DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n",
> > sysvol_gpt_version);
> > + /* only store to cache (and refresh timeout) if we interacted with
> > child */
> > + if (cse_filtered_gpo->send_to_child) {
> >
> > - ret = sysdb_gpo_store_gpo(state->domain, gpo_guid,
> > sysvol_gpt_version);
> > + DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n",
> > sysvol_gpt_version);
> > +
> > + now = time(NULL);
> > + ret = sysdb_gpo_store_gpo(state->domain, gpo_guid,
> > sysvol_gpt_version,
> > + state->domain->gpo_timeout, now);
> > + if (ret != EOK) {
> > + DEBUG(SSSDBG_OP_FAILURE, "Unable to store gpo cache entry:
> > [%d](%s}\n",
> > + ret, sss_strerror(ret));
> > + goto done;
> > + }
> > + }
>
> What about moving the above to the ad_gpo_process_cse* request? That way
> you could always store the GPO data after the child has finished and could
> avoid branching in the caller.
>
> The rest looks good to me and the patches seem to work fine.
I agree with all your comments and have attached a revised patch. With regard to the timeout option, I have changed this to be an sssd-ad option. I have changed the name to ad_gpo_cache_timeout and have modelled it after ipa_hbac_refresh (including the 5 second default timeout).
Regards,
Yassir.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-AD-GPO-add-ad_gpo_cache_timeout-option.patch
Type: text/x-patch
Size: 28734 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20140730/6b9fb641/attachment.bin>
More information about the sssd-devel
mailing list