Date: Mon, 29 Jun 2026 20:28:36 +0000 From: Jochen Neumeister <joneum@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: d10cb9f3925e - main - net/py-lib389: Add new port Message-ID: <6a42d574.308d5.71e52160@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by joneum: URL: https://cgit.FreeBSD.org/ports/commit/?id=d10cb9f3925e39cf9da8e59975fac96e1edc66c0 commit d10cb9f3925e39cf9da8e59975fac96e1edc66c0 Author: Jochen Neumeister <joneum@FreeBSD.org> AuthorDate: 2026-06-29 20:25:46 +0000 Commit: Jochen Neumeister <joneum@FreeBSD.org> CommitDate: 2026-06-29 20:27:24 +0000 net/py-lib389: Add new port lib389 provides the Python library and command-line administration tools for 389 Directory Server. It includes tools for creating and managing Directory Server instances, configuring servers, and managing directory entries. This port is required for the development of net/freeipa-server. WWW: https://www.port389.org/ Sponsored by: Netzkommune GmbH --- net/Makefile | 1 + net/py-lib389/Makefile | 49 ++++ net/py-lib389/distinfo | 3 + net/py-lib389/files/patch-lib389_____init____.py | 17 ++ .../files/patch-lib389_instance_remove.py | 19 ++ net/py-lib389/files/patch-lib389_instance_setup.py | 16 ++ net/py-lib389/files/patch-lib389_nss__ssl.py | 273 +++++++++++++++++++++ net/py-lib389/files/patch-pyproject.toml | 18 ++ net/py-lib389/pkg-descr | 3 + net/py-lib389/pkg-message | 26 ++ 10 files changed, 425 insertions(+) diff --git a/net/Makefile b/net/Makefile index 372552f8f5ee..991e3659aa6e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -1095,6 +1095,7 @@ SUBDIR += py-ldap3 SUBDIR += py-ldapdomaindump SUBDIR += py-ldappool + SUBDIR += py-lib389 SUBDIR += py-libcloud SUBDIR += py-libdnet SUBDIR += py-magic-wormhole diff --git a/net/py-lib389/Makefile b/net/py-lib389/Makefile new file mode 100644 index 000000000000..bbd0cc090984 --- /dev/null +++ b/net/py-lib389/Makefile @@ -0,0 +1,49 @@ +PORTNAME= lib389 +DISTVERSION= 3.2.1 +CATEGORIES= net python +MASTER_SITES= https://github.com/389ds/389-ds-base/releases/download/389-ds-base-${DISTVERSION}/ +PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} +DISTNAME= 389-ds-base-${DISTVERSION} + +MAINTAINER= joneum@FreeBSD.org +COMMENT= Python library and administration tools for 389 Directory Server +WWW= https://www.port389.org/ + +LICENSE= GPLv3+ +LICENSE_FILE= ${WRKSRC}/LICENSE + +BUILD_DEPENDS= ${PYTHON_PKGNAMEPREFIX}argcomplete>=0:devel/py-argcomplete@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}argparse-manpage>=0:devel/py-argparse-manpage@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}cryptography>=0:security/py-cryptography@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}distro>=0:sysutils/py-distro@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}psutil>=0:sysutils/py-psutil@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyasn1>=0:devel/py-pyasn1@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyasn1-modules>=0:devel/py-pyasn1-modules@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}python-ldap>=0:net/py-python-ldap@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}wheel>=0:devel/py-wheel@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}setuptools>=0:devel/py-setuptools@${PY_FLAVOR} + +RUN_DEPENDS= 389-ds-base>=${DISTVERSION}:net/389-ds-base \ + ${PYTHON_PKGNAMEPREFIX}argcomplete>=0:devel/py-argcomplete@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}cryptography>=0:security/py-cryptography@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}distro>=0:sysutils/py-distro@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}psutil>=0:sysutils/py-psutil@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyasn1>=0:devel/py-pyasn1@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyasn1-modules>=0:devel/py-pyasn1-modules@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}python-ldap>=0:net/py-python-ldap@${PY_FLAVOR} + +USES= python:3.12+ shebangfix tar:bzip2 +USE_PYTHON= autoplist concurrent pep517 + +SHEBANG_FILES= cli/dsconf \ + cli/dscontainer \ + cli/dscreate \ + cli/dsctl \ + cli/dsidm \ + cli/openldap_to_ds + +WRKSRC_SUBDIR= src/lib389 + +NO_ARCH= yes + +.include <bsd.port.mk> diff --git a/net/py-lib389/distinfo b/net/py-lib389/distinfo new file mode 100644 index 000000000000..b8bec5a2634e --- /dev/null +++ b/net/py-lib389/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1782503513 +SHA256 (389-ds-base-3.2.1.tar.bz2) = a5b7b533484f16d5271c97b7dbde485b22fa63d2bfb4434ce9b6720849e67559 +SIZE (389-ds-base-3.2.1.tar.bz2) = 23711885 diff --git a/net/py-lib389/files/patch-lib389_____init____.py b/net/py-lib389/files/patch-lib389_____init____.py new file mode 100644 index 000000000000..5412b1b5490d --- /dev/null +++ b/net/py-lib389/files/patch-lib389_____init____.py @@ -0,0 +1,17 @@ +--- lib389/__init__.py.orig 2026-06-29 17:03:20 UTC ++++ lib389/__init__.py +@@ -1158,6 +1158,14 @@ class DirSrv(SimpleLDAPObject, object): + raise e from None + else: + self.log.debug("systemd status -> False") ++ ++ # Runtime directories may be removed during a system reboot. ++ config_stat = os.stat(self.ds_paths.config_dir) ++ for path in (self.ds_paths.run_dir, self.ds_paths.lock_dir): ++ os.makedirs(path, mode=0o770, exist_ok=True) ++ os.chmod(path, 0o770) ++ os.chown(path, config_stat.st_uid, config_stat.st_gid) ++ + # Start the process. + # Wait for it to terminate + # This means the server is probably ready to go .... diff --git a/net/py-lib389/files/patch-lib389_instance_remove.py b/net/py-lib389/files/patch-lib389_instance_remove.py new file mode 100644 index 000000000000..5f73eddec86a --- /dev/null +++ b/net/py-lib389/files/patch-lib389_instance_remove.py @@ -0,0 +1,19 @@ +--- lib389/instance/remove.py.orig 2026-06-29 17:03:20 UTC ++++ lib389/instance/remove.py +@@ -96,12 +96,12 @@ def remove_ds_instance(dirsrv, force=False): + _log.debug("Removing %s" % remove_paths[path_k]) + shutil.rmtree(remove_paths[path_k], ignore_errors=True) + +- # Remove parent (/var/lib/dirsrv/slapd-INST) +- shutil.rmtree(remove_paths['db_dir'].replace('db', ''), ignore_errors=True) ++ # Remove the parent instance data directory. ++ shutil.rmtree(os.path.dirname(remove_paths['db_dir']), ignore_errors=True) + +- # Remove /run/slapd-isntance ++ # Remove the configured LDAPI socket. + try: +- os.remove(f'/run/slapd-{dirsrv.serverid}.socket') ++ os.remove(dirsrv.ds_paths.ldapi) + except OSError as e: + _log.debug("Failed to remove socket file: " + str(e)) + diff --git a/net/py-lib389/files/patch-lib389_instance_setup.py b/net/py-lib389/files/patch-lib389_instance_setup.py new file mode 100644 index 000000000000..9b7516a33ca0 --- /dev/null +++ b/net/py-lib389/files/patch-lib389_instance_setup.py @@ -0,0 +1,16 @@ +--- lib389/instance/setup.py.orig 2026-06-29 17:03:20 UTC ++++ lib389/instance/setup.py +@@ -826,10 +826,10 @@ class SetupDs(object): + # which subsequently breaks containers starting as instance.start then believes + # it COULD check the ds status. The times we need to check for systemd are mainly + # in other environments that use systemd natively in their containers. +- container_result = 1 +- if not self.containerised: ++ container_result = None ++ if not self.containerised and shutil.which("systemd-detect-virt"): + container_result = subprocess.run(["systemd-detect-virt", "-c"], stdout=subprocess.PIPE) +- if self.containerised or container_result.returncode == 0: ++ if self.containerised or (container_result is not None and container_result.returncode == 0): + # In a container, set the db_home_dir to the db path + self.log.debug("Container detected setting db home directory to db directory.") + slapd['db_home_dir'] = slapd['db_dir'] diff --git a/net/py-lib389/files/patch-lib389_nss__ssl.py b/net/py-lib389/files/patch-lib389_nss__ssl.py new file mode 100644 index 000000000000..372fa702b51b --- /dev/null +++ b/net/py-lib389/files/patch-lib389_nss__ssl.py @@ -0,0 +1,273 @@ +--- lib389/nss_ssl.py.orig 2026-06-29 18:47:35 UTC ++++ lib389/nss_ssl.py +@@ -198,7 +198,7 @@ only. + + # Init the db. + # 48886; This needs to be sql format ... +- cmd = ['/usr/bin/certutil', '-N', '-d', self._certdb, '-f', '%s/%s' % (self._certdb, PWD_TXT), '-@', '%s/%s' % (self._certdb, PWD_TXT)] ++ cmd = ['certutil', '-N', '-d', self._certdb, '-f', '%s/%s' % (self._certdb, PWD_TXT), '-@', '%s/%s' % (self._certdb, PWD_TXT)] + self._generate_noise('%s/noise.txt' % self._certdb) + self.log.debug("nss cmd: %s", format_cmd_list(cmd)) + try: +@@ -255,15 +255,15 @@ only. + return True + + try: +- openssl_version = check_output(['/usr/bin/openssl', 'version']).decode('utf-8').strip() ++ openssl_version = check_output(['openssl', 'version']).decode('utf-8').strip() + except subprocess.CalledProcessError as e: + raise ValueError(e.output.decode('utf-8').rstrip()) + rehash_available = DSVersion(openssl_version.split(' ')[1]) >= DSVersion('1.1.0') + + if rehash_available: +- cmd = ['/usr/bin/openssl', 'rehash', certdir] ++ cmd = ['openssl', 'rehash', certdir] + else: +- cmd = ['/usr/bin/c_rehash', certdir] ++ cmd = ['c_rehash', certdir] + self.log.debug("nss cmd: %s", format_cmd_list(cmd)) + try: + res = run(cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +@@ -285,7 +285,7 @@ only. + self._generate_noise('%s/noise.txt' % self._certdb) + # Now run the command. Can we do this with NSS native? + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-S', + '-n', + CA_NAME, +@@ -315,7 +315,7 @@ only. + # Now extract the CAcert to a well know place. + # This allows us to point the cacert dir here and it "just works" + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-L', + '-n', + CA_NAME, +@@ -339,7 +339,7 @@ only. + """ + + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-L', + '-n', + CA_NAME, +@@ -371,7 +371,7 @@ only. + + # Generate a CSR for a new CA cert + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-R', + '-s', + ISSUER, +@@ -396,7 +396,7 @@ only. + + # Sign the CSR with our old CA + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-C', + '-d', + self._certdb, +@@ -423,7 +423,7 @@ only. + + # Import the new CA to our DB instead of the old CA + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-A', + '-n', CA_NAME, + '-t', "CT,,", +@@ -442,7 +442,7 @@ only. + + def _rsa_cert_list(self): + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-L', + '-d', + self._certdb, +@@ -475,7 +475,7 @@ only. + + def _openssl_get_csr_subject(self, csr_dir, csr_name): + cmd = [ +- '/usr/bin/openssl', ++ 'openssl', + 'req', + '-subject', + '-noout', +@@ -498,7 +498,7 @@ only. + + def _openssl_get_csr_sub_alt_names(self, csr_dir, csr_name): + cmd = [ +- '/usr/bin/openssl', ++ 'openssl', + 'req', + '-noout', + '-text', +@@ -529,7 +529,7 @@ only. + if name and csr_dir: + if os.path.exists(csr_dir + "/" + name + ".csr"): + cmd = [ +- "/usr/bin/sed", ++ "sed", + "-n", + '/BEGIN NEW/,/END NEW/p', + csr_dir + "/" + name + ".csr" +@@ -547,7 +547,7 @@ only. + csr_dir = self.dirsrv.get_cert_dir() + # Search for .csr file extensions in instance config dir + cmd = [ +- '/usr/bin/find', ++ 'find', + csr_dir, + '-type', + 'f', +@@ -571,7 +571,7 @@ only. + csr = [] + # Get last modified time stamp + cmd = [ +- '/usr/bin/date', ++ 'date', + '-r', + '%s/%s'% (csr_dir, csr_file), + '+%Y-%m-%d %H:%M:%S', +@@ -596,7 +596,7 @@ only. + def _rsa_cert_key_exists(self, cert_tuple): + name = cert_tuple[0] + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-K', + '-d', + self._certdb, +@@ -688,7 +688,7 @@ only. + # Create noise. + self._generate_noise('%s/noise.txt' % self._certdb) + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-S', + '-n', + name, +@@ -741,7 +741,7 @@ only. + self._generate_noise('%s/noise.txt' % self._certdb) + + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-R', + # We want a dual purposes client and server cert + '--keyUsage', +@@ -781,7 +781,7 @@ only. + ca_path = '%s/ca.crt' % self._certdb + + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-C', + '-d', + self._certdb, +@@ -819,7 +819,7 @@ only. + shutil.copyfile(ca, '%s/ca.crt' % self._certdb) + self.openssl_rehash(self._certdb) + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-A', + '-n', CA_NAME, + '-t', "CT,,", +@@ -840,7 +840,7 @@ only. + raise ValueError("The certificate file ({}) does not exist".format(crt)) + self._assert_not_chain(crt) + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-A', + '-n', name, + '-t', ",,", +@@ -856,7 +856,7 @@ only. + except subprocess.CalledProcessError as e: + raise ValueError(e.output.decode('utf-8').rstrip()) + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-V', + '-d', self._certdb, + '-n', name, +@@ -881,7 +881,7 @@ only. + # Wait a second to avoid an NSS bug with serial ids based on time. + time.sleep(1) + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-S', + '-n', + '%s%s' % (USER_PREFIX, name), +@@ -992,7 +992,7 @@ only. + def list_keys(self, orphan=None): + key_list = [] + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-K', + '-d', + self._certdb, +@@ -1019,7 +1019,7 @@ only. + + def del_key(self, keyid): + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-F', + '-d', + self._certdb, +@@ -1040,7 +1040,7 @@ only. + """Delete this certificate + """ + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-D', + '-d', self._certdb, + '-n', nickname, +@@ -1072,7 +1072,7 @@ only. + + # Modify certificate flags + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-M', + '-d', self._certdb, + '-n', nickname, +@@ -1088,7 +1088,7 @@ only. + + def display_cert_details(self, nickname): + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-d', self._certdb, + '-n', nickname, + '-L', +@@ -1274,7 +1274,7 @@ only. + trust_flags = "CT,," if ca else ",," + + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-A', + '-d', self._certdb, + '-n', nickname, +@@ -1511,7 +1511,7 @@ only. + :raise ValueError: error + """ + cmd = [ +- '/usr/bin/certutil', ++ 'certutil', + '-L', + '-d', self._certdb, + '-n', nickname, diff --git a/net/py-lib389/files/patch-pyproject.toml b/net/py-lib389/files/patch-pyproject.toml new file mode 100644 index 000000000000..dd9d9915828f --- /dev/null +++ b/net/py-lib389/files/patch-pyproject.toml @@ -0,0 +1,18 @@ +--- pyproject.toml.orig 2026-06-29 14:08:52 UTC ++++ pyproject.toml +@@ -58,7 +58,6 @@ build_py = "build_hooks.build_py" + + [tool.setuptools.cmdclass] + build_py = "build_hooks.build_py" +-install = "build_hooks.install" + build_manpages = "build_hooks.build_manpages" + + [tool.build_manpages] +@@ -89,6 +88,7 @@ include = ["lib389", "lib389.*"] + + [tool.setuptools.packages.find] + include = ["lib389", "lib389.*"] ++exclude = ["lib389.tests", "lib389.tests.*"] + + [dependency-groups] + test = ["pytest"] diff --git a/net/py-lib389/pkg-descr b/net/py-lib389/pkg-descr new file mode 100644 index 000000000000..cde021b1d915 --- /dev/null +++ b/net/py-lib389/pkg-descr @@ -0,0 +1,3 @@ +lib389 is the Python administration library for 389 Directory Server. It +provides APIs and command-line tools for creating, configuring, managing, +and inspecting directory server instances. diff --git a/net/py-lib389/pkg-message b/net/py-lib389/pkg-message new file mode 100644 index 000000000000..ababe76c5d27 --- /dev/null +++ b/net/py-lib389/pkg-message @@ -0,0 +1,26 @@ +[ +{ type: install + message: <<EOM +The lib389 command-line tools can be used to create and manage +389 Directory Server instances. + +Create an instance interactively: + + dscreate interactive + +Create an instance from an INF file: + + dscreate from-file /path/to/instance.inf + +Manage an existing instance: + + dsctl <instance> status + dsctl <instance> start + dsctl <instance> stop + dsctl <instance> remove --do-it + +Use dsconf to manage the server configuration and dsidm to manage +directory entries. +EOM +} +]home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a42d574.308d5.71e52160>
