Commit e8ce454f authored by Rocky Automation's avatar Rocky Automation 📺
Browse files

import 389-ds-base-1.4.3.23-10.module+el8.5.0+12398+47000435

parents
c69c175a2f27053dffbfefac9c84ff16c7ff4cbf SOURCES/389-ds-base-1.4.3.23.tar.bz2
9e06b5cc57fd185379d007696da153893cf73e30 SOURCES/jemalloc-5.2.1.tar.bz2
22b1ef11852864027e184bb4bee56286b855b703 SOURCES/vendor-1.4.3.23-2.tar.gz
SOURCES/389-ds-base-1.4.3.23.tar.bz2
SOURCES/jemalloc-5.2.1.tar.bz2
SOURCES/vendor-1.4.3.23-2.tar.gz
From 1e1c2b23c35282481628af7e971ac683da334502 Mon Sep 17 00:00:00 2001
From: James Chapman <jachapma@redhat.com>
Date: Tue, 27 Apr 2021 17:00:15 +0100
Subject: [PATCH 02/12] Issue 4701 - RFE - Exclude attributes from retro
changelog (#4723)
Description: When the retro changelog plugin is enabled it writes the
added/modified values to the "cn-changelog" suffix. In
some cases an entries attribute values can be of a
sensitive nature and should be excluded. This RFE adds
functionality that will allow an admin exclude certain
attributes from the retro changelog DB.
Relates: https://github.com/389ds/389-ds-base/issues/4701
Reviewed by: mreynolds389, droideck (Thanks folks)
---
.../tests/suites/retrocl/basic_test.py | 292 ++++++++++++++++++
1 file changed, 292 insertions(+)
create mode 100644 dirsrvtests/tests/suites/retrocl/basic_test.py
diff --git a/dirsrvtests/tests/suites/retrocl/basic_test.py b/dirsrvtests/tests/suites/retrocl/basic_test.py
new file mode 100644
index 000000000..112c73cb9
--- /dev/null
+++ b/dirsrvtests/tests/suites/retrocl/basic_test.py
@@ -0,0 +1,292 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2021 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+
+import logging
+import ldap
+import time
+import pytest
+from lib389.topologies import topology_st
+from lib389.plugins import RetroChangelogPlugin
+from lib389._constants import *
+from lib389.utils import *
+from lib389.tasks import *
+from lib389.cli_base import FakeArgs, connect_instance, disconnect_instance
+from lib389.cli_base.dsrc import dsrc_arg_concat
+from lib389.cli_conf.plugins.retrochangelog import retrochangelog_add
+from lib389.idm.user import UserAccount, UserAccounts, nsUserAccounts
+
+pytestmark = pytest.mark.tier1
+
+USER1_DN = 'uid=user1,ou=people,'+ DEFAULT_SUFFIX
+USER2_DN = 'uid=user2,ou=people,'+ DEFAULT_SUFFIX
+USER_PW = 'password'
+ATTR_HOMEPHONE = 'homePhone'
+ATTR_CARLICENSE = 'carLicense'
+
+log = logging.getLogger(__name__)
+
+def test_retrocl_exclude_attr_add(topology_st):
+ """ Test exclude attribute feature of the retrocl plugin for add operation
+
+ :id: 3481650f-2070-45ef-9600-2500cfc51559
+
+ :setup: Standalone instance
+
+ :steps:
+ 1. Enable dynamic plugins
+ 2. Confige retro changelog plugin
+ 3. Add an entry
+ 4. Ensure entry attrs are in the changelog
+ 5. Exclude an attr
+ 6. Add another entry
+ 7. Ensure excluded attr is not in the changelog
+
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ 4. Success
+ 5. Success
+ 6. Success
+ 7. Success
+ """
+
+ st = topology_st.standalone
+
+ log.info('Enable dynamic plugins')
+ try:
+ st.config.set('nsslapd-dynamic-plugins', 'on')
+ except ldap.LDAPError as e:
+ ldap.error('Failed to enable dynamic plugins ' + e.args[0]['desc'])
+ assert False
+
+ log.info('Configure retrocl plugin')
+ rcl = RetroChangelogPlugin(st)
+ rcl.disable()
+ rcl.enable()
+ rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')
+
+ log.info('Restarting instance')
+ try:
+ st.restart()
+ except ldap.LDAPError as e:
+ ldap.error('Failed to restart instance ' + e.args[0]['desc'])
+ assert False
+
+ users = UserAccounts(st, DEFAULT_SUFFIX)
+
+ log.info('Adding user1')
+ try:
+ user1 = users.create(properties={
+ 'sn': '1',
+ 'cn': 'user 1',
+ 'uid': 'user1',
+ 'uidNumber': '11',
+ 'gidNumber': '111',
+ 'givenname': 'user1',
+ 'homePhone': '0861234567',
+ 'carLicense': '131D16674',
+ 'mail': 'user1@whereever.com',
+ 'homeDirectory': '/home/user1',
+ 'userpassword': USER_PW})
+ except ldap.ALREADY_EXISTS:
+ pass
+ except ldap.LDAPError as e:
+ log.error("Failed to add user1")
+
+ log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
+ try:
+ cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ except ldap.LDAPError as e:
+ log.fatal("Changelog search failed, error: " +str(e))
+ assert False
+ assert len(cllist) > 0
+ if cllist[0].hasAttr('changes'):
+ clstr = (cllist[0].getValue('changes')).decode()
+ assert ATTR_HOMEPHONE in clstr
+ assert ATTR_CARLICENSE in clstr
+
+ log.info('Excluding attribute ' + ATTR_HOMEPHONE)
+ args = FakeArgs()
+ args.connections = [st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM]
+ args.instance = 'standalone1'
+ args.basedn = None
+ args.binddn = None
+ args.starttls = False
+ args.pwdfile = None
+ args.bindpw = None
+ args.prompt = False
+ args.exclude_attrs = ATTR_HOMEPHONE
+ args.func = retrochangelog_add
+ dsrc_inst = dsrc_arg_concat(args, None)
+ inst = connect_instance(dsrc_inst, False, args)
+ result = args.func(inst, None, log, args)
+ disconnect_instance(inst)
+ assert result is None
+
+ log.info("5s delay for retrocl plugin to restart")
+ time.sleep(5)
+
+ log.info('Adding user2')
+ try:
+ user2 = users.create(properties={
+ 'sn': '2',
+ 'cn': 'user 2',
+ 'uid': 'user2',
+ 'uidNumber': '22',
+ 'gidNumber': '222',
+ 'givenname': 'user2',
+ 'homePhone': '0879088363',
+ 'carLicense': '04WX11038',
+ 'mail': 'user2@whereever.com',
+ 'homeDirectory': '/home/user2',
+ 'userpassword': USER_PW})
+ except ldap.ALREADY_EXISTS:
+ pass
+ except ldap.LDAPError as e:
+ log.error("Failed to add user2")
+
+ log.info('Verify homePhone attr is not in the changelog changestring')
+ try:
+ cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER2_DN)
+ assert len(cllist) > 0
+ if cllist[0].hasAttr('changes'):
+ clstr = (cllist[0].getValue('changes')).decode()
+ assert ATTR_HOMEPHONE not in clstr
+ assert ATTR_CARLICENSE in clstr
+ except ldap.LDAPError as e:
+ log.fatal("Changelog search failed, error: " +str(e))
+ assert False
+
+def test_retrocl_exclude_attr_mod(topology_st):
+ """ Test exclude attribute feature of the retrocl plugin for mod operation
+
+ :id: f6bef689-685b-4f86-a98d-f7e6b1fcada3
+
+ :setup: Standalone instance
+
+ :steps:
+ 1. Enable dynamic plugins
+ 2. Confige retro changelog plugin
+ 3. Add user1 entry
+ 4. Ensure entry attrs are in the changelog
+ 5. Exclude an attr
+ 6. Modify user1 entry
+ 7. Ensure excluded attr is not in the changelog
+
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ 4. Success
+ 5. Success
+ 6. Success
+ 7. Success
+ """
+
+ st = topology_st.standalone
+
+ log.info('Enable dynamic plugins')
+ try:
+ st.config.set('nsslapd-dynamic-plugins', 'on')
+ except ldap.LDAPError as e:
+ ldap.error('Failed to enable dynamic plugins ' + e.args[0]['desc'])
+ assert False
+
+ log.info('Configure retrocl plugin')
+ rcl = RetroChangelogPlugin(st)
+ rcl.disable()
+ rcl.enable()
+ rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')
+
+ log.info('Restarting instance')
+ try:
+ st.restart()
+ except ldap.LDAPError as e:
+ ldap.error('Failed to restart instance ' + e.args[0]['desc'])
+ assert False
+
+ users = UserAccounts(st, DEFAULT_SUFFIX)
+
+ log.info('Adding user1')
+ try:
+ user1 = users.create(properties={
+ 'sn': '1',
+ 'cn': 'user 1',
+ 'uid': 'user1',
+ 'uidNumber': '11',
+ 'gidNumber': '111',
+ 'givenname': 'user1',
+ 'homePhone': '0861234567',
+ 'carLicense': '131D16674',
+ 'mail': 'user1@whereever.com',
+ 'homeDirectory': '/home/user1',
+ 'userpassword': USER_PW})
+ except ldap.ALREADY_EXISTS:
+ pass
+ except ldap.LDAPError as e:
+ log.error("Failed to add user1")
+
+ log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
+ try:
+ cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ except ldap.LDAPError as e:
+ log.fatal("Changelog search failed, error: " +str(e))
+ assert False
+ assert len(cllist) > 0
+ if cllist[0].hasAttr('changes'):
+ clstr = (cllist[0].getValue('changes')).decode()
+ assert ATTR_HOMEPHONE in clstr
+ assert ATTR_CARLICENSE in clstr
+
+ log.info('Excluding attribute ' + ATTR_CARLICENSE)
+ args = FakeArgs()
+ args.connections = [st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM]
+ args.instance = 'standalone1'
+ args.basedn = None
+ args.binddn = None
+ args.starttls = False
+ args.pwdfile = None
+ args.bindpw = None
+ args.prompt = False
+ args.exclude_attrs = ATTR_CARLICENSE
+ args.func = retrochangelog_add
+ dsrc_inst = dsrc_arg_concat(args, None)
+ inst = connect_instance(dsrc_inst, False, args)
+ result = args.func(inst, None, log, args)
+ disconnect_instance(inst)
+ assert result is None
+
+ log.info("5s delay for retrocl plugin to restart")
+ time.sleep(5)
+
+ log.info('Modify user1 carLicense attribute')
+ try:
+ st.modify_s(USER1_DN, [(ldap.MOD_REPLACE, ATTR_CARLICENSE, b"123WX321")])
+ except ldap.LDAPError as e:
+ log.fatal('test_retrocl_exclude_attr_mod: Failed to update user1 attribute: error ' + e.message['desc'])
+ assert False
+
+ log.info('Verify carLicense attr is not in the changelog changestring')
+ try:
+ cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ assert len(cllist) > 0
+ # There will be 2 entries in the changelog for this user, we are only
+ #interested in the second one, the modify operation.
+ if cllist[1].hasAttr('changes'):
+ clstr = (cllist[1].getValue('changes')).decode()
+ assert ATTR_CARLICENSE not in clstr
+ except ldap.LDAPError as e:
+ log.fatal("Changelog search failed, error: " +str(e))
+ assert False
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
--
2.26.3
This diff is collapsed.
From c167d6127db45d8426437c273060c8c8f7fbcb9b Mon Sep 17 00:00:00 2001
From: Firstyear <william.brown@suse.com>
Date: Wed, 23 Sep 2020 09:19:34 +1000
Subject: [PATCH 04/12] Ticket 4326 - entryuuid fixup did not work correctly
(#4328)
Bug Description: due to an oversight in how fixup tasks
worked, the entryuuid fixup task did not work correctly and
would not persist over restarts.
Fix Description: Correctly implement entryuuid fixup.
fixes: #4326
Author: William Brown <william@blackhats.net.au>
Review by: mreynolds (thanks!)
---
.../tests/suites/entryuuid/basic_test.py | 24 +++-
src/plugins/entryuuid/src/lib.rs | 43 ++++++-
src/slapi_r_plugin/src/constants.rs | 5 +
src/slapi_r_plugin/src/entry.rs | 8 ++
src/slapi_r_plugin/src/lib.rs | 2 +
src/slapi_r_plugin/src/macros.rs | 2 +-
src/slapi_r_plugin/src/modify.rs | 118 ++++++++++++++++++
src/slapi_r_plugin/src/pblock.rs | 7 ++
src/slapi_r_plugin/src/value.rs | 4 +
9 files changed, 206 insertions(+), 7 deletions(-)
create mode 100644 src/slapi_r_plugin/src/modify.rs
diff --git a/dirsrvtests/tests/suites/entryuuid/basic_test.py b/dirsrvtests/tests/suites/entryuuid/basic_test.py
index beb73701d..4d8a40909 100644
--- a/dirsrvtests/tests/suites/entryuuid/basic_test.py
+++ b/dirsrvtests/tests/suites/entryuuid/basic_test.py
@@ -12,6 +12,7 @@ import time
import shutil
from lib389.idm.user import nsUserAccounts, UserAccounts
from lib389.idm.account import Accounts
+from lib389.idm.domain import Domain
from lib389.topologies import topology_st as topology
from lib389.backend import Backends
from lib389.paths import Paths
@@ -190,6 +191,7 @@ def test_entryuuid_fixup_task(topology):
3. Enable the entryuuid plugin
4. Run the fixup
5. Assert the entryuuid now exists
+ 6. Restart and check they persist
:expectedresults:
1. Success
@@ -197,6 +199,7 @@ def test_entryuuid_fixup_task(topology):
3. Success
4. Success
5. Suddenly EntryUUID!
+ 6. Still has EntryUUID!
"""
# 1. Disable the plugin
plug = EntryUUIDPlugin(topology.standalone)
@@ -220,7 +223,22 @@ def test_entryuuid_fixup_task(topology):
assert(task.is_complete() and task.get_exit_code() == 0)
topology.standalone.config.loglevel(vals=(ErrorLog.DEFAULT,))
- # 5. Assert the uuid.
- euuid = account.get_attr_val_utf8('entryUUID')
- assert(euuid is not None)
+ # 5.1 Assert the uuid on the user.
+ euuid_user = account.get_attr_val_utf8('entryUUID')
+ assert(euuid_user is not None)
+
+ # 5.2 Assert it on the domain entry.
+ domain = Domain(topology.standalone, dn=DEFAULT_SUFFIX)
+ euuid_domain = domain.get_attr_val_utf8('entryUUID')
+ assert(euuid_domain is not None)
+
+ # Assert it persists after a restart.
+ topology.standalone.restart()
+ # 6.1 Assert the uuid on the use.
+ euuid_user_2 = account.get_attr_val_utf8('entryUUID')
+ assert(euuid_user_2 == euuid_user)
+
+ # 6.2 Assert it on the domain entry.
+ euuid_domain_2 = domain.get_attr_val_utf8('entryUUID')
+ assert(euuid_domain_2 == euuid_domain)
diff --git a/src/plugins/entryuuid/src/lib.rs b/src/plugins/entryuuid/src/lib.rs
index 6b5e8d1bb..92977db05 100644
--- a/src/plugins/entryuuid/src/lib.rs
+++ b/src/plugins/entryuuid/src/lib.rs
@@ -187,9 +187,46 @@ impl SlapiPlugin3 for EntryUuid {
}
}
-pub fn entryuuid_fixup_mapfn(mut e: EntryRef, _data: &()) -> Result<(), PluginError> {
- assign_uuid(&mut e);
- Ok(())
+pub fn entryuuid_fixup_mapfn(e: &EntryRef, _data: &()) -> Result<(), PluginError> {
+ /* Supply a modification to the entry. */
+ let sdn = e.get_sdnref();
+
+ /* Sanity check that entryuuid doesn't already exist */
+ if e.contains_attr("entryUUID") {
+ log_error!(
+ ErrorLevel::Trace,
+ "skipping fixup for -> {}",
+ sdn.to_dn_string()
+ );
+ return Ok(());
+ }
+
+ // Setup the modifications
+ let mut mods = SlapiMods::new();
+
+ let u: Uuid = Uuid::new_v4();
+ let uuid_value = Value::from(&u);
+ let values: ValueArray = std::iter::once(uuid_value).collect();
+ mods.append(ModType::Replace, "entryUUID", values);
+
+ /* */
+ let lmod = Modify::new(&sdn, mods, plugin_id())?;
+
+ match lmod.execute() {
+ Ok(_) => {
+ log_error!(ErrorLevel::Trace, "fixed-up -> {}", sdn.to_dn_string());
+ Ok(())
+ }
+ Err(e) => {
+ log_error!(
+ ErrorLevel::Error,
+ "entryuuid_fixup_mapfn -> fixup failed -> {} {:?}",
+ sdn.to_dn_string(),
+ e
+ );
+ Err(PluginError::GenericFailure)
+ }
+ }
}
#[cfg(test)]
diff --git a/src/slapi_r_plugin/src/constants.rs b/src/slapi_r_plugin/src/constants.rs
index cf76ccbdb..34845c2f4 100644
--- a/src/slapi_r_plugin/src/constants.rs
+++ b/src/slapi_r_plugin/src/constants.rs
@@ -5,6 +5,11 @@ use std::os::raw::c_char;
pub const LDAP_SUCCESS: i32 = 0;
pub const PLUGIN_DEFAULT_PRECEDENCE: i32 = 50;
+#[repr(i32)]
+pub enum OpFlags {
+ ByassReferrals = 0x0040_0000,
+}
+
#[repr(i32)]
/// The set of possible function handles we can register via the pblock. These
/// values correspond to slapi-plugin.h.
diff --git a/src/slapi_r_plugin/src/entry.rs b/src/slapi_r_plugin/src/entry.rs
index 034efe692..22ae45189 100644
--- a/src/slapi_r_plugin/src/entry.rs
+++ b/src/slapi_r_plugin/src/entry.rs
@@ -70,6 +70,14 @@ impl EntryRef {
}
}
+ pub fn contains_attr(&self, name: &str) -> bool {
+ let cname = CString::new(name).expect("invalid attr name");
+ let va = unsafe { slapi_entry_attr_get_valuearray(self.raw_e, cname.as_ptr()) };
+
+ // If it's null, it's not present, so flip the logic.
+ !va.is_null()
+ }
+
pub fn add_value(&mut self, a: &str, v: &ValueRef) {
// turn the attr to a c string.
// TODO FIX
diff --git a/src/slapi_r_plugin/src/lib.rs b/src/slapi_r_plugin/src/lib.rs
index d7fc22e52..076907bae 100644
--- a/src/slapi_r_plugin/src/lib.rs
+++ b/src/slapi_r_plugin/src/lib.rs
@@ -9,6 +9,7 @@ pub mod dn;
pub mod entry;
pub mod error;
pub mod log;
+pub mod modify;
pub mod pblock;
pub mod plugin;
pub mod search;
@@ -24,6 +25,7 @@ pub mod prelude {
pub use crate::entry::EntryRef;
pub use crate::error::{DseCallbackStatus, LDAPError, PluginError, RPluginError};
pub use crate::log::{log_error, ErrorLevel};
+ pub use crate::modify::{ModType, Modify, SlapiMods};
pub use crate::pblock::{Pblock, PblockRef};
pub use crate::plugin::{register_plugin_ext, PluginIdRef, SlapiPlugin3};
pub use crate::search::{Search, SearchScope};
diff --git a/src/slapi_r_plugin/src/macros.rs b/src/slapi_r_plugin/src/macros.rs
index 030449632..bc8dfa60f 100644
--- a/src/slapi_r_plugin/src/macros.rs
+++ b/src/slapi_r_plugin/src/macros.rs
@@ -825,7 +825,7 @@ macro_rules! slapi_r_search_callback_mapfn {
let e = EntryRef::new(raw_e);
let data_ptr = raw_data as *const _;
let data = unsafe { &(*data_ptr) };
- match $cb_mod_ident(e, data) {
+ match $cb_mod_ident(&e, data) {
Ok(_) => LDAPError::Success as i32,
Err(e) => e as i32,
}
diff --git a/src/slapi_r_plugin/src/modify.rs b/src/slapi_r_plugin/src/modify.rs
new file mode 100644
index 000000000..30864377a
--- /dev/null
+++ b/src/slapi_r_plugin/src/modify.rs
@@ -0,0 +1,118 @@
+use crate::constants::OpFlags;
+use crate::dn::SdnRef;
+use crate::error::{LDAPError, PluginError};
+use crate::pblock::Pblock;
+use crate::plugin::PluginIdRef;
+use crate::value::{slapi_value, ValueArray};
+
+use std::ffi::CString;
+use std::ops::{Deref, DerefMut};
+use std::os::raw::c_char;
+
+extern "C" {
+ fn slapi_modify_internal_set_pb_ext(
+ pb: *const libc::c_void,
+ dn: *const libc::c_void,
+ mods: *const *const libc::c_void,
+ controls: *const *const libc::c_void,
+ uniqueid: *const c_char,
+ plugin_ident: *const libc::c_void,
+ op_flags: i32,
+ );
+ fn slapi_modify_internal_pb(pb: *const libc::c_void);
+ fn slapi_mods_free(smods: *const *const libc::c_void);
+ fn slapi_mods_get_ldapmods_byref(smods: *const libc::c_void) -> *const *const libc::c_void;
+ fn slapi_mods_new() -> *const libc::c_void;
+ fn slapi_mods_add_mod_values(
+ smods: *const libc::c_void,
+ mtype: i32,
+ attrtype: *const c_char,
+ value: *const *const slapi_value,
+ );
+}
+
+#[derive(Debug)]
+#[repr(i32)]
+pub enum ModType {
+ Add = 0,
+ Delete = 1,
+ Replace = 2,
+}
+
+pub struct SlapiMods {
+ inner: *const libc::c_void,
+ vas: Vec<ValueArray>,
+}
+
+impl Drop for SlapiMods {
+ fn drop(&mut self) {
+ unsafe { slapi_mods_free(&self.inner as *const *const libc::c_void) }
+ }
+}
+
+impl SlapiMods {
+ pub fn new() -> Self {
+ SlapiMods {
+ inner: unsafe { slapi_mods_new() },
+ vas: Vec::new(),
+ }
+ }
+
+ pub fn append(&mut self, modtype: ModType, attrtype: &str, values: ValueArray) {
+ // We can get the value array pointer here to push to the inner
+ // because the internal pointers won't change even when we push them