aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/Makefile1
-rw-r--r--net/py-lib389/Makefile49
-rw-r--r--net/py-lib389/distinfo3
-rw-r--r--net/py-lib389/files/patch-lib389_____init____.py17
-rw-r--r--net/py-lib389/files/patch-lib389_instance_remove.py19
-rw-r--r--net/py-lib389/files/patch-lib389_instance_setup.py16
-rw-r--r--net/py-lib389/files/patch-lib389_nss__ssl.py273
-rw-r--r--net/py-lib389/files/patch-pyproject.toml18
-rw-r--r--net/py-lib389/pkg-descr3
-rw-r--r--net/py-lib389/pkg-message26
10 files changed, 425 insertions, 0 deletions
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
+}
+]