Fabiano Fidêncio 8a7243b
From 7703a7efe1ed4800a7676cfaac9bd00fec7de1c4 Mon Sep 17 00:00:00 2001
Fabiano Fidêncio 8a7243b
From: Jakub Hrozek <jhrozek@redhat.com>
Fabiano Fidêncio 8a7243b
Date: Wed, 4 Apr 2018 14:13:56 +0200
Fabiano Fidêncio 8a7243b
Subject: [PATCH] FILES: Skip files that are not created yet
Fabiano Fidêncio 8a7243b
MIME-Version: 1.0
Fabiano Fidêncio 8a7243b
Content-Type: text/plain; charset=UTF-8
Fabiano Fidêncio 8a7243b
Content-Transfer-Encoding: 8bit
Fabiano Fidêncio 8a7243b
Fabiano Fidêncio 8a7243b
In order to avoid complex ordering logic, even if one file is updated,
Fabiano Fidêncio 8a7243b
we flush all the entries. In theory, we could only flush the individual
Fabiano Fidêncio 8a7243b
file and all the files preceding it, but it's safer to just create a
Fabiano Fidêncio 8a7243b
complete mirror every time.
Fabiano Fidêncio 8a7243b
Fabiano Fidêncio 8a7243b
And this can be problematic if one of the files we try to update is not
Fabiano Fidêncio 8a7243b
created yet during the update. This can happen e.g. when a file is not
Fabiano Fidêncio 8a7243b
created during early boot.
Fabiano Fidêncio 8a7243b
Fabiano Fidêncio 8a7243b
To solve this, try to be very defensive and always flush the whole
Fabiano Fidêncio 8a7243b
database, ignore ENOENT errors, but abort on all other errors.
Fabiano Fidêncio 8a7243b
Fabiano Fidêncio 8a7243b
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Fabiano Fidêncio 8a7243b
(cherry picked from commit c1bce7da6c33b352dc708a5dd9712a4d96c63057)
Fabiano Fidêncio 8a7243b
---
Fabiano Fidêncio 8a7243b
 src/providers/files/files_ops.c       | 22 ++++++++++---
Fabiano Fidêncio 8a7243b
 src/tests/intg/test_files_provider.py | 60 +++++++++++++++++++++++++++++++++++
Fabiano Fidêncio 8a7243b
 2 files changed, 78 insertions(+), 4 deletions(-)
Fabiano Fidêncio 8a7243b
Fabiano Fidêncio 8a7243b
diff --git a/src/providers/files/files_ops.c b/src/providers/files/files_ops.c
Fabiano Fidêncio 8a7243b
index b91078417..f5a40297a 100644
Fabiano Fidêncio 8a7243b
--- a/src/providers/files/files_ops.c
Fabiano Fidêncio 8a7243b
+++ b/src/providers/files/files_ops.c
Fabiano Fidêncio 8a7243b
@@ -734,8 +734,15 @@ static errno_t sf_enum_files(struct files_id_ctx *id_ctx,
Fabiano Fidêncio 8a7243b
         /* All users were deleted, therefore we need to enumerate each file again */
Fabiano Fidêncio 8a7243b
         for (size_t i = 0; id_ctx->passwd_files[i] != NULL; i++) {
Fabiano Fidêncio 8a7243b
             ret = sf_enum_users(id_ctx, id_ctx->passwd_files[i]);
Fabiano Fidêncio 8a7243b
-            if (ret != EOK) {
Fabiano Fidêncio 8a7243b
-                DEBUG(SSSDBG_OP_FAILURE, "Cannot enumerate users\n");
Fabiano Fidêncio 8a7243b
+            if (ret == ENOENT) {
Fabiano Fidêncio 8a7243b
+                DEBUG(SSSDBG_MINOR_FAILURE,
Fabiano Fidêncio 8a7243b
+                      "The file %s does not exist (yet), skipping\n",
Fabiano Fidêncio 8a7243b
+                      id_ctx->passwd_files[i]);
Fabiano Fidêncio 8a7243b
+                continue;
Fabiano Fidêncio 8a7243b
+            } else if (ret != EOK) {
Fabiano Fidêncio 8a7243b
+                DEBUG(SSSDBG_OP_FAILURE,
Fabiano Fidêncio 8a7243b
+                      "Cannot enumerate users from %s, aborting\n",
Fabiano Fidêncio 8a7243b
+                      id_ctx->passwd_files[i]);
Fabiano Fidêncio 8a7243b
                 goto done;
Fabiano Fidêncio 8a7243b
             }
Fabiano Fidêncio 8a7243b
         }
Fabiano Fidêncio 8a7243b
@@ -750,8 +757,15 @@ static errno_t sf_enum_files(struct files_id_ctx *id_ctx,
Fabiano Fidêncio 8a7243b
         /* All groups were deleted, therefore we need to enumerate each file again */
Fabiano Fidêncio 8a7243b
         for (size_t i = 0; id_ctx->group_files[i] != NULL; i++) {
Fabiano Fidêncio 8a7243b
             ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]);
Fabiano Fidêncio 8a7243b
-            if (ret != EOK) {
Fabiano Fidêncio 8a7243b
-                DEBUG(SSSDBG_OP_FAILURE, "Cannot enumerate groups\n");
Fabiano Fidêncio 8a7243b
+            if (ret == ENOENT) {
Fabiano Fidêncio 8a7243b
+                DEBUG(SSSDBG_MINOR_FAILURE,
Fabiano Fidêncio 8a7243b
+                      "The file %s does not exist (yet), skipping\n",
Fabiano Fidêncio 8a7243b
+                      id_ctx->group_files[i]);
Fabiano Fidêncio 8a7243b
+                continue;
Fabiano Fidêncio 8a7243b
+            } else if (ret != EOK) {
Fabiano Fidêncio 8a7243b
+                DEBUG(SSSDBG_OP_FAILURE,
Fabiano Fidêncio 8a7243b
+                      "Cannot enumerate groups from %s, aborting\n",
Fabiano Fidêncio 8a7243b
+                      id_ctx->group_files[i]);
Fabiano Fidêncio 8a7243b
                 goto done;
Fabiano Fidêncio 8a7243b
             }
Fabiano Fidêncio 8a7243b
         }
Fabiano Fidêncio 8a7243b
diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py
Fabiano Fidêncio 8a7243b
index ce5c7b774..cc9c1f1c7 100644
Fabiano Fidêncio 8a7243b
--- a/src/tests/intg/test_files_provider.py
Fabiano Fidêncio 8a7243b
+++ b/src/tests/intg/test_files_provider.py
Fabiano Fidêncio 8a7243b
@@ -187,6 +187,40 @@ def files_multiple_sources(request):
Fabiano Fidêncio 8a7243b
     return alt_pwops, alt_grops
Fabiano Fidêncio 8a7243b
 
Fabiano Fidêncio 8a7243b
 
Fabiano Fidêncio 8a7243b
+@pytest.fixture
Fabiano Fidêncio 8a7243b
+def files_multiple_sources_nocreate(request):
Fabiano Fidêncio 8a7243b
+    """
Fabiano Fidêncio 8a7243b
+    Sets up SSSD with multiple sources, but does not actually create
Fabiano Fidêncio 8a7243b
+    the files.
Fabiano Fidêncio 8a7243b
+    """
Fabiano Fidêncio 8a7243b
+    alt_passwd_path = tempfile.mktemp(prefix='altpasswd')
Fabiano Fidêncio 8a7243b
+    request.addfinalizer(lambda: os.unlink(alt_passwd_path))
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    alt_group_path = tempfile.mktemp(prefix='altgroup')
Fabiano Fidêncio 8a7243b
+    request.addfinalizer(lambda: os.unlink(alt_group_path))
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    passwd_list = ",".join([os.environ["NSS_WRAPPER_PASSWD"], alt_passwd_path])
Fabiano Fidêncio 8a7243b
+    group_list = ",".join([os.environ["NSS_WRAPPER_GROUP"], alt_group_path])
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    conf = unindent("""\
Fabiano Fidêncio 8a7243b
+        [sssd]
Fabiano Fidêncio 8a7243b
+        domains             = files
Fabiano Fidêncio 8a7243b
+        services            = nss
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+        [nss]
Fabiano Fidêncio 8a7243b
+        debug_level = 10
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+        [domain/files]
Fabiano Fidêncio 8a7243b
+        id_provider = files
Fabiano Fidêncio 8a7243b
+        passwd_files = {passwd_list}
Fabiano Fidêncio 8a7243b
+        group_files = {group_list}
Fabiano Fidêncio 8a7243b
+        debug_level = 10
Fabiano Fidêncio 8a7243b
+    """).format(**locals())
Fabiano Fidêncio 8a7243b
+    create_conf_fixture(request, conf)
Fabiano Fidêncio 8a7243b
+    create_sssd_fixture(request)
Fabiano Fidêncio 8a7243b
+    return alt_passwd_path, alt_group_path
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
 @pytest.fixture
Fabiano Fidêncio 8a7243b
 def proxy_to_files_domain_only(request):
Fabiano Fidêncio 8a7243b
     conf = unindent("""\
Fabiano Fidêncio 8a7243b
@@ -1113,3 +1147,29 @@ def test_multiple_passwd_group_files(add_user_with_canary,
Fabiano Fidêncio 8a7243b
 
Fabiano Fidêncio 8a7243b
     check_group(GROUP1)
Fabiano Fidêncio 8a7243b
     check_group(ALT_GROUP1)
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+def test_multiple_files_created_after_startup(add_user_with_canary,
Fabiano Fidêncio 8a7243b
+                                              add_group_with_canary,
Fabiano Fidêncio 8a7243b
+                                              files_multiple_sources_nocreate):
Fabiano Fidêncio 8a7243b
+    """
Fabiano Fidêncio 8a7243b
+    Test that users and groups can be mirrored from multiple files,
Fabiano Fidêncio 8a7243b
+    but those files are not created when SSSD starts, only afterwards.
Fabiano Fidêncio 8a7243b
+    """
Fabiano Fidêncio 8a7243b
+    alt_passwd_path, alt_group_path = files_multiple_sources_nocreate
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    check_user(USER1)
Fabiano Fidêncio 8a7243b
+    check_group(GROUP1)
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    # touch the files
Fabiano Fidêncio 8a7243b
+    for fpath in (alt_passwd_path, alt_group_path):
Fabiano Fidêncio 8a7243b
+        with open(fpath, "w") as f:
Fabiano Fidêncio 8a7243b
+            pass
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    alt_pwops = PasswdOps(alt_passwd_path)
Fabiano Fidêncio 8a7243b
+    alt_grops = GroupOps(alt_group_path)
Fabiano Fidêncio 8a7243b
+    alt_pwops.useradd(**ALT_USER1)
Fabiano Fidêncio 8a7243b
+    alt_grops.groupadd(**ALT_GROUP1)
Fabiano Fidêncio 8a7243b
+
Fabiano Fidêncio 8a7243b
+    check_user(ALT_USER1)
Fabiano Fidêncio 8a7243b
+    check_group(ALT_GROUP1)
Fabiano Fidêncio 8a7243b
-- 
Fabiano Fidêncio 8a7243b
2.14.3
Fabiano Fidêncio 8a7243b