251 lines
8.7 KiB
Diff
251 lines
8.7 KiB
Diff
From b033b0dda972e885f63234aa81dca317c8234c2c Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
Date: Tue, 23 May 2023 12:21:44 +0200
|
|
Subject: [PATCH] ipa: correctly remove missing attributes on netgroup update
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
When a netgroup is updated, previously it did not remove the missing
|
|
attributes. This caused an issue especially when a member was removed.
|
|
|
|
Resolves: https://github.com/SSSD/sssd/issues/6652
|
|
|
|
Reviewed-by: Alejandro López <allopez@redhat.com>
|
|
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
|
|
|
|
Reference: https://github.com/SSSD/sssd/commit/b033b0dda972e885f63234aa81dca317c8234c2c
|
|
Conflict: NA
|
|
---
|
|
src/db/sysdb.c | 9 ++
|
|
src/db/sysdb.h | 1 +
|
|
src/providers/ipa/ipa_netgroups.c | 35 +++++++-
|
|
src/tests/system/tests/test_netgroups.py | 108 +++++++++++++++++++++++
|
|
4 files changed, 151 insertions(+), 2 deletions(-)
|
|
create mode 100644 src/tests/system/tests/test_netgroups.py
|
|
|
|
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
|
|
index 649e79fca..1faa11b16 100644
|
|
--- a/src/db/sysdb.c
|
|
+++ b/src/db/sysdb.c
|
|
@@ -523,6 +523,15 @@ static int sysdb_attrs_add_val_int(struct sysdb_attrs *attrs,
|
|
|
|
return EOK;
|
|
}
|
|
+
|
|
+int sysdb_attrs_add_empty(struct sysdb_attrs *attrs, const char *name)
|
|
+{
|
|
+ struct ldb_message_element *el;
|
|
+
|
|
+ /* Calling this will create the element if it does not exist. */
|
|
+ return sysdb_attrs_get_el_ext(attrs, name, true, &el);
|
|
+}
|
|
+
|
|
int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
|
|
const char *name, const struct ldb_val *val)
|
|
{
|
|
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
|
|
index 2f20692cc..887a9630e 100644
|
|
--- a/src/db/sysdb.h
|
|
+++ b/src/db/sysdb.h
|
|
@@ -398,6 +398,7 @@ enum sysdb_obj_type {
|
|
extern const char *sysdb_ts_cache_attrs[];
|
|
|
|
/* values are copied in the structure, allocated on "attrs" */
|
|
+int sysdb_attrs_add_empty(struct sysdb_attrs *attrs, const char *name);
|
|
int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
|
|
const char *name, const struct ldb_val *val);
|
|
int sysdb_attrs_add_val_safe(struct sysdb_attrs *attrs,
|
|
diff --git a/src/providers/ipa/ipa_netgroups.c b/src/providers/ipa/ipa_netgroups.c
|
|
index 52d90af4f..57f11a507 100644
|
|
--- a/src/providers/ipa/ipa_netgroups.c
|
|
+++ b/src/providers/ipa/ipa_netgroups.c
|
|
@@ -70,7 +70,10 @@ static errno_t ipa_save_netgroup(TALLOC_CTX *mem_ctx,
|
|
struct ldb_message_element *el;
|
|
struct sysdb_attrs *netgroup_attrs;
|
|
const char *name = NULL;
|
|
+ char **missing;
|
|
+ int missing_index;
|
|
int ret;
|
|
+ int i;
|
|
size_t c;
|
|
|
|
ret = sysdb_attrs_get_el(attrs,
|
|
@@ -90,6 +93,23 @@ static errno_t ipa_save_netgroup(TALLOC_CTX *mem_ctx,
|
|
goto fail;
|
|
}
|
|
|
|
+ missing = talloc_zero_array(netgroup_attrs, char *, attrs->num + 1);
|
|
+ if (missing == NULL) {
|
|
+ ret = ENOMEM;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ for (i = 0, missing_index = 0; i < attrs->num; i++) {
|
|
+ if (attrs->a[i].num_values == 0) {
|
|
+ missing[missing_index] = talloc_strdup(missing, attrs->a[i].name);
|
|
+ if (missing[missing_index] == NULL) {
|
|
+ ret = ENOMEM;
|
|
+ goto fail;
|
|
+ }
|
|
+ missing_index++;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
|
|
if (ret) {
|
|
goto fail;
|
|
@@ -138,7 +158,6 @@ static errno_t ipa_save_netgroup(TALLOC_CTX *mem_ctx,
|
|
if (el->num_values == 0) {
|
|
DEBUG(SSSDBG_TRACE_LIBS,
|
|
"No original members for netgroup [%s]\n", name);
|
|
-
|
|
} else {
|
|
DEBUG(SSSDBG_TRACE_LIBS,
|
|
"Adding original members to netgroup [%s]\n", name);
|
|
@@ -173,7 +192,7 @@ static errno_t ipa_save_netgroup(TALLOC_CTX *mem_ctx,
|
|
|
|
DEBUG(SSSDBG_TRACE_FUNC, "Storing info for netgroup %s\n", name);
|
|
|
|
- ret = sysdb_add_netgroup(dom, name, NULL, netgroup_attrs, NULL,
|
|
+ ret = sysdb_add_netgroup(dom, name, NULL, netgroup_attrs, missing,
|
|
dom->netgroup_timeout, 0);
|
|
if (ret) goto fail;
|
|
|
|
@@ -866,6 +885,18 @@ static int ipa_netgr_process_all(struct ipa_get_netgroups_state *state)
|
|
|
|
hash_iterate(state->new_netgroups, extract_netgroups, state);
|
|
for (i = 0; i < state->netgroups_count; i++) {
|
|
+ /* Make sure these attributes always exist, so we can remove them if
|
|
+ * there are no members. */
|
|
+ ret = sysdb_attrs_add_empty(state->netgroups[i], SYSDB_NETGROUP_MEMBER);
|
|
+ if (ret != EOK) {
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ ret = sysdb_attrs_add_empty(state->netgroups[i], SYSDB_NETGROUP_TRIPLE);
|
|
+ if (ret != EOK) {
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
/* load all its member netgroups, translate */
|
|
DEBUG(SSSDBG_TRACE_INTERNAL, "Extracting netgroup members of netgroup %d\n", i);
|
|
ret = sysdb_attrs_get_string_array(state->netgroups[i],
|
|
diff --git a/src/tests/system/tests/test_netgroups.py b/src/tests/system/tests/test_netgroups.py
|
|
new file mode 100644
|
|
index 000000000..6b6bc8e8b
|
|
--- /dev/null
|
|
+++ b/src/tests/system/tests/test_netgroups.py
|
|
@@ -0,0 +1,108 @@
|
|
+"""
|
|
+Netgroup tests.
|
|
+
|
|
+:requirement: netgroup
|
|
+"""
|
|
+
|
|
+from __future__ import annotations
|
|
+
|
|
+import pytest
|
|
+from sssd_test_framework.roles.client import Client
|
|
+from sssd_test_framework.roles.generic import GenericProvider
|
|
+from sssd_test_framework.topology import KnownTopologyGroup
|
|
+
|
|
+
|
|
+@pytest.mark.tier(1)
|
|
+@pytest.mark.ticket(gh=6652, bz=2162552)
|
|
+@pytest.mark.topology(KnownTopologyGroup.AnyProvider)
|
|
+def test_netgroups__add_remove_netgroup_triple(client: Client, provider: GenericProvider):
|
|
+ """
|
|
+ :title: Netgroup triple is correctly removed from cached record
|
|
+ :setup:
|
|
+ 1. Create local user "user-1"
|
|
+ 2. Create netgroup "ng-1"
|
|
+ 3. Add "(-,user-1,)" triple to the netgroup
|
|
+ 4. Start SSSD
|
|
+ :steps:
|
|
+ 1. Run "getent netgroup ng-1"
|
|
+ 2. Remove "(-,user-1,)" triple from "ng-1"
|
|
+ 3. Invalidate netgroup in cache "sssctl cache-expire -n ng-1"
|
|
+ 4. Run "getent netgroup ng-1"
|
|
+ :expectedresults:
|
|
+ 1. "(-,user-1,)" is present in the netgroup
|
|
+ 2. Triple was removed from the netgroup
|
|
+ 3. Cached record was invalidated
|
|
+ 4. "(-,user-1,)" is not present in the netgroup
|
|
+ :customerscenario: True
|
|
+ """
|
|
+ user = provider.user("user-1").add()
|
|
+ ng = provider.netgroup("ng-1").add().add_member(user=user)
|
|
+
|
|
+ client.sssd.start()
|
|
+
|
|
+ result = client.tools.getent.netgroup("ng-1")
|
|
+ assert result is not None
|
|
+ assert result.name == "ng-1"
|
|
+ assert len(result.members) == 1
|
|
+ assert "(-, user-1)" in result.members
|
|
+
|
|
+ ng.remove_member(user=user)
|
|
+ client.sssctl.cache_expire(netgroups=True)
|
|
+
|
|
+ result = client.tools.getent.netgroup("ng-1")
|
|
+ assert result is not None
|
|
+ assert result.name == "ng-1"
|
|
+ assert len(result.members) == 0
|
|
+
|
|
+
|
|
+@pytest.mark.tier(1)
|
|
+@pytest.mark.ticket(gh=6652, bz=2162552)
|
|
+@pytest.mark.topology(KnownTopologyGroup.AnyProvider)
|
|
+def test_netgroups__add_remove_netgroup_member(client: Client, provider: GenericProvider):
|
|
+ """
|
|
+ :title: Netgroup member is correctly removed from cached record
|
|
+ :setup:
|
|
+ 1. Create local user "user-1"
|
|
+ 2. Create local user "user-2"
|
|
+ 3. Create netgroup "ng-1"
|
|
+ 4. Create netgroup "ng-2"
|
|
+ 5. Add "(-,user-1,)" triple to the netgroup "ng-1"
|
|
+ 6. Add "(-,user-2,)" triple to the netgroup "ng-2"
|
|
+ 7. Add "ng-1" as a member to "ng-2"
|
|
+ 8. Start SSSD
|
|
+ :steps:
|
|
+ 1. Run "getent netgroup ng-2"
|
|
+ 2. Remove "ng-1" from "ng-2"
|
|
+ 3. Invalidate netgroup "ng-2" in cache "sssctl cache-expire -n ng-2"
|
|
+ 4. Run "getent netgroup ng-2"
|
|
+ :expectedresults:
|
|
+ 1. "(-,user-1,)", "(-,user-2,)" is present in the netgroup
|
|
+ 2. Netgroup member was removed from the netgroup
|
|
+ 3. Cached record was invalidated
|
|
+ 4. "(-,user-1,)" is not present in the netgroup, only "(-,user-2,)"
|
|
+ :customerscenario: True
|
|
+ """
|
|
+ u1 = provider.user("user-1").add()
|
|
+ u2 = provider.user("user-2").add()
|
|
+
|
|
+ ng1 = provider.netgroup("ng-1").add().add_member(user=u1)
|
|
+ ng2 = provider.netgroup("ng-2").add().add_member(user=u2, ng=ng1)
|
|
+
|
|
+ client.sssd.start()
|
|
+
|
|
+ result = client.tools.getent.netgroup("ng-2")
|
|
+ assert result is not None
|
|
+ assert result.name == "ng-2"
|
|
+ assert len(result.members) == 2
|
|
+ assert "(-, user-1)" in result.members
|
|
+ assert "(-, user-2)" in result.members
|
|
+
|
|
+ ng2.remove_member(ng=ng1)
|
|
+ client.sssctl.cache_expire(netgroups=True)
|
|
+
|
|
+ result = client.tools.getent.netgroup("ng-2")
|
|
+ assert result is not None
|
|
+ assert result.name == "ng-2"
|
|
+ assert len(result.members) == 1
|
|
+ assert "(-, user-1)" not in result.members
|
|
+ assert "(-, user-2)" in result.members
|
|
--
|
|
2.27.0
|
|
|