dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone

Blame SOURCES/0062-CONFDB-Allow-configuring-application-sections-as-non.patch

bb7cd1
From 05ae58c86eae80c7e69fb809dc3cd89d0b7418f4 Mon Sep 17 00:00:00 2001
bb7cd1
From: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
Date: Mon, 27 Mar 2017 09:48:46 +0200
bb7cd1
Subject: [PATCH 62/72] CONFDB: Allow configuring [application] sections as
bb7cd1
 non-POSIX domains
bb7cd1
MIME-Version: 1.0
bb7cd1
Content-Type: text/plain; charset=UTF-8
bb7cd1
Content-Transfer-Encoding: 8bit
bb7cd1
bb7cd1
Related to:
bb7cd1
https://pagure.io/SSSD/sssd/issue/3310
bb7cd1
bb7cd1
Allows to add a new section:
bb7cd1
    [application/$name]
bb7cd1
bb7cd1
This section internally (on the confdb level) expands to:
bb7cd1
    [domain/$name]
bb7cd1
    domain_type = application
bb7cd1
bb7cd1
The reasons to add this new section is two-fold. One, to make the
bb7cd1
configuration of application domains more explicit and two, to make it
bb7cd1
possible to share configuration between two domains, one POSIX and one
bb7cd1
non-POSIX by application domain's inherit_from option:
bb7cd1
    [application/$name]
bb7cd1
    inherit_from = posix_domain_name
bb7cd1
bb7cd1
Reviewed-by: Sumit Bose <sbose@redhat.com>
bb7cd1
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
bb7cd1
---
bb7cd1
 src/confdb/confdb.c      | 288 ++++++++++++++++++++++++++++++++++++++++++++---
bb7cd1
 src/confdb/confdb.h      |   4 +
bb7cd1
 src/config/cfg_rules.ini |   9 +-
bb7cd1
 src/man/sssd.conf.5.xml  |  77 +++++++++++++
bb7cd1
 src/monitor/monitor.c    |   8 ++
bb7cd1
 5 files changed, 368 insertions(+), 18 deletions(-)
bb7cd1
bb7cd1
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
bb7cd1
index 70a1eb7b2c7e83dfa9d217a15c7d3d4c8580b891..88e114457deac3ca50c291a131122624fb6f6fe4 100644
bb7cd1
--- a/src/confdb/confdb.c
bb7cd1
+++ b/src/confdb/confdb.c
bb7cd1
@@ -813,6 +813,50 @@ done:
bb7cd1
     return ret;
bb7cd1
 }
bb7cd1
 
bb7cd1
+static int confdb_get_domain_section(TALLOC_CTX *mem_ctx,
bb7cd1
+                                     struct confdb_ctx *cdb,
bb7cd1
+                                     const char *section,
bb7cd1
+                                     const char *name,
bb7cd1
+                                     struct ldb_result **_res)
bb7cd1
+{
bb7cd1
+    TALLOC_CTX *tmp_ctx;
bb7cd1
+    int ret;
bb7cd1
+    struct ldb_result *res;
bb7cd1
+    struct ldb_dn *dn;
bb7cd1
+
bb7cd1
+    tmp_ctx = talloc_new(NULL);
bb7cd1
+    if (tmp_ctx == NULL) {
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", name, section);
bb7cd1
+    if (dn == NULL) {
bb7cd1
+        ret = ENOMEM;
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
bb7cd1
+                     LDB_SCOPE_BASE, NULL, NULL);
bb7cd1
+    if (ret != LDB_SUCCESS) {
bb7cd1
+        ret = sysdb_error_to_errno(ret);
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (res->count == 0) {
bb7cd1
+        ret = ENOENT;
bb7cd1
+        goto done;
bb7cd1
+    } else if (res->count > 1) {
bb7cd1
+        ret = E2BIG;
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    *_res = talloc_steal(mem_ctx, res);
bb7cd1
+    ret = EOK;
bb7cd1
+done:
bb7cd1
+    talloc_free(tmp_ctx);
bb7cd1
+    return ret;
bb7cd1
+}
bb7cd1
+
bb7cd1
 static int confdb_get_domain_internal(struct confdb_ctx *cdb,
bb7cd1
                                       TALLOC_CTX *mem_ctx,
bb7cd1
                                       const char *name,
bb7cd1
@@ -821,7 +865,6 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
bb7cd1
     struct sss_domain_info *domain;
bb7cd1
     struct ldb_result *res;
bb7cd1
     TALLOC_CTX *tmp_ctx;
bb7cd1
-    struct ldb_dn *dn;
bb7cd1
     const char *tmp;
bb7cd1
     int ret, val;
bb7cd1
     uint32_t entry_cache_timeout;
bb7cd1
@@ -833,23 +876,15 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
bb7cd1
     tmp_ctx = talloc_new(mem_ctx);
bb7cd1
     if (!tmp_ctx) return ENOMEM;
bb7cd1
 
bb7cd1
-    dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb,
bb7cd1
-                        "cn=%s,%s", name, CONFDB_DOMAIN_BASEDN);
bb7cd1
-    if (!dn) {
bb7cd1
-        ret = ENOMEM;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
bb7cd1
-                     LDB_SCOPE_BASE, NULL, NULL);
bb7cd1
-    if (ret != LDB_SUCCESS) {
bb7cd1
-        ret = EIO;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (res->count != 1) {
bb7cd1
+    ret = confdb_get_domain_section(tmp_ctx, cdb, CONFDB_DOMAIN_BASEDN,
bb7cd1
+                                    name, &res;;
bb7cd1
+    if (ret == ENOENT) {
bb7cd1
         DEBUG(SSSDBG_FATAL_FAILURE, "Unknown domain [%s]\n", name);
bb7cd1
-        ret = ENOENT;
bb7cd1
+        goto done;
bb7cd1
+    } else if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
+              "Error %d: %s while retrieving %s\n",
bb7cd1
+              ret, sss_strerror(ret), name);
bb7cd1
         goto done;
bb7cd1
     }
bb7cd1
 
bb7cd1
@@ -1841,3 +1876,222 @@ int confdb_ensure_files_domain(struct confdb_ctx *cdb,
bb7cd1
     return activate_files_domain(cdb, implicit_files_dom_name);
bb7cd1
 #endif /* ADD_FILES_DOMAIN */
bb7cd1
 }
bb7cd1
+
bb7cd1
+static int confdb_get_parent_domain(TALLOC_CTX *mem_ctx,
bb7cd1
+                                    const char *name,
bb7cd1
+                                    struct confdb_ctx *cdb,
bb7cd1
+                                    struct ldb_result *app_dom,
bb7cd1
+                                    struct ldb_result **_parent_dom)
bb7cd1
+{
bb7cd1
+    const char *inherit_from;
bb7cd1
+
bb7cd1
+    inherit_from = ldb_msg_find_attr_as_string(app_dom->msgs[0],
bb7cd1
+                                               CONFDB_DOMAIN_INHERIT_FROM, NULL);
bb7cd1
+    if (inherit_from == NULL) {
bb7cd1
+        DEBUG(SSSDBG_CONF_SETTINGS,
bb7cd1
+              "%s does not inherit from any POSIX domain\n", name);
bb7cd1
+        *_parent_dom = NULL;
bb7cd1
+        return EOK;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    return confdb_get_domain_section(mem_ctx, cdb,
bb7cd1
+                                     CONFDB_DOMAIN_BASEDN, inherit_from,
bb7cd1
+                                     _parent_dom);
bb7cd1
+}
bb7cd1
+
bb7cd1
+static int confdb_add_app_domain(TALLOC_CTX *mem_ctx,
bb7cd1
+                                 struct confdb_ctx *cdb,
bb7cd1
+                                 const char *name)
bb7cd1
+{
bb7cd1
+    char *cdb_path = NULL;
bb7cd1
+    const char *val[2] = { NULL, NULL };
bb7cd1
+    int ret;
bb7cd1
+
bb7cd1
+    cdb_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
bb7cd1
+    if (cdb_path == NULL) {
bb7cd1
+    return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    val[0] = CONFDB_DOMAIN_TYPE_APP;
bb7cd1
+    ret = confdb_add_param(cdb, true, cdb_path, CONFDB_DOMAIN_TYPE, val);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n",
bb7cd1
+              ret, sss_strerror(ret));
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static int confdb_merge_parent_domain(const char *name,
bb7cd1
+                                      struct confdb_ctx *cdb,
bb7cd1
+                                      struct ldb_result *app_section)
bb7cd1
+{
bb7cd1
+    int ret;
bb7cd1
+    int ldb_flag;
bb7cd1
+    struct ldb_result *parent_domain = NULL;
bb7cd1
+    struct ldb_message *replace_msg = NULL;
bb7cd1
+    struct ldb_message *app_msg = NULL;
bb7cd1
+    struct ldb_dn *domain_dn;
bb7cd1
+    TALLOC_CTX *tmp_ctx = NULL;
bb7cd1
+
bb7cd1
+    tmp_ctx = talloc_new(NULL);
bb7cd1
+    if (tmp_ctx == NULL) {
bb7cd1
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    domain_dn = ldb_dn_new_fmt(tmp_ctx,
bb7cd1
+                               cdb->ldb,
bb7cd1
+                               "%s=%s,%s",
bb7cd1
+                               CONFDB_DOMAIN_ATTR,
bb7cd1
+                               name,
bb7cd1
+                               CONFDB_DOMAIN_BASEDN);
bb7cd1
+    if (domain_dn == NULL) {
bb7cd1
+        ret = ENOMEM;
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    /* Copy the parent domain parameters */
bb7cd1
+    ret = confdb_get_parent_domain(tmp_ctx, name, cdb,
bb7cd1
+                                   app_section, &parent_domain);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+              "Cannot retrieve the parent domain [%d]: %s\n",
bb7cd1
+              ret, sss_strerror(ret));
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (parent_domain != NULL) {
bb7cd1
+        replace_msg = ldb_msg_copy(tmp_ctx, parent_domain->msgs[0]);
bb7cd1
+        if (replace_msg == NULL) {
bb7cd1
+            ret = ENOMEM;
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+        replace_msg->dn = domain_dn;
bb7cd1
+
bb7cd1
+        for (unsigned i = 0; i < replace_msg->num_elements; i++) {
bb7cd1
+            replace_msg->elements[i].flags = LDB_FLAG_MOD_ADD;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = ldb_modify(cdb->ldb, replace_msg);
bb7cd1
+        if (ret != LDB_SUCCESS) {
bb7cd1
+            ret = sysdb_error_to_errno(ret);
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                "Inheriting options from parent domain failed [%d]: %s\n",
bb7cd1
+                ret, sss_strerror(ret));
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    /* Finally, add any app-domain specific overrides */
bb7cd1
+    app_msg = ldb_msg_new(tmp_ctx);
bb7cd1
+    if (app_msg == NULL) {
bb7cd1
+        ret = ENOMEM;
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+    app_msg->dn = domain_dn;
bb7cd1
+
bb7cd1
+    for (unsigned i = 0; i < app_section->msgs[0]->num_elements; i++) {
bb7cd1
+        struct ldb_message_element *el = NULL;
bb7cd1
+
bb7cd1
+        if (replace_msg != NULL) {
bb7cd1
+            el = ldb_msg_find_element(replace_msg,
bb7cd1
+                                      app_section->msgs[0]->elements[i].name);
bb7cd1
+            if (el == NULL) {
bb7cd1
+                /* Adding an element */
bb7cd1
+                ldb_flag = LDB_FLAG_MOD_ADD;
bb7cd1
+            } else {
bb7cd1
+                /* Overriding an element */
bb7cd1
+                ldb_flag = LDB_FLAG_MOD_REPLACE;
bb7cd1
+            }
bb7cd1
+        } else {
bb7cd1
+            /* If there was no domain to inherit from, just add all */
bb7cd1
+            ldb_flag = LDB_FLAG_MOD_ADD;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = ldb_msg_add(app_msg,
bb7cd1
+                          &app_section->msgs[0]->elements[i],
bb7cd1
+                          ldb_flag);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            continue;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = ldb_modify(cdb->ldb, app_msg);
bb7cd1
+    if (ret != LDB_SUCCESS) {
bb7cd1
+        ret = sysdb_error_to_errno(ret);
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+              "Adding app-specific options failed [%d]: %s\n",
bb7cd1
+              ret, sss_strerror(ret));
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    DEBUG(SSSDBG_TRACE_LIBS, "Added a domain section for %s\n", name);
bb7cd1
+    ret = EOK;
bb7cd1
+done:
bb7cd1
+    talloc_free(tmp_ctx);
bb7cd1
+    return ret;
bb7cd1
+}
bb7cd1
+
bb7cd1
+int confdb_expand_app_domains(struct confdb_ctx *cdb)
bb7cd1
+{
bb7cd1
+    int ret;
bb7cd1
+    char **domlist;
bb7cd1
+    TALLOC_CTX *tmp_ctx;
bb7cd1
+    struct ldb_result *app_domain = NULL;
bb7cd1
+
bb7cd1
+    tmp_ctx = talloc_new(NULL);
bb7cd1
+    if (tmp_ctx == NULL) {
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = confdb_get_string_as_list(cdb, tmp_ctx,
bb7cd1
+                                    CONFDB_MONITOR_CONF_ENTRY,
bb7cd1
+                                    CONFDB_MONITOR_ACTIVE_DOMAINS,
bb7cd1
+                                    &domlist);
bb7cd1
+    if (ret == ENOENT) {
bb7cd1
+        DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured, fatal error!\n");
bb7cd1
+        goto done;
bb7cd1
+    } else if (ret != EOK ) {
bb7cd1
+        DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    for (int i = 0; domlist[i]; i++) {
bb7cd1
+        ret = confdb_get_domain_section(tmp_ctx, cdb,
bb7cd1
+                                        CONFDB_APP_DOMAIN_BASEDN, domlist[i],
bb7cd1
+                                        &app_domain);
bb7cd1
+        if (ret == ENOENT) {
bb7cd1
+            DEBUG(SSSDBG_TRACE_INTERNAL,
bb7cd1
+                  "%s is not an app domain\n", domlist[i]);
bb7cd1
+            continue;
bb7cd1
+        } else if (ret != EOK) {
bb7cd1
+            DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
+                  "Error %d: %s while retrieving %s\n",
bb7cd1
+                  ret, sss_strerror(ret), domlist[i]);
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = confdb_add_app_domain(tmp_ctx, cdb, domlist[i]);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                  "Cannot add the app domain section [%d]: %s\n",
bb7cd1
+                  ret, sss_strerror(ret));
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = confdb_merge_parent_domain(domlist[i], cdb, app_domain);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                  "Cannot add options into the app domain section [%d]: %s\n",
bb7cd1
+                  ret, sss_strerror(ret));
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = EOK;
bb7cd1
+done:
bb7cd1
+    talloc_free(tmp_ctx);
bb7cd1
+    return ret;
bb7cd1
+}
bb7cd1
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
bb7cd1
index a4046610f3cdbdb832de8924bf4397fb0018f2db..5a8d377c312f641f544b1c7cf38826192462ea3c 100644
bb7cd1
--- a/src/confdb/confdb.h
bb7cd1
+++ b/src/confdb/confdb.h
bb7cd1
@@ -164,6 +164,7 @@
bb7cd1
 /* Domains */
bb7cd1
 #define CONFDB_DOMAIN_PATH_TMPL "config/domain/%s"
bb7cd1
 #define CONFDB_DOMAIN_BASEDN "cn=domain,cn=config"
bb7cd1
+#define CONFDB_APP_DOMAIN_BASEDN "cn=application,cn=config"
bb7cd1
 #define CONFDB_DOMAIN_ID_PROVIDER "id_provider"
bb7cd1
 #define CONFDB_DOMAIN_AUTH_PROVIDER "auth_provider"
bb7cd1
 #define CONFDB_DOMAIN_ACCESS_PROVIDER "access_provider"
bb7cd1
@@ -212,6 +213,7 @@
bb7cd1
 #define CONFDB_DOMAIN_TYPE "domain_type"
bb7cd1
 #define CONFDB_DOMAIN_TYPE_POSIX "posix"
bb7cd1
 #define CONFDB_DOMAIN_TYPE_APP "application"
bb7cd1
+#define CONFDB_DOMAIN_INHERIT_FROM "inherit_from"
bb7cd1
 
bb7cd1
 /* Local Provider */
bb7cd1
 #define CONFDB_LOCAL_DEFAULT_SHELL   "default_shell"
bb7cd1
@@ -398,6 +400,8 @@ int confdb_get_domains(struct confdb_ctx *cdb,
bb7cd1
 int confdb_ensure_files_domain(struct confdb_ctx *cdb,
bb7cd1
                                const char *implicit_files_dom_name);
bb7cd1
 
bb7cd1
+int confdb_expand_app_domains(struct confdb_ctx *cdb);
bb7cd1
+
bb7cd1
 /**
bb7cd1
  * Get a null-terminated linked-list of all domain names
bb7cd1
  * @param[in] mem_ctx The parent memory context for the value list
bb7cd1
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
bb7cd1
index 3c857236eaa55b313d176bc4bb479918163b60d5..8fd2d2c5236246394353a88c50d1510bd6233f77 100644
bb7cd1
--- a/src/config/cfg_rules.ini
bb7cd1
+++ b/src/config/cfg_rules.ini
bb7cd1
@@ -12,6 +12,7 @@ section = secrets
bb7cd1
 section = kcm
bb7cd1
 section_re = ^secrets/users/[0-9]\+$
bb7cd1
 section_re = ^domain/.*$
bb7cd1
+section_re = ^application/.*$
bb7cd1
 
bb7cd1
 [rule/allowed_sssd_options]
bb7cd1
 validator = ini_allowed_options
bb7cd1
@@ -286,7 +287,7 @@ option = responder_idle_timeout
bb7cd1
 
bb7cd1
 [rule/allowed_domain_options]
bb7cd1
 validator = ini_allowed_options
bb7cd1
-section_re = ^domain/.*$
bb7cd1
+section_re = ^(domain|application)/.*$
bb7cd1
 
bb7cd1
 option = debug
bb7cd1
 option = debug_level
bb7cd1
@@ -684,3 +685,9 @@ option = ldap_user_ssh_public_key
bb7cd1
 option = ldap_user_uid_number
bb7cd1
 option = ldap_user_uuid
bb7cd1
 option = ldap_use_tokengroups
bb7cd1
+
bb7cd1
+[rule/allowed_application_options]
bb7cd1
+validator = ini_allowed_options
bb7cd1
+section_re = ^application/.*$
bb7cd1
+
bb7cd1
+option = inherit_from
bb7cd1
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
bb7cd1
index 9abcff84a95ea1b27e36845e830cc125fdc89f90..8294793c765bfa6bf481693c7d7f206950454681 100644
bb7cd1
--- a/src/man/sssd.conf.5.xml
bb7cd1
+++ b/src/man/sssd.conf.5.xml
bb7cd1
@@ -1539,6 +1539,10 @@ pam_account_locked_message = Account locked, please contact help desk.
bb7cd1
                             <quote>id_provider=ldap</quote> only.
bb7cd1
                         </para>
bb7cd1
                         <para>
bb7cd1
+                            For an easy way to configure a non-POSIX domains, please
bb7cd1
+                            see the <quote>Application domains</quote> section.
bb7cd1
+                        </para>
bb7cd1
+                        <para>
bb7cd1
                             Default: posix
bb7cd1
                         </para>
bb7cd1
                     </listitem>
bb7cd1
@@ -2692,6 +2696,79 @@ subdomain_inherit = ldap_purge_cache_timeout
bb7cd1
             </variablelist>
bb7cd1
         </para>
bb7cd1
 
bb7cd1
+        <refsect2 id='app_domains'>
bb7cd1
+            <title>Application domains</title>
bb7cd1
+            <para>
bb7cd1
+                SSSD, with its D-Bus interface (see
bb7cd1
+                <citerefentry>
bb7cd1
+                    <refentrytitle>sssd-ifp</refentrytitle>
bb7cd1
+                    <manvolnum>5</manvolnum>
bb7cd1
+                </citerefentry>) is appealing to applications
bb7cd1
+                as a gateway to an LDAP directory where users and groups
bb7cd1
+                are stored. However, contrary to the traditional SSSD
bb7cd1
+                deployment where all users and groups either have POSIX
bb7cd1
+                attributes or those attributes can be inferred from the
bb7cd1
+                Windows SIDs, in many cases the users and groups in the
bb7cd1
+                application support scenario have no POSIX attributes.
bb7cd1
+                Instead of setting a
bb7cd1
+                <quote>[domain/<replaceable>NAME</replaceable>]</quote>
bb7cd1
+                section, the administrator can set up an
bb7cd1
+                <quote>[application/<replaceable>NAME</replaceable>]</quote>
bb7cd1
+                section that internally represents a domain with type
bb7cd1
+                <quote>application</quote> optionally inherits settings
bb7cd1
+                from a tradition SSSD domain.
bb7cd1
+            </para>
bb7cd1
+            <para>
bb7cd1
+                Please note that the application domain must still be
bb7cd1
+                explicitly enabled in the <quote>domains</quote> parameter
bb7cd1
+                so that the lookup order between the application domain
bb7cd1
+                and its POSIX sibling domain is set correctly.
bb7cd1
+            </para>
bb7cd1
+            <variablelist>
bb7cd1
+                <title>Application domain parameters</title>
bb7cd1
+                <varlistentry>
bb7cd1
+                    <term>inherit_from (string)</term>
bb7cd1
+                    <listitem>
bb7cd1
+                        <para>
bb7cd1
+                            The SSSD POSIX-type domain the application
bb7cd1
+                            domain inherits all settings from. The
bb7cd1
+                            application domain can moreover add its own
bb7cd1
+                            settings to the application settings that augment
bb7cd1
+                            or override the <quote>sibling</quote>
bb7cd1
+                            domain settings.
bb7cd1
+                        </para>
bb7cd1
+                        <para>
bb7cd1
+                            Default: Not set
bb7cd1
+                        </para>
bb7cd1
+                    </listitem>
bb7cd1
+                </varlistentry>
bb7cd1
+            </variablelist>
bb7cd1
+            <para>
bb7cd1
+                The following example illustrates the use of an application
bb7cd1
+                domain. In this setup, the POSIX domain is connected to an LDAP
bb7cd1
+                server and is used by the OS through the NSS responder. In addition,
bb7cd1
+                the application domains also requests the telephoneNumber attribute,
bb7cd1
+                stores it as the phone attribute in the cache and makes the phone
bb7cd1
+                attribute reachable through the D-Bus interface.
bb7cd1
+            </para>
bb7cd1
+<programlisting>
bb7cd1
+[sssd]
bb7cd1
+domains = appdom, posixdom
bb7cd1
+
bb7cd1
+[ifp]
bb7cd1
+user_attributes = +phone
bb7cd1
+
bb7cd1
+[domain/posixdom]
bb7cd1
+id_provider = ldap
bb7cd1
+ldap_uri = ldap://ldap.example.com
bb7cd1
+ldap_search_base = dc=example,dc=com
bb7cd1
+
bb7cd1
+[application/appdom]
bb7cd1
+inherit_from = posixdom
bb7cd1
+ldap_user_extra_attrs = phone:telephoneNumber
bb7cd1
+</programlisting>
bb7cd1
+        </refsect2>
bb7cd1
+
bb7cd1
         <refsect2 id='local_domain'>
bb7cd1
             <title>The local domain section</title>
bb7cd1
             <para>
bb7cd1
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
bb7cd1
index 7e7b5a07d11aecf1c0b11592213b90d385fd5076..2753b46667f7ae0b022776862c67a327d3356d6d 100644
bb7cd1
--- a/src/monitor/monitor.c
bb7cd1
+++ b/src/monitor/monitor.c
bb7cd1
@@ -1064,6 +1064,14 @@ static int get_monitor_config(struct mt_ctx *ctx)
bb7cd1
         /* Not fatal */
bb7cd1
     }
bb7cd1
 
bb7cd1
+    ret = confdb_expand_app_domains(ctx->cdb);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to expand application domains\n");
bb7cd1
+        /* This must not be fatal so that SSSD keeps running and lets
bb7cd1
+         * admin correct the error.
bb7cd1
+         */
bb7cd1
+    }
bb7cd1
+
bb7cd1
     ret = confdb_get_domains(ctx->cdb, &ctx->domains);
bb7cd1
     if (ret != EOK) {
bb7cd1
         DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n");
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1