URL: https://github.com/SSSD/sssd/pull/485 Author: justin-stephenson Title: #485: Support alternative sources for the files provider Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/485/head:pr485 git checkout pr485
From 11449444b049ff4c4633b924cba9b78643193983 Mon Sep 17 00:00:00 2001 From: Justin Stephenson <[email protected]> Date: Fri, 14 Jul 2017 16:08:37 -0400 Subject: [PATCH 1/3] CONFDB: Add passwd_files and group_files options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new options to the files provider allowing an administrator to configure the files provider to read and monitor multiple or non-standard passwd and group file sources. These options default to /etc/passwd and /etc/group when unset. Reviewed-by: Pavel Březina <[email protected]> Reviewed-by: Jakub Hrozek <[email protected]> --- Makefile.am | 3 ++- src/confdb/confdb.h | 4 ++++ src/config/SSSDConfig/__init__.py.in | 6 +++++- src/config/cfg_rules.ini | 4 ++++ src/config/etc/sssd.api.d/sssd-files.conf | 3 +++ src/man/sssd-files.5.xml | 36 +++++++++++++++++++++++++++++-- src/providers/files/files_init.c | 1 + 7 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/config/etc/sssd.api.d/sssd-files.conf diff --git a/Makefile.am b/Makefile.am index e1bc4aecb..9c65aede4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4575,7 +4575,8 @@ dist_sssdapiplugin_DATA = \ src/config/etc/sssd.api.d/sssd-ldap.conf \ src/config/etc/sssd.api.d/sssd-local.conf \ src/config/etc/sssd.api.d/sssd-proxy.conf \ - src/config/etc/sssd.api.d/sssd-simple.conf + src/config/etc/sssd.api.d/sssd-simple.conf \ + src/config/etc/sssd.api.d/sssd-files.conf edit_cmd = $(SED) \ -e 's|@sbindir[@]|$(sbindir)|g' \ diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index c97a9b804..1d322aaac 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -242,6 +242,10 @@ #define CONFDB_PROXY_FAST_ALIAS "proxy_fast_alias" #define CONFDB_PROXY_MAX_CHILDREN "proxy_max_children" +/* Files Provider */ +#define CONFDB_FILES_PASSWD "passwd_files" +#define CONFDB_FILES_GROUP "group_files" + /* Secrets Service */ #define CONFDB_SEC_CONF_ENTRY "config/secrets" #define CONFDB_SEC_CONTAINERS_NEST_LEVEL "containers_nest_level" diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 857d56cb5..32b74e4c7 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -473,7 +473,11 @@ option_strings = { 'proxy_fast_alias' : _('Whether to look up canonical group name from cache if possible'), # [provider/proxy/auth] - 'proxy_pam_target' : _('PAM stack to use') + 'proxy_pam_target' : _('PAM stack to use'), + + # [provider/files] + 'passwd_files' : _('Path of passwd file sources.'), + 'group_files' : _('Path of group file sources.') } def striplist(l): diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 4e70bf7b6..551322780 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -404,6 +404,10 @@ option = dyndns_force_tcp option = dyndns_auth option = dyndns_server +# files provider specific options +option = passwd_files +option = group_files + # local provider specific options option = create_homedir option = remove_homedir diff --git a/src/config/etc/sssd.api.d/sssd-files.conf b/src/config/etc/sssd.api.d/sssd-files.conf new file mode 100644 index 000000000..2444d4924 --- /dev/null +++ b/src/config/etc/sssd.api.d/sssd-files.conf @@ -0,0 +1,3 @@ +[provider/files] +passwd_files = str, None, false +group_files = str, None, false diff --git a/src/man/sssd-files.5.xml b/src/man/sssd-files.5.xml index d44fffc03..59e1b6523 100644 --- a/src/man/sssd-files.5.xml +++ b/src/man/sssd-files.5.xml @@ -56,14 +56,46 @@ <refsect1 id='configuration-options'> <title>CONFIGURATION OPTIONS</title> <para> - The files provider has no specific options of its own, however, - generic SSSD domain options can be set where applicable. + In addition to the options listed below, generic SSSD domain options + can be set where applicable. Refer to the section <quote>DOMAIN SECTIONS</quote> of the <citerefentry> <refentrytitle>sssd.conf</refentrytitle> <manvolnum>5</manvolnum> </citerefentry> manual page for details on the configuration of an SSSD domain. + <variablelist> + <varlistentry> + <term>passwd_files (string)</term> + <listitem> + <para> + Comma-separated list of one or multiple password + filenames to be read and enumerated by the files + provider, inotify monitor watches will be set on + each file to detect changes dynamically. + </para> + <para> + Default: /etc/passwd + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>group_files (string)</term> + <listitem> + <para> + Comma-separated list of one or multiple group + filenames to be read and enumerated by the files + provider, inotify monitor watches will be set on + each file to detect changes dynamically. + </para> + <para> + Default: /etc/group + </para> + </listitem> + </varlistentry> + + </variablelist> </para> </refsect1> diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c index 8e5cd4cf9..b8a051c34 100644 --- a/src/providers/files/files_init.c +++ b/src/providers/files/files_init.c @@ -21,6 +21,7 @@ #include "providers/data_provider/dp.h" #include "providers/files/files_private.h" +#include "util/util.h" int sssm_files_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, From 8bf784bb73160d114669fadbdab3d66a5c04cd71 Mon Sep 17 00:00:00 2001 From: Justin Stephenson <[email protected]> Date: Mon, 17 Jul 2017 15:01:36 -0400 Subject: [PATCH 2/3] FILES: Handle files provider sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setup watches on passwd and group files provided with the files provider options passwd_files and group_files lists Resolves: https://pagure.io/SSSD/sssd/issue/3402 Reviewed-by: Pavel Březina <[email protected]> Reviewed-by: Jakub Hrozek <[email protected]> --- src/providers/files/files_init.c | 161 +++++++++++++++++--- src/providers/files/files_ops.c | 285 ++++++++++++++++++++++-------------- src/providers/files/files_private.h | 8 +- 3 files changed, 327 insertions(+), 127 deletions(-) diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c index b8a051c34..746c04af1 100644 --- a/src/providers/files/files_init.c +++ b/src/providers/files/files_init.c @@ -23,6 +23,138 @@ #include "providers/files/files_private.h" #include "util/util.h" +#define DEFAULT_PASSWD_FILE "/etc/passwd" +#define DEFAULT_GROUP_FILE "/etc/group" + +static errno_t files_init_file_sources(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + const char ***_passwd_files, + const char ***_group_files) +{ + TALLOC_CTX *tmp_ctx = NULL; + char *conf_passwd_files; + char *conf_group_files; + char **passwd_list = NULL; + char **group_list = NULL; + int num_passwd_files = 0; + int num_group_files = 0; + const char **passwd_files = NULL; + const char **group_files = NULL; + const char *dfl_passwd_files = NULL; + const char *env_group_files = NULL; + int i; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + dfl_passwd_files = getenv("SSS_FILES_PASSWD"); + if (dfl_passwd_files) { + sss_log(SSS_LOG_ALERT, + "Defaulting to %s for the passwd file, " + "this should only be used for testing!\n", + dfl_passwd_files); + } else { + dfl_passwd_files = DEFAULT_PASSWD_FILE; + } + DEBUG(SSSDBG_TRACE_FUNC, + "Using default passwd file: [%s].\n", dfl_passwd_files); + + env_group_files = getenv("SSS_FILES_GROUP"); + if (env_group_files) { + sss_log(SSS_LOG_ALERT, + "Defaulting to %s for the group file, " + "this should only be used for testing!\n", + env_group_files); + } else { + env_group_files = DEFAULT_GROUP_FILE; + } + DEBUG(SSSDBG_TRACE_FUNC, + "Using default group file: [%s].\n", DEFAULT_GROUP_FILE); + + ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path, + CONFDB_FILES_PASSWD, dfl_passwd_files, + &conf_passwd_files); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to retrieve confdb passwd files!\n"); + goto done; + } + + ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path, + CONFDB_FILES_GROUP, env_group_files, + &conf_group_files); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to retrieve confdb group files!\n"); + goto done; + } + + ret = split_on_separator(tmp_ctx, conf_passwd_files, ',', true, true, + &passwd_list, &num_passwd_files); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse passwd list!\n"); + goto done; + } + + passwd_files = talloc_zero_array(tmp_ctx, const char *, + num_passwd_files + 1); + if (passwd_files == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); + ret = ENOMEM; + goto done; + } + + for (i = 0; i < num_passwd_files; i++) { + DEBUG(SSSDBG_TRACE_FUNC, + "Using passwd file: [%s].\n", passwd_list[i]); + + passwd_files[i] = talloc_strdup(passwd_files, passwd_list[i]); + if (passwd_files[i] == NULL) { + ret = ENOMEM; + goto done; + } + } + + /* Retrieve list of group files */ + ret = split_on_separator(tmp_ctx, conf_group_files, ',', true, true, + &group_list, &num_group_files); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse group files!\n"); + goto done; + } + + group_files = talloc_zero_array(tmp_ctx, const char *, + num_group_files + 1); + if (group_files == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); + ret = ENOMEM; + goto done; + } + + for (i = 0; i < num_group_files; i++) { + DEBUG(SSSDBG_TRACE_FUNC, + "Using group file: [%s].\n", group_list[i]); + group_files[i] = talloc_strdup(group_files, group_list[i]); + if (group_files[i] == NULL) { + ret = ENOMEM; + goto done; + } + } + + *_passwd_files = talloc_steal(mem_ctx, passwd_files); + *_group_files = talloc_steal(mem_ctx, group_files); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + int sssm_files_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, @@ -30,32 +162,27 @@ int sssm_files_init(TALLOC_CTX *mem_ctx, void **_module_data) { struct files_id_ctx *ctx; - int ret; - const char *passwd_file = NULL; - const char *group_file = NULL; - - /* So far this is mostly useful for tests */ - passwd_file = getenv("SSS_FILES_PASSWD"); - if (passwd_file == NULL) { - passwd_file = "/etc/passwd"; - } - - group_file = getenv("SSS_FILES_GROUP"); - if (group_file == NULL) { - group_file = "/etc/group"; - } + errno_t ret; ctx = talloc_zero(mem_ctx, struct files_id_ctx); if (ctx == NULL) { return ENOMEM; } + ctx->be = be_ctx; ctx->domain = be_ctx->domain; - ctx->passwd_file = passwd_file; - ctx->group_file = group_file; + + ret = files_init_file_sources(ctx, be_ctx, + &ctx->passwd_files, + &ctx->group_files); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize the passwd/group source files\n"); + goto done; + } ctx->fctx = sf_init(ctx, be_ctx->ev, - ctx->passwd_file, ctx->group_file, + ctx->passwd_files, + ctx->group_files, ctx); if (ctx->fctx == NULL) { ret = ENOMEM; diff --git a/src/providers/files/files_ops.c b/src/providers/files/files_ops.c index b59a94252..a2a2798d3 100644 --- a/src/providers/files/files_ops.c +++ b/src/providers/files/files_ops.c @@ -44,6 +44,7 @@ struct files_ctx { static errno_t enum_files_users(TALLOC_CTX *mem_ctx, struct files_id_ctx *id_ctx, + const char *passwd_file, struct passwd ***_users) { errno_t ret, close_ret; @@ -53,12 +54,12 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx, FILE *pwd_handle = NULL; size_t n_users = 0; - pwd_handle = fopen(id_ctx->passwd_file, "r"); + pwd_handle = fopen(passwd_file, "r"); if (pwd_handle == NULL) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "Cannot open passwd file %s [%d]\n", - id_ctx->passwd_file, ret); + passwd_file, ret); goto done; } @@ -133,7 +134,7 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx, close_ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "Cannot close passwd file %s [%d]\n", - id_ctx->passwd_file, close_ret); + passwd_file, close_ret); } } return ret; @@ -141,6 +142,7 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx, static errno_t enum_files_groups(TALLOC_CTX *mem_ctx, struct files_id_ctx *id_ctx, + const char *group_file, struct group ***_groups) { errno_t ret, close_ret; @@ -150,12 +152,12 @@ static errno_t enum_files_groups(TALLOC_CTX *mem_ctx, size_t n_groups = 0; FILE *grp_handle = NULL; - grp_handle = fopen(id_ctx->group_file, "r"); + grp_handle = fopen(group_file, "r"); if (grp_handle == NULL) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "Cannot open group file %s [%d]\n", - id_ctx->group_file, ret); + group_file, ret); goto done; } @@ -237,7 +239,7 @@ static errno_t enum_files_groups(TALLOC_CTX *mem_ctx, close_ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "Cannot close group file %s [%d]\n", - id_ctx->group_file, close_ret); + group_file, close_ret); } } return ret; @@ -446,35 +448,23 @@ static errno_t refresh_override_attrs(struct files_id_ctx *id_ctx, return ret; } -static errno_t sf_enum_groups(struct files_id_ctx *id_ctx); +static errno_t sf_enum_groups(struct files_id_ctx *id_ctx, + const char *group_file); -errno_t sf_enum_users(struct files_id_ctx *id_ctx) +errno_t sf_enum_users(struct files_id_ctx *id_ctx, + const char *passwd_file) { errno_t ret; - errno_t tret; TALLOC_CTX *tmp_ctx = NULL; struct passwd **users = NULL; - bool in_transaction = false; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } - ret = enum_files_users(tmp_ctx, id_ctx, &users); - if (ret != EOK) { - goto done; - } - - ret = sysdb_transaction_start(id_ctx->domain->sysdb); - if (ret != EOK) { - goto done; - } - in_transaction = true; - - /* remove previous cache contents */ - /* FIXME - this is terribly inefficient */ - ret = delete_all_users(id_ctx->domain); + ret = enum_files_users(tmp_ctx, id_ctx, passwd_file, + &users); if (ret != EOK) { goto done; } @@ -496,31 +486,8 @@ errno_t sf_enum_users(struct files_id_ctx *id_ctx) "override values might not be available.\n"); } - ret = sysdb_transaction_commit(id_ctx->domain->sysdb); - if (ret != EOK) { - goto done; - } - in_transaction = false; - - /* Covers the case when someone edits /etc/group, adds a group member and - * only then edits passwd and adds the user. The reverse is not needed, - * because member/memberof links are established when groups are saved. - */ - ret = sf_enum_groups(id_ctx); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Cannot refresh groups\n"); - goto done; - } - ret = EOK; done: - if (in_transaction) { - tret = sysdb_transaction_cancel(id_ctx->domain->sysdb); - if (tret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Cannot cancel transaction: %d\n", ret); - } - } talloc_free(tmp_ctx); return ret; } @@ -698,13 +665,12 @@ static errno_t save_file_group(struct files_id_ctx *id_ctx, return ret; } -static errno_t sf_enum_groups(struct files_id_ctx *id_ctx) +static errno_t sf_enum_groups(struct files_id_ctx *id_ctx, + const char *group_file) { errno_t ret; - errno_t tret; TALLOC_CTX *tmp_ctx = NULL; struct group **groups = NULL; - bool in_transaction = false; const char **cached_users = NULL; tmp_ctx = talloc_new(NULL); @@ -712,7 +678,8 @@ static errno_t sf_enum_groups(struct files_id_ctx *id_ctx) return ENOMEM; } - ret = enum_files_groups(tmp_ctx, id_ctx, &groups); + ret = enum_files_groups(tmp_ctx, id_ctx, group_file, + &groups); if (ret != EOK) { goto done; } @@ -722,18 +689,6 @@ static errno_t sf_enum_groups(struct files_id_ctx *id_ctx) goto done; } - ret = sysdb_transaction_start(id_ctx->domain->sysdb); - if (ret != EOK) { - goto done; - } - in_transaction = true; - - /* remove previous cache contents */ - ret = delete_all_groups(id_ctx->domain); - if (ret != EOK) { - goto done; - } - for (size_t i = 0; groups[i]; i++) { ret = save_file_group(id_ctx, groups[i], cached_users); if (ret != EOK) { @@ -750,21 +705,8 @@ static errno_t sf_enum_groups(struct files_id_ctx *id_ctx) "override values might not be available.\n"); } - ret = sysdb_transaction_commit(id_ctx->domain->sysdb); - if (ret != EOK) { - goto done; - } - in_transaction = false; - ret = EOK; done: - if (in_transaction) { - tret = sysdb_transaction_cancel(id_ctx->domain->sysdb); - if (tret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Cannot cancel transaction: %d\n", ret); - } - } talloc_free(tmp_ctx); return ret; } @@ -783,21 +725,17 @@ static int sf_passwd_cb(const char *filename, uint32_t flags, void *pvt) { struct files_id_ctx *id_ctx; errno_t ret; + errno_t tret; + bool in_transaction = false; id_ctx = talloc_get_type(pvt, struct files_id_ctx); if (id_ctx == NULL) { - return EINVAL; + ret = EINVAL; + goto done; } DEBUG(SSSDBG_TRACE_FUNC, "passwd notification\n"); - if (strcmp(filename, id_ctx->passwd_file) != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Wrong file, expected %s, got %s\n", - id_ctx->passwd_file, filename); - return EINVAL; - } - id_ctx->updating_passwd = true; dp_sbus_domain_inconsistent(id_ctx->be->provider, id_ctx->domain); @@ -805,11 +743,64 @@ static int sf_passwd_cb(const char *filename, uint32_t flags, void *pvt) dp_sbus_reset_users_memcache(id_ctx->be->provider); dp_sbus_reset_initgr_memcache(id_ctx->be->provider); - ret = sf_enum_users(id_ctx); + ret = sysdb_transaction_start(id_ctx->domain->sysdb); + if (ret != EOK) { + goto done; + } + in_transaction = true; + + ret = delete_all_users(id_ctx->domain); + if (ret != EOK) { + goto done; + } + + /* All users were deleted, therefore we need to enumerate each file again */ + for (size_t i = 0; id_ctx->passwd_files[i] != NULL; i++) { + ret = sf_enum_users(id_ctx, id_ctx->passwd_files[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot enumerate users\n"); + goto done; + } + } + + /* Covers the case when someone edits /etc/group, adds a group member and + * only then edits passwd and adds the user. The reverse is not needed, + * because member/memberof links are established when groups are saved. + */ + ret = delete_all_groups(id_ctx->domain); + if (ret != EOK) { + goto done; + } + + /* All groups were deleted, therefore we need to enumerate each file again */ + for (size_t i = 0; id_ctx->group_files[i] != NULL; i++) { + ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot enumerate groups\n"); + goto done; + } + } + + ret = sysdb_transaction_commit(id_ctx->domain->sysdb); + if (ret != EOK) { + goto done; + } + in_transaction = false; id_ctx->updating_passwd = false; sf_cb_done(id_ctx); files_account_info_finished(id_ctx, BE_REQ_USER, ret); + + ret = EOK; +done: + if (in_transaction) { + tret = sysdb_transaction_cancel(id_ctx->domain->sysdb); + if (tret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot cancel transaction: %d\n", ret); + } + } + return ret; } @@ -817,21 +808,17 @@ static int sf_group_cb(const char *filename, uint32_t flags, void *pvt) { struct files_id_ctx *id_ctx; errno_t ret; + errno_t tret; + bool in_transaction = false; id_ctx = talloc_get_type(pvt, struct files_id_ctx); if (id_ctx == NULL) { - return EINVAL; + ret = EINVAL; + goto done; } DEBUG(SSSDBG_TRACE_FUNC, "group notification\n"); - if (strcmp(filename, id_ctx->group_file) != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Wrong file, expected %s, got %s\n", - id_ctx->group_file, filename); - return EINVAL; - } - id_ctx->updating_groups = true; dp_sbus_domain_inconsistent(id_ctx->be->provider, id_ctx->domain); @@ -839,11 +826,47 @@ static int sf_group_cb(const char *filename, uint32_t flags, void *pvt) dp_sbus_reset_groups_memcache(id_ctx->be->provider); dp_sbus_reset_initgr_memcache(id_ctx->be->provider); - ret = sf_enum_groups(id_ctx); + ret = sysdb_transaction_start(id_ctx->domain->sysdb); + if (ret != EOK) { + goto done; + } + in_transaction = true; + + ret = delete_all_groups(id_ctx->domain); + if (ret != EOK) { + goto done; + } + + /* All groups were deleted, therefore we need to enumerate each file again */ + for (size_t i = 0; id_ctx->group_files[i] != NULL; i++) { + ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot enumerate groups\n"); + goto done; + } + } + + ret = sysdb_transaction_commit(id_ctx->domain->sysdb); + if (ret != EOK) { + goto done; + } + in_transaction = false; id_ctx->updating_groups = false; sf_cb_done(id_ctx); files_account_info_finished(id_ctx, BE_REQ_GROUP, ret); + + ret = EOK; + +done: + if (in_transaction) { + tret = sysdb_transaction_cancel(id_ctx->domain->sysdb); + if (tret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot cancel transaction: %d\n", ret); + } + } + return ret; } @@ -853,19 +876,62 @@ static void startup_enum_files(struct tevent_context *ev, { struct files_id_ctx *id_ctx = talloc_get_type(pvt, struct files_id_ctx); errno_t ret; + errno_t tret; + bool in_transaction = false; talloc_zfree(imm); - ret = sf_enum_users(id_ctx); + ret = sysdb_transaction_start(id_ctx->domain->sysdb); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Enumerating users failed, data might be inconsistent!\n"); + goto done; } + in_transaction = true; - ret = sf_enum_groups(id_ctx); + ret = delete_all_users(id_ctx->domain); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Enumerating groups failed, data might be inconsistent!\n"); + goto done; + } + + ret = delete_all_groups(id_ctx->domain); + if (ret != EOK) { + goto done; + } + + for (size_t i = 0; id_ctx->passwd_files[i] != NULL; i++) { + DEBUG(SSSDBG_TRACE_FUNC, + "Startup user enumeration of [%s]\n", id_ctx->passwd_files[i]); + ret = sf_enum_users(id_ctx, id_ctx->passwd_files[i]); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Enumerating users failed, data might be inconsistent!\n"); + goto done; + } + } + + for (size_t i = 0; id_ctx->group_files[i] != NULL; i++) { + DEBUG(SSSDBG_TRACE_FUNC, + "Startup group enumeration of [%s]\n", id_ctx->group_files[i]); + ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Enumerating groups failed, data might be inconsistent!\n"); + goto done; + } + } + + ret = sysdb_transaction_commit(id_ctx->domain->sysdb); + if (ret != EOK) { + goto done; + } + in_transaction = false; + +done: + if (in_transaction) { + tret = sysdb_transaction_cancel(id_ctx->domain->sysdb); + if (tret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot cancel transaction: %d\n", ret); + } } } @@ -884,22 +950,29 @@ static struct snotify_ctx *sf_setup_watch(TALLOC_CTX *mem_ctx, struct files_ctx *sf_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - const char *passwd_file, - const char *group_file, + const char **passwd_files, + const char **group_files, struct files_id_ctx *id_ctx) { struct files_ctx *fctx; struct tevent_immediate *imm; + int i; fctx = talloc(mem_ctx, struct files_ctx); if (fctx == NULL) { return NULL; } - fctx->pwd_watch = sf_setup_watch(fctx, ev, passwd_file, - sf_passwd_cb, id_ctx); - fctx->grp_watch = sf_setup_watch(fctx, ev, group_file, - sf_group_cb, id_ctx); + for (i = 0; passwd_files[i]; i++) { + fctx->pwd_watch = sf_setup_watch(fctx, ev, passwd_files[i], + sf_passwd_cb, id_ctx); + } + + for (i = 0; group_files[i]; i++) { + fctx->grp_watch = sf_setup_watch(fctx, ev, group_files[i], + sf_group_cb, id_ctx); + } + if (fctx->pwd_watch == NULL || fctx->grp_watch == NULL) { talloc_free(fctx); return NULL; diff --git a/src/providers/files/files_private.h b/src/providers/files/files_private.h index a7d195c90..f44e6d458 100644 --- a/src/providers/files/files_private.h +++ b/src/providers/files/files_private.h @@ -39,8 +39,8 @@ struct files_id_ctx { struct sss_domain_info *domain; struct files_ctx *fctx; - const char *passwd_file; - const char *group_file; + const char **passwd_files; + const char **group_files; bool updating_passwd; bool updating_groups; @@ -53,8 +53,8 @@ struct files_id_ctx { /* files_ops.c */ struct files_ctx *sf_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - const char *passwd_file, - const char *group_file, + const char **passwd_files, + const char **group_files, struct files_id_ctx *id_ctx); /* files_id.c */ From 10f072959df28180349471408067e2fece8303be Mon Sep 17 00:00:00 2001 From: Jakub Hrozek <[email protected]> Date: Mon, 26 Mar 2018 17:30:14 +0200 Subject: [PATCH 3/3] Tests: Add a test for the multiple files feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an integration test for the new feature. Reviewed-by: Pavel Březina <[email protected]> --- src/tests/intg/test_files_provider.py | 61 ++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py index 41bfd8844..ce5c7b774 100644 --- a/src/tests/intg/test_files_provider.py +++ b/src/tests/intg/test_files_provider.py @@ -25,6 +25,7 @@ import pwd import grp import pytest +import tempfile import ent import sssd_id @@ -33,7 +34,7 @@ call_sssd_enumeration, call_sssd_getpwuid) from sssd_group import call_sssd_getgrnam, call_sssd_getgrgid -from files_ops import passwd_ops_setup, group_ops_setup +from files_ops import passwd_ops_setup, group_ops_setup, PasswdOps, GroupOps from util import unindent # Sync this with files_ops.c @@ -59,6 +60,11 @@ dir='/home/ov/user1', shell='/bin/ov_user1_shell') +ALT_USER1 = dict(name='altuser1', passwd='x', uid=60001, gid=70001, + gecos='User for tests from alt files', + dir='/home/altuser1', + shell='/bin/bash') + CANARY_GR = dict(name='canary', gid=300001, mem=[]) @@ -79,6 +85,10 @@ gid=40000, mem=[]) +ALT_GROUP1 = dict(name='alt_group1', + gid=80001, + mem=['alt_user1']) + def start_sssd(): """Start sssd and add teardown for stopping it and removing state""" @@ -145,6 +155,38 @@ def files_domain_only(request): return None [email protected] +def files_multiple_sources(request): + _, alt_passwd_path = tempfile.mkstemp(prefix='altpasswd') + request.addfinalizer(lambda: os.unlink(alt_passwd_path)) + alt_pwops = PasswdOps(alt_passwd_path) + + _, alt_group_path = tempfile.mkstemp(prefix='altgroup') + request.addfinalizer(lambda: os.unlink(alt_group_path)) + alt_grops = GroupOps(alt_group_path) + + passwd_list = ",".join([os.environ["NSS_WRAPPER_PASSWD"], alt_passwd_path]) + group_list = ",".join([os.environ["NSS_WRAPPER_GROUP"], alt_group_path]) + + conf = unindent("""\ + [sssd] + domains = files + services = nss + + [nss] + debug_level = 10 + + [domain/files] + id_provider = files + passwd_files = {passwd_list} + group_files = {group_list} + debug_level = 10 + """).format(**locals()) + create_conf_fixture(request, conf) + create_sssd_fixture(request) + return alt_pwops, alt_grops + + @pytest.fixture def proxy_to_files_domain_only(request): conf = unindent("""\ @@ -1054,3 +1096,20 @@ def test_no_sssd_conf(add_user_with_canary, no_sssd_conf): res, user = sssd_getpwnam_sync(USER1["name"]) assert res == NssReturnCode.SUCCESS assert user == USER1 + + +def test_multiple_passwd_group_files(add_user_with_canary, + add_group_with_canary, + files_multiple_sources): + """ + Test that users and groups can be mirrored from multiple files + """ + alt_pwops, alt_grops = files_multiple_sources + alt_pwops.useradd(**ALT_USER1) + alt_grops.groupadd(**ALT_GROUP1) + + check_user(USER1) + check_user(ALT_USER1) + + check_group(GROUP1) + check_group(ALT_GROUP1)
_______________________________________________ sssd-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
