From 81ca90a77a667e26446d26223fdcf7e12ba45f15 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sat, 2 Dec 2017 12:51:35 +0100 Subject: [PATCH 1/5] Convert slapdtest to package with data The slapdtest module has been converted to a package to ship the test certs as package data. Closes: https://github.com/python-ldap/python-ldap/issues/76 Signed-off-by: Christian Heimes --- Lib/{slapdtest.py => slapdtest/__init__.py} | 15 +++++++-------- {Tests => Lib/slapdtest}/certs/README | 0 {Tests => Lib/slapdtest}/certs/ca.conf | 0 {Tests => Lib/slapdtest}/certs/ca.pem | 0 {Tests => Lib/slapdtest}/certs/client.conf | 0 {Tests => Lib/slapdtest}/certs/client.key | 0 {Tests => Lib/slapdtest}/certs/client.pem | 0 {Tests => Lib/slapdtest}/certs/gencerts.sh | 0 {Tests => Lib/slapdtest}/certs/gennssdb.sh | 0 {Tests => Lib/slapdtest}/certs/server.conf | 0 {Tests => Lib/slapdtest}/certs/server.key | 0 {Tests => Lib/slapdtest}/certs/server.pem | 0 MANIFEST.in | 1 + setup.py | 3 ++- 14 files changed, 10 insertions(+), 9 deletions(-) rename Lib/{slapdtest.py => slapdtest/__init__.py} (97%) rename {Tests => Lib/slapdtest}/certs/README (100%) rename {Tests => Lib/slapdtest}/certs/ca.conf (100%) rename {Tests => Lib/slapdtest}/certs/ca.pem (100%) rename {Tests => Lib/slapdtest}/certs/client.conf (100%) rename {Tests => Lib/slapdtest}/certs/client.key (100%) rename {Tests => Lib/slapdtest}/certs/client.pem (100%) rename {Tests => Lib/slapdtest}/certs/gencerts.sh (100%) rename {Tests => Lib/slapdtest}/certs/gennssdb.sh (100%) rename {Tests => Lib/slapdtest}/certs/server.conf (100%) rename {Tests => Lib/slapdtest}/certs/server.key (100%) rename {Tests => Lib/slapdtest}/certs/server.pem (100%) diff --git a/Lib/slapdtest.py b/Lib/slapdtest/__init__.py similarity index 97% rename from Lib/slapdtest.py rename to Lib/slapdtest/__init__.py index cd142f6..297bda7 100644 --- a/Lib/slapdtest.py +++ b/Lib/slapdtest/__init__.py @@ -24,6 +24,8 @@ import ldap from ldap.compat import quote_plus +HERE = os.path.abspath(os.path.dirname(__file__)) + # a template string for generating simple slapd.conf file SLAPD_CONF_TEMPLATE = r""" serverID %(serverid)s @@ -191,14 +193,11 @@ def __init__(self): ldapi_path = os.path.join(self.testrundir, 'ldapi') self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path) # TLS certs - capath = os.path.abspath(os.path.join( - os.getcwd(), 'Tests/certs' - )) - self.cafile = os.path.join(capath, 'ca.pem') - self.servercert = os.path.join(capath, 'server.pem') - self.serverkey = os.path.join(capath, 'server.key') - self.clientcert = os.path.join(capath, 'client.pem') - self.clientkey = os.path.join(capath, 'client.key') + self.cafile = os.path.join(HERE, 'certs/ca.pem') + self.servercert = os.path.join(HERE, 'certs/server.pem') + self.serverkey = os.path.join(HERE, 'certs/server.key') + self.clientcert = os.path.join(HERE, 'certs/client.pem') + self.clientkey = os.path.join(HERE, 'certs/client.key') def _check_requirements(self): binaries = [ diff --git a/Tests/certs/README b/Lib/slapdtest/certs/README similarity index 100% rename from Tests/certs/README rename to Lib/slapdtest/certs/README diff --git a/Tests/certs/ca.conf b/Lib/slapdtest/certs/ca.conf similarity index 100% rename from Tests/certs/ca.conf rename to Lib/slapdtest/certs/ca.conf diff --git a/Tests/certs/ca.pem b/Lib/slapdtest/certs/ca.pem similarity index 100% rename from Tests/certs/ca.pem rename to Lib/slapdtest/certs/ca.pem diff --git a/Tests/certs/client.conf b/Lib/slapdtest/certs/client.conf similarity index 100% rename from Tests/certs/client.conf rename to Lib/slapdtest/certs/client.conf diff --git a/Tests/certs/client.key b/Lib/slapdtest/certs/client.key similarity index 100% rename from Tests/certs/client.key rename to Lib/slapdtest/certs/client.key diff --git a/Tests/certs/client.pem b/Lib/slapdtest/certs/client.pem similarity index 100% rename from Tests/certs/client.pem rename to Lib/slapdtest/certs/client.pem diff --git a/Tests/certs/gencerts.sh b/Lib/slapdtest/certs/gencerts.sh similarity index 100% rename from Tests/certs/gencerts.sh rename to Lib/slapdtest/certs/gencerts.sh diff --git a/Tests/certs/gennssdb.sh b/Lib/slapdtest/certs/gennssdb.sh similarity index 100% rename from Tests/certs/gennssdb.sh rename to Lib/slapdtest/certs/gennssdb.sh diff --git a/Tests/certs/server.conf b/Lib/slapdtest/certs/server.conf similarity index 100% rename from Tests/certs/server.conf rename to Lib/slapdtest/certs/server.conf diff --git a/Tests/certs/server.key b/Lib/slapdtest/certs/server.key similarity index 100% rename from Tests/certs/server.key rename to Lib/slapdtest/certs/server.key diff --git a/Tests/certs/server.pem b/Lib/slapdtest/certs/server.pem similarity index 100% rename from Tests/certs/server.pem rename to Lib/slapdtest/certs/server.pem diff --git a/MANIFEST.in b/MANIFEST.in index f7398fa..687d2b0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,5 +5,6 @@ recursive-include Build *.cfg* recursive-include Lib *.py recursive-include Demo *.py recursive-include Tests *.py *.ldif +recursive-include Lib/slapdtest *.pem *.key *.conf *.sh README recursive-include Doc *.rst *.py spelling_wordlist.txt Makefile prune Doc/.build diff --git a/setup.py b/setup.py index f09d9c3..3d7d338 100644 --- a/setup.py +++ b/setup.py @@ -175,13 +175,14 @@ class OpenLDAP2: py_modules = [ 'ldapurl', 'ldif', - 'slapdtest', + ], packages = [ 'ldap', 'ldap.controls', 'ldap.extop', 'ldap.schema', + 'slapdtest', ], package_dir = {'': 'Lib',}, data_files = LDAP_CLASS.extra_files, From e89b035a2127f75b4aab0059d1e0ce806403f6f5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sat, 2 Dec 2017 13:03:08 +0100 Subject: [PATCH 2/5] Prolong certs to be valid for 10 years Now that we ship the certs as part of the package, make them valid for a longer time. CA validity is one day longer than certs, which are one day longer valid than CRL. Signed-off-by: Christian Heimes --- Lib/slapdtest/certs/ca.conf | 4 +- Lib/slapdtest/certs/ca.pem | 104 +++++++++++++++--------------- Lib/slapdtest/certs/client.key | 52 +++++++-------- Lib/slapdtest/certs/client.pem | 106 +++++++++++++++---------------- Lib/slapdtest/certs/gencerts.sh | 1 + Lib/slapdtest/certs/server.key | 52 +++++++-------- Lib/slapdtest/certs/server.pem | 108 ++++++++++++++++---------------- 7 files changed, 214 insertions(+), 213 deletions(-) diff --git a/Lib/slapdtest/certs/ca.conf b/Lib/slapdtest/certs/ca.conf index 4fb2e2b..5046b0d 100644 --- a/Lib/slapdtest/certs/ca.conf +++ b/Lib/slapdtest/certs/ca.conf @@ -32,7 +32,7 @@ serial = $tmpdir/$ca.crt.srl crlnumber = $tmpdir/$ca.crl.srl database = $tmpdir/$ca.db unique_subject = no -default_days = 1461 +default_days = 3652 default_md = sha256 policy = match_pol email_in_dn = no @@ -40,7 +40,7 @@ preserve = no name_opt = $name_opt cert_opt = ca_default copy_extensions = none -default_crl_days = 365 +default_crl_days = 3651 [match_pol] countryName = match diff --git a/Lib/slapdtest/certs/ca.pem b/Lib/slapdtest/certs/ca.pem index ffd6a5e..cf2ff33 100644 --- a/Lib/slapdtest/certs/ca.pem +++ b/Lib/slapdtest/certs/ca.pem @@ -5,31 +5,31 @@ Certificate: Signature Algorithm: sha256WithRSAEncryption Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA Validity - Not Before: Nov 28 13:49:28 2017 GMT - Not After : Nov 28 13:49:28 2021 GMT + Not Before: Dec 2 11:57:47 2017 GMT + Not After : Sep 4 11:57:47 2027 GMT Subject: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: - 00:b4:bd:47:78:d9:62:4e:8e:ae:18:53:b8:8e:9f: - 0b:13:ea:f2:59:c0:1d:7f:0b:5c:5a:ed:c8:b8:cd: - ff:66:94:c4:40:d5:cd:4c:da:06:d2:35:1c:6a:c5: - 76:70:6d:f0:81:8a:25:e4:35:c8:d5:79:17:3e:35: - ec:2b:97:73:77:6c:04:7f:1f:0b:b5:f3:fd:1a:cd: - 76:2c:5c:17:45:6a:6d:c4:d1:6c:f8:09:ba:a0:f8: - 57:44:d7:b4:1c:a4:be:a4:4b:e4:76:34:1c:b1:0b: - 12:42:7e:79:e4:01:e0:5f:8f:6c:03:2d:2a:b6:4e: - 72:85:f1:b9:ac:d5:22:a7:0a:fc:5a:0c:e5:75:8f: - 9f:20:c2:14:ab:53:6a:b0:e6:8a:0d:f4:97:53:7f: - f7:79:29:dd:ea:df:ae:39:6f:59:d8:b3:8e:da:bf: - 08:cd:03:ea:2a:91:33:c9:6f:21:a6:56:06:10:c1: - 40:4b:31:95:b0:47:2a:1e:2f:7d:eb:9b:f1:d4:27: - af:1a:5d:bf:0f:b4:f5:d5:b8:1d:04:61:fa:06:af: - 49:6f:ff:99:88:f3:44:16:ed:3b:f1:c8:ea:31:0a: - f3:f5:97:7a:17:08:e5:e8:8f:dd:1d:c8:8f:55:bf: - 47:93:9a:be:84:99:6f:f3:99:61:5d:b7:13:56:34: - 04:91 + 00:af:1f:cf:0f:c5:95:66:2d:eb:85:cc:21:fc:0d: + 0f:44:d8:2f:a8:85:08:ef:60:67:57:fa:0b:c5:e4: + b3:fb:f1:6f:cb:30:7a:47:0d:a7:f1:b5:37:81:5f: + f6:39:28:e2:f9:4d:6c:2e:a6:5c:0e:3c:db:4d:c9: + 2a:64:ce:0d:15:30:c7:75:52:b8:74:c5:0b:00:4c: + 2f:94:1b:dd:fb:83:2c:58:02:73:b0:86:3a:6a:aa: + 55:f2:d5:49:99:17:a5:e2:44:ec:dd:62:5f:8d:ce: + 77:29:0b:8d:87:23:e2:4b:d6:1c:25:f3:06:a9:ee: + 33:6f:ac:ed:22:9e:35:ec:55:e7:1b:38:68:7e:46: + e3:c3:42:ac:06:0b:0a:7a:84:c9:3d:ef:3d:a5:6e: + e9:10:24:c3:28:fe:1f:4a:9a:23:8a:3c:db:0a:66: + 5d:07:f8:c5:17:68:53:e4:0e:37:33:c4:d2:ad:58: + 62:6b:8a:87:ab:73:eb:bc:2b:ac:07:69:84:8d:e3: + c4:a9:78:9b:6c:1e:03:63:df:b4:96:18:bd:3c:2e: + be:7f:2c:d5:a8:f8:12:b9:ab:27:52:b0:de:38:62: + 3c:54:a7:f3:aa:37:a3:11:12:b2:a7:6f:8d:96:10: + ce:01:cb:25:24:a6:51:18:93:69:9b:9e:5c:8a:ff: + fe:89 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical @@ -37,44 +37,44 @@ Certificate: X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Subject Key Identifier: - 3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + 3B:1F:32:F4:FE:57:D1:6F:49:91:55:F2:24:F1:0A:66:3B:A5:EE:D4 X509v3 Authority Key Identifier: - keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + keyid:3B:1F:32:F4:FE:57:D1:6F:49:91:55:F2:24:F1:0A:66:3B:A5:EE:D4 Signature Algorithm: sha256WithRSAEncryption - 03:d2:e6:f5:e4:1d:99:2e:df:02:b9:5b:f7:e0:82:ca:39:76: - 5c:8f:3d:f1:5f:d4:bd:1b:4b:4f:35:4b:5d:f6:21:8b:c0:87: - 23:de:7e:9d:93:1b:67:60:6d:df:7b:95:f0:6a:87:94:5c:f9: - a3:62:50:7b:68:02:b0:5c:d2:4b:f9:b1:97:ba:24:84:47:6e: - e1:e9:d6:e0:fa:2f:f7:9b:c5:67:3a:eb:8e:bc:b7:8f:31:7d: - 5c:ba:91:ce:9d:2c:91:85:32:74:e7:e9:ba:07:61:7c:8b:55: - 69:db:f9:7b:1d:ef:55:fc:bf:58:fc:99:66:9c:9e:92:35:75: - 53:0a:31:e1:34:8a:cf:bc:79:b0:0e:ac:bf:aa:f0:e3:74:88: - f2:a6:5c:38:ad:21:31:ea:cd:e2:57:01:6b:9e:0b:24:62:78: - ac:6a:88:ba:ae:be:20:27:63:ab:3b:e9:2c:c0:5c:81:c5:e7: - e6:fe:a7:09:30:b4:28:65:51:6f:1b:1d:22:f8:30:7d:87:ae: - da:28:99:5c:8b:15:f0:b7:45:d0:1d:3b:ad:c5:29:4a:ed:11: - 68:c4:af:28:a3:0b:9f:1b:c8:86:56:80:3d:6b:d3:1f:c6:b0: - 3d:4a:39:1c:10:57:2d:22:df:d7:7b:ad:7d:f9:12:47:bb:33: - 29:61:14:c4 + 0a:e7:dc:38:ce:03:dd:a8:99:11:d0:24:be:ef:1a:18:9d:7c: + 95:75:4a:4a:29:44:23:28:fc:66:d5:81:ce:05:c2:c0:6b:71: + d6:8d:33:a9:53:a6:1c:f1:4e:50:ae:a3:b1:72:d6:69:53:ad: + a9:62:a9:45:27:68:17:35:41:97:ec:e9:65:91:62:12:ed:eb: + 45:3a:9b:cc:09:bc:e3:ad:22:6b:13:6b:b0:67:ef:ce:01:83: + 5e:6c:95:e2:b3:73:b9:69:9a:33:49:f9:5f:52:4e:39:94:c9: + db:93:6f:d8:ba:10:92:ce:fa:12:6b:bc:31:ff:c1:67:70:63: + 07:dc:53:7a:3a:a3:51:20:15:44:cf:1c:a9:cd:b7:30:1d:8e: + 55:93:8a:56:8c:3d:e9:8b:ae:0c:77:8d:5c:8b:fd:22:d8:4c: + 3e:e4:76:e8:d9:e8:c3:98:f4:98:ff:02:60:95:8e:3e:26:7a: + e2:fe:2c:0a:a4:52:8d:4c:3d:dd:4c:fd:2f:2c:db:83:4c:2b: + 25:24:37:78:9a:07:27:52:f9:1c:c0:65:65:cb:50:77:b4:2d: + fa:f4:af:bb:42:1c:43:65:c6:01:6e:f1:4b:fe:b8:4a:3c:29: + 8b:b6:84:1e:17:99:61:98:65:fe:f2:e9:ce:bb:ac:87:69:cb: + e6:13:42:bf -----BEGIN CERTIFICATE----- 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 -----END CERTIFICATE----- diff --git a/Lib/slapdtest/certs/client.key b/Lib/slapdtest/certs/client.key index 81c3e76..70600ba 100644 --- a/Lib/slapdtest/certs/client.key +++ b/Lib/slapdtest/certs/client.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4aZb1WfASk2JR -VAwFMMQCJNkbBDj7d8QdqSMa32jgTG8m/0N5RYGhdIi6zVeO2GmrSDuRd9Lv5hqu -6ZgFI/rRCYSZHrIe6MXSOs6ZZKHIeQYkZcKa7Eg1FWQPBS51FJjYcotoHj5uxyKZ -pOBMC63qODgq77G4zcqIKVswKS34KAIwvBAAUmTMtyMOOEh8oZm4V4ILpFFNBfs9 -CcyKMcAtCiFXOYZQ0G16ExzT560FMxMmCHd8HkevhfgFlKZb9/bsHNb+tvBwTQNm -eUl4gnPDJk6YLBGIscBImvSRJu8o07aZBvAZvRhPa5iX/mtnlg0pDQ9jiGFK24qB -VPQKtwHjAgMBAAECggEBAIYO7Fir6uP2FHD+4kYbr0HHu7PyG+JirETLoeN1KW50 -4hC9XDWam6PdbVAu2knTdO248uTK8KLI6fjhg0upXjn761LMh7wEh1pOucW07A8q -O5bWCuRIhC1iwXxRzfX65SnkCwfDhKtPRA3hV9SwYNt1xw8fdFjd8S+OsOWP6gUN -A33rBN6L44zfabZmcIO4DvSjDP4zoOL640uFg9dyf2yHzFI+q4mZgMK2iW5TZILl -pNfdQF/hZsqrme+kzUyEtQHzLxGk1twYlFubePS0K1wzXRw6OqFRA0+pYNYP+JmJ -bQs1k/e/y5qRiD9+UzR3MOTASl9BWDu9KCK1LF5pqYECgYEA7SD43REkVmQkFinf -Re1kfOTkqCub1t4veTZBqVBNCF10fnQwPk1UQ2PShum1iJun6S3P0NzJP/svGc0N -m44XJaD8QHnXdsDkHGx36/Cj15+VYpGvSpkPUgVQk4Q82n29Y3v8/xR6xqhXiB2N -kuWHig8WIrrc690mUlL1NLQvH+ECgYEAxxaggQXlBTdDSMj2x3Y/0TJlkese2Oet -JxWu6xGfjrsjMxZj1c5C3ESeKws3Z1eH9nk3AVzJ/q/+2SyCM3lM+eFz6dAtKVDB -Olly4YhxoEZDgW4JXMVLP8d7xNDxWk9y7UitpvfDJ8J0hf//y9KR2jnokkfSKScN -AsqrMe7+6kMCgYEAgndztV3rGkU6vZ8II1c7xKPDUuu7cHsKr6w0cE2oNIQGxlRy -/rRZOkK/4E7R/Hl35wm3n3j6mWNARPfXFtEU1zU91NO0wrfaSfE8AeqCmu5IqNTz -Fx4jmcMm1CMbwDMScpwTVN0VuBuDHXb1H+99pW4rhaw+RN+GaCEQnJDOpMECgYBv -UTOFcOpRNEkm1VdGx9N/ARLRuAmTdlbW18TqIvx4LiLMWeSQk7fGuYdGwgrEeajI -I5ah6GP5SCbS/5P9fAGSZoENZx0ZUNH58jHN8SC3YRI1uHT7rkUY8E1ACyQoPuwf -yNdv2HECNjQ5CJ7aNG7g+igUQpw77l3UBcYbMWrPSQKBgG+R+nFGbjJ7oHyvJyJI -C3rlD6vay9BoXmjA05dCO36zDcq5xZqwLnQmYkFgBw+RwvwV8gbBirG7GEpy0rdt -5YbHwiI6fMfLsXocU9f86o2dhhpA2o42ig3mfe8X3LteWtmRfJ3BtHbW2ZWS8Kvx -MnZGm64AmjWV5oJb7e5jpgu6 +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGxvbMEbahViK4 +P6aoWUkciIf1dEYTBuU8M1eShREUZ3Ytq/ee425pXRyxxDrAa8ygRjqs7tauwhgA +KNuPRGyw7hyZ1Ku4vQObwX9rzyHQ6Fj606U4HHbYfAVb0AF7OzLbhNH3isCRtNcm +EUSYG1Nkfn9zQkV4pz2KJM4ePt4GyGJV0NhRUdHdwgsWiuRt2EIRPwLXdkf/4svm +2EahAJax+SMaZYe/lg9w9SBxl6DTaF9lFpoPqzeW+KnXCmE8e+qSWea8EjkzIRXa +4KJ/EnUMP2fUL+Je2agGF2YfCId9YvLTQV8YDv7Im1Sp0sbIUDoWX14GDUbZ8cBr +wfOyI0TfAgMBAAECggEATWv1eGp1zcU05Lq1+OA938U1316YZJTM+HOu6jy1+FKL +7yIJ4nMG8Db6FCswDv5txwdTl0O3jn2+x2Eik1y9UPSNY0U4VU4Zd7MYJC+bJjk5 +XwjMU1yS1aMIm0gbK5pVJrdG6Lm8Y4QiQIt9Qhlyk7PJhGUNlf7ds06+kX0/ETiO +vx5SatExeKu5F+JRnGFdAN0106SF5vBum+UbrgOSnJmfwX5VoOXARD21ppxgMzAr +JyGBpgBgy++GpV15gXGuA7DVMIADdHw8hV4OuBLjpkUL+ntArjhpUi7TP7VU3WKR +uUmvLm9CX1l8O/xZMpt9N1+o71a//7asnz8AMtT6cQKBgQD4FgefUkVnXDA1xKDW +1JbArVQeHiLGlRdLakRUY/HdGj72YgAOLt3UsrON4VQXl0C6rks/8HKCFaMexBlF +OecJNWsEVgBEAfsQ+NvrApOQsTszc8Zqna0Kqe2vA0VNa+SAzdHzhBbFcaVkzXJb +JB7M0/OIt5IaqXg6Y5eX2eZF1QKBgQDNHkIoJ/2hYtlSgXpGaniM+0XemQJgJXig +edAQdGKKfqwmjSFjByDM01ZaidMu5fEkeGhMRE73IbwNw0pWsMXylD6bI6+sk7yQ +biM+fslFEEDbgSJe41Jy2eerh5am+dnrMWNhd7QZV1K6tmaqrIzkmIV21/EPXIPp +BNHO8GV14wKBgGOybrO/GzcTXChvcXeEDWU3AqPr1mvZhHgBJ56GX69MGdtnvL/2 +Y51Th0bQM7wbQ58B5im21j2itl/pzIH+Z/NSbURbz1WFOkEy0SYbbfPq1XCy6Rz1 +apHrgiIf/VzErBp7HBFxlrkYF7Bvw7IOzPXhg3AA3Y0rZ66HUWdr4NdVAoGBAJfC +E2Bydgy5feC1OypuC9MC9abDviY0kxLoDTCfa2jcX7IGKPWDiJkCo5lI7557Mfax +vzjuMR5XLzNfkdih4VKgq9FMjeU5SQHy+tB6LZ+Tbuj4md1qgs3GuskGAEh6Auko +GUc7sVwuZ18NJNiR4Ywf7F8JVajv4gi9MB3Tbr3RAoGARSnVu+6rYSQTyEqvbsaB +gIW7Ezea5q06GcQF072nk3tNSXuU/52YMlodAJ1UfFPbBAtaa7wEFN8oRG1IyKON +MGyf6RD8GoInJjaDihkdCsR28RkchwymG1UMPnPzqRxSAb7da5YuMR8PEioVbL68 +dxhsgNi1Wtc2nGqN96qufG0= -----END PRIVATE KEY----- diff --git a/Lib/slapdtest/certs/client.pem b/Lib/slapdtest/certs/client.pem index 8133c6d..33b95a7 100644 --- a/Lib/slapdtest/certs/client.pem +++ b/Lib/slapdtest/certs/client.pem @@ -5,31 +5,31 @@ Certificate: Signature Algorithm: sha256WithRSAEncryption Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA Validity - Not Before: Nov 28 13:49:28 2017 GMT - Not After : Nov 28 13:49:28 2021 GMT + Not Before: Dec 2 11:57:48 2017 GMT + Not After : Dec 2 11:57:48 2027 GMT Subject: C=DE, O=python-ldap, OU=slapd-test, CN=client Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: - 00:b8:69:96:f5:59:f0:12:93:62:51:54:0c:05:30: - c4:02:24:d9:1b:04:38:fb:77:c4:1d:a9:23:1a:df: - 68:e0:4c:6f:26:ff:43:79:45:81:a1:74:88:ba:cd: - 57:8e:d8:69:ab:48:3b:91:77:d2:ef:e6:1a:ae:e9: - 98:05:23:fa:d1:09:84:99:1e:b2:1e:e8:c5:d2:3a: - ce:99:64:a1:c8:79:06:24:65:c2:9a:ec:48:35:15: - 64:0f:05:2e:75:14:98:d8:72:8b:68:1e:3e:6e:c7: - 22:99:a4:e0:4c:0b:ad:ea:38:38:2a:ef:b1:b8:cd: - ca:88:29:5b:30:29:2d:f8:28:02:30:bc:10:00:52: - 64:cc:b7:23:0e:38:48:7c:a1:99:b8:57:82:0b:a4: - 51:4d:05:fb:3d:09:cc:8a:31:c0:2d:0a:21:57:39: - 86:50:d0:6d:7a:13:1c:d3:e7:ad:05:33:13:26:08: - 77:7c:1e:47:af:85:f8:05:94:a6:5b:f7:f6:ec:1c: - d6:fe:b6:f0:70:4d:03:66:79:49:78:82:73:c3:26: - 4e:98:2c:11:88:b1:c0:48:9a:f4:91:26:ef:28:d3: - b6:99:06:f0:19:bd:18:4f:6b:98:97:fe:6b:67:96: - 0d:29:0d:0f:63:88:61:4a:db:8a:81:54:f4:0a:b7: - 01:e3 + 00:c6:c6:f6:cc:11:b6:a1:56:22:b8:3f:a6:a8:59: + 49:1c:88:87:f5:74:46:13:06:e5:3c:33:57:92:85: + 11:14:67:76:2d:ab:f7:9e:e3:6e:69:5d:1c:b1:c4: + 3a:c0:6b:cc:a0:46:3a:ac:ee:d6:ae:c2:18:00:28: + db:8f:44:6c:b0:ee:1c:99:d4:ab:b8:bd:03:9b:c1: + 7f:6b:cf:21:d0:e8:58:fa:d3:a5:38:1c:76:d8:7c: + 05:5b:d0:01:7b:3b:32:db:84:d1:f7:8a:c0:91:b4: + d7:26:11:44:98:1b:53:64:7e:7f:73:42:45:78:a7: + 3d:8a:24:ce:1e:3e:de:06:c8:62:55:d0:d8:51:51: + d1:dd:c2:0b:16:8a:e4:6d:d8:42:11:3f:02:d7:76: + 47:ff:e2:cb:e6:d8:46:a1:00:96:b1:f9:23:1a:65: + 87:bf:96:0f:70:f5:20:71:97:a0:d3:68:5f:65:16: + 9a:0f:ab:37:96:f8:a9:d7:0a:61:3c:7b:ea:92:59: + e6:bc:12:39:33:21:15:da:e0:a2:7f:12:75:0c:3f: + 67:d4:2f:e2:5e:d9:a8:06:17:66:1f:08:87:7d:62: + f2:d3:41:5f:18:0e:fe:c8:9b:54:a9:d2:c6:c8:50: + 3a:16:5f:5e:06:0d:46:d9:f1:c0:6b:c1:f3:b2:23: + 44:df Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical @@ -39,45 +39,45 @@ Certificate: X509v3 Extended Key Usage: critical TLS Web Client Authentication X509v3 Subject Key Identifier: - C5:E2:E2:72:A6:55:C1:FB:D3:4B:11:01:D0:A0:AE:99:B6:8F:F1:39 + 67:63:38:F4:B4:BC:F3:6B:BC:74:0E:7C:27:C9:BB:C2:CC:58:AC:16 X509v3 Authority Key Identifier: - keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + keyid:3B:1F:32:F4:FE:57:D1:6F:49:91:55:F2:24:F1:0A:66:3B:A5:EE:D4 Signature Algorithm: sha256WithRSAEncryption - 11:76:03:a3:a6:9d:4e:3e:74:93:50:3b:31:d5:c7:d0:a8:34: - 84:01:6b:a2:08:cd:89:11:57:97:a2:e9:83:f0:a6:ef:03:8c: - b2:8d:31:8f:ee:b3:c9:8c:49:1f:e4:fc:21:58:8d:22:c2:17: - 96:2e:b1:d1:64:03:d6:48:70:41:65:22:38:bf:9f:00:dd:a8: - 82:a0:df:22:e0:9a:1b:27:16:4b:db:7f:b0:fe:9f:a8:80:90: - 69:ad:35:be:e6:95:fe:f9:64:96:0a:d8:d7:8e:aa:63:fb:9a: - d5:d0:e9:cb:8c:f3:08:c0:0c:26:72:c9:c6:29:5c:cf:3c:9e: - e2:38:37:5a:16:2f:70:82:0b:e6:80:27:90:bd:81:b4:58:52: - 6c:4e:b7:77:fc:49:76:7a:4f:6c:ee:ff:02:1f:f4:49:6e:78: - c3:fa:cd:ee:d3:e7:e5:05:a4:16:97:48:16:44:9f:81:1c:ac: - a9:30:0e:1d:ea:15:32:d7:2b:1e:68:92:0a:9c:5b:b2:27:57: - d3:21:3e:76:71:94:2d:da:76:61:aa:64:99:b7:54:1c:ba:e2: - a5:b3:21:a4:a8:36:fe:5d:a3:73:6a:5e:77:af:ab:9a:d9:62: - 00:f0:fd:90:1e:b6:cc:57:5d:92:0d:16:16:97:78:48:27:fc: - d9:2d:55:4d + 76:24:42:6b:33:4f:d6:59:07:48:5b:04:9c:3c:d3:3f:63:80: + 75:4d:78:d7:d5:85:b1:77:81:31:a3:91:cb:c9:a3:8c:0e:00: + 28:08:74:71:6c:fc:83:8c:80:ec:1c:e8:ee:83:e0:7f:49:3b: + f3:42:33:5a:1f:68:0c:a5:41:42:ce:bf:77:29:07:f2:18:a7: + 81:17:d7:76:47:04:d9:8a:dd:e8:5a:26:26:ea:a4:76:70:e1: + f1:fa:e1:db:bc:f2:24:b2:37:a8:58:2f:e3:66:89:77:02:55: + 87:ef:3c:1f:66:ce:4e:86:b3:4c:57:43:86:7f:4c:ab:5a:33: + dd:ca:e3:2f:3b:af:b4:43:5a:53:8b:e0:12:da:e7:c0:13:76: + b2:68:d5:14:f8:1a:07:ce:8a:87:5c:91:bd:35:d7:83:c6:2a: + a4:e0:92:50:01:b9:c2:fa:69:06:5c:8a:80:ee:9c:24:f9:49: + 64:e3:59:c1:a6:69:29:ce:b7:89:20:a9:7c:d6:9f:df:2a:d1: + a4:98:2a:6d:7b:93:6a:52:e3:ae:de:1a:d8:f3:2e:cf:02:7e: + ba:9a:fa:f4:b3:b5:6e:9a:23:10:70:53:53:30:d5:8a:32:35: + 01:52:58:6d:9d:f5:8e:bb:b9:76:bd:41:16:88:26:f8:d3:ce: + 70:03:c8:59 -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJERTEU MBIGA1UECgwLcHl0aG9uLWxkYXAxEzARBgNVBAsMCnNsYXBkLXRlc3QxHDAaBgNV -BAMME1B5dGhvbiBMREFQIFRlc3QgQ0EwHhcNMTcxMTI4MTM0OTI4WhcNMjExMTI4 -MTM0OTI4WjBJMQswCQYDVQQGEwJERTEUMBIGA1UECgwLcHl0aG9uLWxkYXAxEzAR +BAMME1B5dGhvbiBMREFQIFRlc3QgQ0EwHhcNMTcxMjAyMTE1NzQ4WhcNMjcxMjAy +MTE1NzQ4WjBJMQswCQYDVQQGEwJERTEUMBIGA1UECgwLcHl0aG9uLWxkYXAxEzAR BgNVBAsMCnNsYXBkLXRlc3QxDzANBgNVBAMMBmNsaWVudDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALhplvVZ8BKTYlFUDAUwxAIk2RsEOPt3xB2pIxrf -aOBMbyb/Q3lFgaF0iLrNV47YaatIO5F30u/mGq7pmAUj+tEJhJkesh7oxdI6zplk -och5BiRlwprsSDUVZA8FLnUUmNhyi2gePm7HIpmk4EwLreo4OCrvsbjNyogpWzAp -LfgoAjC8EABSZMy3Iw44SHyhmbhXggukUU0F+z0JzIoxwC0KIVc5hlDQbXoTHNPn -rQUzEyYId3weR6+F+AWUplv39uwc1v628HBNA2Z5SXiCc8MmTpgsEYixwEia9JEm -7yjTtpkG8Bm9GE9rmJf+a2eWDSkND2OIYUrbioFU9Aq3AeMCAwEAAaN4MHYwDAYD +AQEBBQADggEPADCCAQoCggEBAMbG9swRtqFWIrg/pqhZSRyIh/V0RhMG5TwzV5KF +ERRndi2r957jbmldHLHEOsBrzKBGOqzu1q7CGAAo249EbLDuHJnUq7i9A5vBf2vP +IdDoWPrTpTgcdth8BVvQAXs7MtuE0feKwJG01yYRRJgbU2R+f3NCRXinPYokzh4+ +3gbIYlXQ2FFR0d3CCxaK5G3YQhE/Atd2R//iy+bYRqEAlrH5Ixplh7+WD3D1IHGX +oNNoX2UWmg+rN5b4qdcKYTx76pJZ5rwSOTMhFdrgon8SdQw/Z9Qv4l7ZqAYXZh8I +h31i8tNBXxgO/sibVKnSxshQOhZfXgYNRtnxwGvB87IjRN8CAwEAAaN4MHYwDAYD VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUH -AwIwHQYDVR0OBBYEFMXi4nKmVcH700sRAdCgrpm2j/E5MB8GA1UdIwQYMBaAFD2A -47uUl9vd38gaI4rLK8E9GuaFMA0GCSqGSIb3DQEBCwUAA4IBAQARdgOjpp1OPnST -UDsx1cfQqDSEAWuiCM2JEVeXoumD8KbvA4yyjTGP7rPJjEkf5PwhWI0iwheWLrHR -ZAPWSHBBZSI4v58A3aiCoN8i4JobJxZL23+w/p+ogJBprTW+5pX++WSWCtjXjqpj -+5rV0OnLjPMIwAwmcsnGKVzPPJ7iODdaFi9wggvmgCeQvYG0WFJsTrd3/El2ek9s -7v8CH/RJbnjD+s3u0+flBaQWl0gWRJ+BHKypMA4d6hUy1yseaJIKnFuyJ1fTIT52 -cZQt2nZhqmSZt1QcuuKlsyGkqDb+XaNzal53r6ua2WIA8P2QHrbMV12SDRYWl3hI -J/zZLVVN +AwIwHQYDVR0OBBYEFGdjOPS0vPNrvHQOfCfJu8LMWKwWMB8GA1UdIwQYMBaAFDsf +MvT+V9FvSZFV8iTxCmY7pe7UMA0GCSqGSIb3DQEBCwUAA4IBAQB2JEJrM0/WWQdI +WwScPNM/Y4B1TXjX1YWxd4Exo5HLyaOMDgAoCHRxbPyDjIDsHOjug+B/STvzQjNa +H2gMpUFCzr93KQfyGKeBF9d2RwTZit3oWiYm6qR2cOHx+uHbvPIksjeoWC/jZol3 +AlWH7zwfZs5OhrNMV0OGf0yrWjPdyuMvO6+0Q1pTi+AS2ufAE3ayaNUU+BoHzoqH +XJG9NdeDxiqk4JJQAbnC+mkGXIqA7pwk+Ulk41nBpmkpzreJIKl81p/fKtGkmCpt +e5NqUuOu3hrY8y7PAn66mvr0s7VumiMQcFNTMNWKMjUBUlhtnfWOu7l2vUEWiCb4 +085wA8hZ -----END CERTIFICATE----- diff --git a/Lib/slapdtest/certs/gencerts.sh b/Lib/slapdtest/certs/gencerts.sh index 6edafa0..7a971a3 100755 --- a/Lib/slapdtest/certs/gencerts.sh +++ b/Lib/slapdtest/certs/gencerts.sh @@ -29,6 +29,7 @@ openssl ca -selfsign \ -in $CATMPDIR/ca.csr \ -out $CAOUTDIR/ca.pem \ -extensions ca_ext \ + -days 3563 \ -batch # server cert diff --git a/Lib/slapdtest/certs/server.key b/Lib/slapdtest/certs/server.key index 081dc2f..a48ee56 100644 --- a/Lib/slapdtest/certs/server.key +++ b/Lib/slapdtest/certs/server.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTJOAnZdPnCTmy -gkI5XUHsuk1xL4eePxMcV+8HYMfQh+b354CygQnRcjj38uQ6S70mOIyCrTWKNrec -VrnV0xu4o16AkSRrkN0AVpfWk0ae2GaccDV+o82x+NBStfYNXW2xZ1aZIyFplGTU -yxQCpsU4yCX7RM7Ywq3fM6b8eoR2jRNGC/uMdNN/7WJkHfhJFOYFpPJ6vKOlR3PP -qzkj8WRu/ill63+phHA3UEUweKG4DoaP85M0WqHW4Kvp0A4sI5uPYI2lPrDqUf6L -Wc22gUpcFFNDReWYcxLobCsAeT4SqvEC83Dv53NKQS6wt4zLewVG1+8cjyctwv4m -PAatL8uDAgMBAAECggEACB8+BCX1nciMEKLUG1LMC2grPHRgmiTA/nEff8AoT4w6 -xUSBfdxa3VSwflE4mEl7kDHSreAt1BBAxeHMKj6BrXuTUgzDQuQCrFWoZ5eousmG -QPRMCoAQlI0GrnfTbDYw1wcrnJ5uVZpgupLJRUTXB1UjqOO/tTTf7VsWTFYGLG00 -8OeIenTGX0E1mVW9ERYCSYEtMfhQhSS3dhPmMm5VV6muIxv4ym6r2uodCY7ocxGA -JmI9F22xovH8CUtzoRbh0o4Y9VUVkKcMDl35+hya8c0BH4Vh22hnYgiyUkS1pBgY -GiX/rmU4FxkzLDrLLMB8cf+rzh+aOKjNupZ2dbNgsQKBgQDu3DLRHhUJEUcoK6Gb -ltVK179WsT1Me1Y/qiZ2SgGsXmSZFK+8cYLvXUI7Epz2Du2DwAb1J+sItie5QQ9g -o6eymTS7DuQ6MFS1UmC8PfSNjT/dFd/sVIEFJRcNkVC4CpJCnE4MQOUb6OIT8YnR -+HNDNMWc5+ab1OeFxMWRSrP52wKBgQDiS4oFkhfPtaxVyUHuiR0+0icjCGehWSM0 -eNoiX561HtBrYCZYp6kg1JMSLBSJPRaHi78td3z+6iDvE6HQtwrLq/LNd2CRJ80U -rkGjsItpZYfnJVMmK6Y4KksGlvYqWshWb8Zp0o+LPRb6g0TxZrbOGv7yD8FjaZwq -wlGxleIJeQKBgDDR+uT5BA2lZWjVeiOF8bRpYmdCtKe0Mc2zZkcZGzxy0pbjPoQC -o2NvKUFPrZsxM+SQ1Bs5fHV8XaQkoxL6gCUl4Tw2b/lgtX+WBcWT2C8yZpI2jV0N -bI1zpkGUqO3k4z4QGnewr+NDdyniXWv4Hv7mg1ltoJnLK0MRE9x9a0mvAoGBAIi4 -8w8ikVhhf1nlWvxvw0etWRAFh/coD+koC0MxWoY7s9jsIr71rW20gZc9Irs4OWBz -wnIJ+29YrcVEq0ObE96yaORS9/k7fuC719S6WcC4I0A4gOBTBv5wLxwwIVK9vsTa -i5psKWYK5tM8dG8Vi+VC0j4V3tXdfQkolosg74yhAoGAOLj21q7nNk+ExGAOesmR -qykxwIXxbHxDIfmEJJVE6OJMRvubr8WgaiSG0ptWBeiHDnldUS436difn7JXlsdo -K51jVzzgUqZXK75xvnSD7e5AL3fFRCU5usoU699fxWJTMs8H2z4alRng06MloeXJ -xrLwQyuLH8BWYFuPj4QxwwQ= +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAgcI7Pj89Aw4r +rb+N8j3t1ynJgXRhQNxbxQcQmUCi8AtpGKNXu+aM9u2HxZ677ALfhsEivtQA5QKz +Ll5G2G2IQa7uzgIco73OL/kMZIJt7sKfnvfACtSoOlD0IyOzVEEu0AVA7hMHb6Ul +I0mCNfdk2FWFbc1nUmIAEBhIODbFoNW+Rc6lz94NsUqArDayvWpAsXkUbubQikpi +KNX1OpOOC9GUbEhwI/G90ZnUg9STk/2oxsvwLlYdOhGhpyfl53tTu7eLMBriMxFl +UTvkY1GUgPj0fA/giWtCerGOyeKu1hFlbS4LjborsfrlyYPwfwTg3YL4hVnt9fF0 +rpjzY1mlAgMBAAECggEAJY6rSEeiqtKXxynEv3rNXkOmIWwiOn8e/sB32mMr2x4d ++8kUxR8hocrjGKQTjfJDtTxjHdZBIlOLrU2UkxnSdMzrxidm/hNsCngNjL9nOu9k +BSRMjakPSCrodFkOtAPyG6H2BG7uQ3siqxYxVzgUJhaWyMtdUZUfDYgWVLCy7udU +5ML/OTOi7virueMmshjXoyrDug9OpiEMKiLu3ndAaDk/26m05ePAXB6TjW8SFw1B +qn7cITSG0G5MZ9pOw0KwT9irY1SdppBHVWIg7dkYWRCni0BPCFewastU+GVKH5PJ ++dYSvafhkEGD1bBu484KN9yX1BcHV41ZKR8pGgMM2QKBgQD3/0R2vZsTxoO1CHNI +IT7nBnuPIOP45iTFm/SNRY7e4dhQBy6HM6JD3Sr6Iksm8jRoboz+tnAso6l6QHRS +842uqBiOHdnka2RslDmrEun1lJv1MWuPM8JN0o8pYjVG/IRtaAFnYSEk72UoNy2h +bHC4OGFNwMbAadVm7DK5OiMfXwKBgQDGuBRxz7jkVZoMbbaeIqmGZAIejWkJweDZ +AK+txM+6Sg+Li14t190N3Xf6tyyidKhUAEWaINzLjZB+luxNaDXtxqWzLYHCwQKA +qfrjWVeZOS1clLya7jwl1jJqBtBiGKHv9eRL21hgX/9gX3odxqFMvX3vm6L7F1q1 +5CNApW0ZewKBgGO8qNcsWBLy8oM7G8n1fOvCwqyEaMrwG/fRSeALCnN+1tUQnljH +nkm2yBMC+cB3Bja9xzylOKXrSDyfcWjvBJsqhX2aacggnKnCTxMLL0aR9sr8jipw +gYN03Bijo5Oh+MxbWL0v5fmJweATmOljyE1+dzui/QvjRGz5L0kpJXj3AoGBAIa4 +3+t1B4WN312TuB4no8Tf4mvyNQcPcS/Nfk0RxD8o3Lcfal8sHMq8ng3Ux6bv7frd +IFLo+qfpts+L5HJqNz2X0ljSfkmZ7udp1hTySigwEmfU0rU61H5WZGFrczU+O/Ni +Qj+HWrgj/Q/KSxEKy+oqAcpDOtB+Odpc6+V1Aa0nAoGBAItWHP9UjTNFqOfyjZhG +qaUiZd1S2KyRR0l/lVcn+rJ46Yg5i+lMGwHMF1xPyWH4ELz+QCUX3doOI4yB2ikg +XXFcc8/bqgaR4AfOvP98T86s7+f33kaAKZsgyAFB2cjo+fz8ArTz+GjPeHbiOPaR +Ra7+BVwl9GE0+bCdirq+99GO -----END PRIVATE KEY----- diff --git a/Lib/slapdtest/certs/server.pem b/Lib/slapdtest/certs/server.pem index 45ae694..7e75059 100644 --- a/Lib/slapdtest/certs/server.pem +++ b/Lib/slapdtest/certs/server.pem @@ -5,31 +5,31 @@ Certificate: Signature Algorithm: sha256WithRSAEncryption Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA Validity - Not Before: Nov 28 13:49:28 2017 GMT - Not After : Nov 28 13:49:28 2021 GMT + Not Before: Dec 2 11:57:48 2017 GMT + Not After : Dec 2 11:57:48 2027 GMT Subject: C=DE, O=python-ldap, OU=slapd-test, CN=server cert for localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: - 00:d3:24:e0:27:65:d3:e7:09:39:b2:82:42:39:5d: - 41:ec:ba:4d:71:2f:87:9e:3f:13:1c:57:ef:07:60: - c7:d0:87:e6:f7:e7:80:b2:81:09:d1:72:38:f7:f2: - e4:3a:4b:bd:26:38:8c:82:ad:35:8a:36:b7:9c:56: - b9:d5:d3:1b:b8:a3:5e:80:91:24:6b:90:dd:00:56: - 97:d6:93:46:9e:d8:66:9c:70:35:7e:a3:cd:b1:f8: - d0:52:b5:f6:0d:5d:6d:b1:67:56:99:23:21:69:94: - 64:d4:cb:14:02:a6:c5:38:c8:25:fb:44:ce:d8:c2: - ad:df:33:a6:fc:7a:84:76:8d:13:46:0b:fb:8c:74: - d3:7f:ed:62:64:1d:f8:49:14:e6:05:a4:f2:7a:bc: - a3:a5:47:73:cf:ab:39:23:f1:64:6e:fe:29:65:eb: - 7f:a9:84:70:37:50:45:30:78:a1:b8:0e:86:8f:f3: - 93:34:5a:a1:d6:e0:ab:e9:d0:0e:2c:23:9b:8f:60: - 8d:a5:3e:b0:ea:51:fe:8b:59:cd:b6:81:4a:5c:14: - 53:43:45:e5:98:73:12:e8:6c:2b:00:79:3e:12:aa: - f1:02:f3:70:ef:e7:73:4a:41:2e:b0:b7:8c:cb:7b: - 05:46:d7:ef:1c:8f:27:2d:c2:fe:26:3c:06:ad:2f: - cb:83 + 00:c0:81:c2:3b:3e:3f:3d:03:0e:2b:ad:bf:8d:f2: + 3d:ed:d7:29:c9:81:74:61:40:dc:5b:c5:07:10:99: + 40:a2:f0:0b:69:18:a3:57:bb:e6:8c:f6:ed:87:c5: + 9e:bb:ec:02:df:86:c1:22:be:d4:00:e5:02:b3:2e: + 5e:46:d8:6d:88:41:ae:ee:ce:02:1c:a3:bd:ce:2f: + f9:0c:64:82:6d:ee:c2:9f:9e:f7:c0:0a:d4:a8:3a: + 50:f4:23:23:b3:54:41:2e:d0:05:40:ee:13:07:6f: + a5:25:23:49:82:35:f7:64:d8:55:85:6d:cd:67:52: + 62:00:10:18:48:38:36:c5:a0:d5:be:45:ce:a5:cf: + de:0d:b1:4a:80:ac:36:b2:bd:6a:40:b1:79:14:6e: + e6:d0:8a:4a:62:28:d5:f5:3a:93:8e:0b:d1:94:6c: + 48:70:23:f1:bd:d1:99:d4:83:d4:93:93:fd:a8:c6: + cb:f0:2e:56:1d:3a:11:a1:a7:27:e5:e7:7b:53:bb: + b7:8b:30:1a:e2:33:11:65:51:3b:e4:63:51:94:80: + f8:f4:7c:0f:e0:89:6b:42:7a:b1:8e:c9:e2:ae:d6: + 11:65:6d:2e:0b:8d:ba:2b:b1:fa:e5:c9:83:f0:7f: + 04:e0:dd:82:f8:85:59:ed:f5:f1:74:ae:98:f3:63: + 59:a5 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical @@ -39,48 +39,48 @@ Certificate: X509v3 Extended Key Usage: critical TLS Web Server Authentication X509v3 Subject Key Identifier: - 98:03:0F:65:1A:34:A9:E1:09:1B:EC:D0:ED:A8:11:E6:AE:85:1F:2C + 1B:78:45:40:0D:50:8A:8B:3B:C1:0A:F8:3F:7A:48:7B:A6:3C:28:09 X509v3 Authority Key Identifier: - keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + keyid:3B:1F:32:F4:FE:57:D1:6F:49:91:55:F2:24:F1:0A:66:3B:A5:EE:D4 X509v3 Subject Alternative Name: DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 Signature Algorithm: sha256WithRSAEncryption - a6:01:8e:6f:0f:db:35:1f:a2:03:f5:39:ca:16:5f:e5:5a:0f: - 7e:f1:24:8a:b9:6f:78:c1:2c:f7:3a:07:f1:27:46:47:e0:98: - a1:ec:23:38:30:b9:bc:66:ac:17:06:36:48:ad:5d:1d:b4:a2: - c1:2c:08:55:ff:00:01:04:26:60:38:a6:13:52:7b:d3:88:8a: - b1:1f:a4:cd:14:9b:c8:04:77:01:72:6d:fe:b5:8c:3a:25:e2: - 2b:83:73:4b:2e:c6:6f:20:8b:00:c7:3b:2e:de:62:e9:74:81: - c6:a5:f5:b1:f9:db:b9:58:f9:7c:a2:3f:4e:46:93:ae:af:75: - 01:77:ea:34:4e:82:dc:d3:53:39:c0:b0:f9:8a:86:8d:f5:f2: - c3:a0:fa:e4:a9:b3:2c:33:ba:78:d5:ef:12:05:33:4f:29:9b: - 88:41:52:73:5a:17:7e:bc:66:d0:dc:c7:14:6d:a5:99:78:67: - 81:36:76:29:63:de:76:d4:eb:ca:5c:82:1b:ae:7d:80:ed:32: - 69:b0:b7:7a:1d:e1:00:a8:b1:95:d3:4d:d5:e2:8c:f4:30:a7: - da:79:bd:f5:bb:7a:8d:c5:ec:1c:16:32:58:92:ad:fc:1c:83: - 49:ca:8c:f9:6d:d4:f7:2c:98:1a:25:47:36:16:4f:15:46:ea: - 71:78:f1:51 + ad:08:3f:7d:b1:09:a1:a5:6c:c3:58:80:1d:e5:33:a5:bb:c0: + 33:39:95:aa:88:ee:c4:8e:38:3b:59:a7:0e:39:74:6c:fe:11: + 33:5e:fa:50:cb:20:4b:67:b7:c9:5e:96:a7:9e:d8:47:46:e1: + ab:fe:5d:8b:9a:2d:1a:1b:43:08:f9:93:0f:2a:e3:ce:83:4a: + 94:cd:02:f0:8e:25:f2:41:0d:55:10:f5:4c:5b:39:8b:77:5e: + ab:78:16:64:a1:48:d5:e1:f6:69:9a:0f:d8:30:a6:cc:92:4d: + 81:df:46:74:ab:cf:1d:b7:d4:01:b9:6d:d5:f4:14:b8:d5:54: + 84:79:11:42:69:55:7f:74:ce:01:96:2f:3f:51:23:b3:11:fb: + 72:dc:4c:b9:a3:89:ef:31:e4:c0:49:06:fa:8d:09:71:e1:c1: + 74:a9:ed:f8:96:87:67:16:b5:5d:16:5d:59:70:ff:1c:b5:a1: + 6c:d2:22:11:3a:0e:6f:76:9b:69:cb:f3:85:a7:79:ad:53:f5: + 34:e8:87:cc:dd:09:51:25:e0:28:ee:79:a0:a3:dc:0a:dd:f0: + 1b:e3:c9:5f:14:d3:95:f5:12:4d:23:95:45:2c:3c:32:94:ad: + ce:1e:a0:5f:e6:e8:28:c6:f9:c7:fb:57:06:ad:0b:eb:86:ca: + 0e:d2:a8:67 -----BEGIN CERTIFICATE----- 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 -/ByDScqM+W3U9yyYGiVHNhZPFUbqcXjxUQ== +AQsFAAOCAQEArQg/fbEJoaVsw1iAHeUzpbvAMzmVqojuxI44O1mnDjl0bP4RM176 +UMsgS2e3yV6Wp57YR0bhq/5di5otGhtDCPmTDyrjzoNKlM0C8I4l8kENVRD1TFs5 +i3deq3gWZKFI1eH2aZoP2DCmzJJNgd9GdKvPHbfUAblt1fQUuNVUhHkRQmlVf3TO +AZYvP1EjsxH7ctxMuaOJ7zHkwEkG+o0JceHBdKnt+JaHZxa1XRZdWXD/HLWhbNIi +EToOb3abacvzhad5rVP1NOiHzN0JUSXgKO55oKPcCt3wG+PJXxTTlfUSTSOVRSw8 +MpStzh6gX+boKMb5x/tXBq0L64bKDtKoZw== -----END CERTIFICATE----- From 289ba45ebcd6d6041f87354bb784b6a7e1c358d0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 1 Dec 2017 18:03:21 +0100 Subject: [PATCH 3/5] slapdtest: Don't have code in __init__ --- Lib/slapdtest/__init__.py | 507 +---------------------------------- Lib/slapdtest/_slapdtest.py | 512 ++++++++++++++++++++++++++++++++++++ 2 files changed, 514 insertions(+), 505 deletions(-) create mode 100644 Lib/slapdtest/_slapdtest.py diff --git a/Lib/slapdtest/__init__.py b/Lib/slapdtest/__init__.py index 297bda7..a1acd2b 100644 --- a/Lib/slapdtest/__init__.py +++ b/Lib/slapdtest/__init__.py @@ -5,510 +5,7 @@ See https://www.python-ldap.org/ for details. """ -from __future__ import unicode_literals - __version__ = '3.0.0b1' -import os -import socket -import time -import subprocess -import logging -import atexit -from logging.handlers import SysLogHandler -import unittest - -# Switch off processing .ldaprc or ldap.conf before importing _ldap -os.environ['LDAPNOINIT'] = '1' - -import ldap -from ldap.compat import quote_plus - -HERE = os.path.abspath(os.path.dirname(__file__)) - -# a template string for generating simple slapd.conf file -SLAPD_CONF_TEMPLATE = r""" -serverID %(serverid)s -moduleload back_%(database)s -include "%(schema_prefix)s/core.schema" -loglevel %(loglevel)s -allow bind_v2 - -authz-regexp - "gidnumber=%(root_gid)s\\+uidnumber=%(root_uid)s,cn=peercred,cn=external,cn=auth" - "%(rootdn)s" - -database %(database)s -directory "%(directory)s" -suffix "%(suffix)s" -rootdn "%(rootdn)s" -rootpw "%(rootpw)s" - -TLSCACertificateFile "%(cafile)s" -TLSCertificateFile "%(servercert)s" -TLSCertificateKeyFile "%(serverkey)s" -# ignore missing client cert but fail with invalid client cert -TLSVerifyClient try - -authz-regexp - "C=DE, O=python-ldap, OU=slapd-test, CN=([A-Za-z]+)" - "ldap://ou=people,dc=local???($1)" - -""" - -LOCALHOST = '127.0.0.1' - - -def identity(test_item): - """Identity decorator - - """ - return test_item - - -def skip_unless_travis(reason): - """Skip test unless test case is executed on CI like Travis CI - """ - if os.environ.get('CI', False): - return identity - else: - return unittest.skip(reason) - - -def requires_tls(skip_nss=False): - """Decorator for TLS tests - - Tests are not skipped on CI (e.g. Travis CI) - - :param skip_nss: Skip test when libldap is compiled with NSS as TLS lib - """ - if not ldap.TLS_AVAIL: - return skip_unless_travis("test needs ldap.TLS_AVAIL") - elif skip_nss and ldap.get_option(ldap.OPT_X_TLS_PACKAGE) == 'MozNSS': - return skip_unless_travis( - "Test doesn't work correctly with Mozilla NSS, see " - "https://bugzilla.redhat.com/show_bug.cgi?id=1519167" - ) - else: - return identity - - -def combined_logger( - log_name, - log_level=logging.WARN, - sys_log_format='%(levelname)s %(message)s', - console_log_format='%(asctime)s %(levelname)s %(message)s', - ): - """ - Returns a combined SysLogHandler/StreamHandler logging instance - with formatters - """ - if 'LOGLEVEL' in os.environ: - log_level = os.environ['LOGLEVEL'] - try: - log_level = int(log_level) - except ValueError: - pass - # for writing to syslog - new_logger = logging.getLogger(log_name) - if sys_log_format and os.path.exists('/dev/log'): - my_syslog_formatter = logging.Formatter( - fmt=' '.join((log_name, sys_log_format))) - my_syslog_handler = logging.handlers.SysLogHandler( - address='/dev/log', - facility=SysLogHandler.LOG_DAEMON, - ) - my_syslog_handler.setFormatter(my_syslog_formatter) - new_logger.addHandler(my_syslog_handler) - if console_log_format: - my_stream_formatter = logging.Formatter(fmt=console_log_format) - my_stream_handler = logging.StreamHandler() - my_stream_handler.setFormatter(my_stream_formatter) - new_logger.addHandler(my_stream_handler) - new_logger.setLevel(log_level) - return new_logger # end of combined_logger() - - -class SlapdObject(object): - """ - Controller class for a slapd instance, OpenLDAP's server. - - This class creates a temporary data store for slapd, runs it - listening on a private Unix domain socket and TCP port, - and initializes it with a top-level entry and the root user. - - When a reference to an instance of this class is lost, the slapd - server is shut down. - """ - slapd_conf_template = SLAPD_CONF_TEMPLATE - database = 'mdb' - suffix = 'dc=slapd-test,dc=python-ldap,dc=org' - root_cn = 'Manager' - root_dn = 'cn=%s,%s' % (root_cn, suffix) - root_pw = 'password' - slapd_loglevel = 'stats stats2' - # use SASL/EXTERNAL via LDAPI when invoking OpenLDAP CLI tools - cli_sasl_external = True - local_host = '127.0.0.1' - testrunsubdirs = ( - 'schema', - ) - openldap_schema_files = ( - 'core.schema', - ) - - TMPDIR = os.environ.get('TMP', os.getcwd()) - SBINDIR = os.environ.get('SBIN', '/usr/sbin') - BINDIR = os.environ.get('BIN', '/usr/bin') - if 'SCHEMA' in os.environ: - SCHEMADIR = os.environ['SCHEMA'] - elif os.path.isdir("/etc/openldap/schema"): - SCHEMADIR = "/etc/openldap/schema" - elif os.path.isdir("/etc/ldap/schema"): - SCHEMADIR = "/etc/ldap/schema" - else: - SCHEMADIR = None - PATH_LDAPADD = os.path.join(BINDIR, 'ldapadd') - PATH_LDAPDELETE = os.path.join(BINDIR, 'ldapdelete') - PATH_LDAPMODIFY = os.path.join(BINDIR, 'ldapmodify') - PATH_LDAPWHOAMI = os.path.join(BINDIR, 'ldapwhoami') - PATH_SLAPD = os.environ.get('SLAPD', os.path.join(SBINDIR, 'slapd')) - PATH_SLAPTEST = os.path.join(SBINDIR, 'slaptest') - - # time in secs to wait before trying to access slapd via LDAP (again) - _start_sleep = 1.5 - - # create loggers once, multiple calls mess up refleak tests - _log = combined_logger('python-ldap-test') - - def __init__(self): - self._proc = None - self._port = self._avail_tcp_port() - self.server_id = self._port % 4096 - self.testrundir = os.path.join(self.TMPDIR, 'python-ldap-test-%d' % self._port) - self._schema_prefix = os.path.join(self.testrundir, 'schema') - self._slapd_conf = os.path.join(self.testrundir, 'slapd.conf') - self._db_directory = os.path.join(self.testrundir, "openldap-data") - self.ldap_uri = "ldap://%s:%d/" % (LOCALHOST, self._port) - ldapi_path = os.path.join(self.testrundir, 'ldapi') - self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path) - # TLS certs - self.cafile = os.path.join(HERE, 'certs/ca.pem') - self.servercert = os.path.join(HERE, 'certs/server.pem') - self.serverkey = os.path.join(HERE, 'certs/server.key') - self.clientcert = os.path.join(HERE, 'certs/client.pem') - self.clientkey = os.path.join(HERE, 'certs/client.key') - - def _check_requirements(self): - binaries = [ - self.PATH_LDAPADD, self.PATH_LDAPMODIFY, self.PATH_LDAPWHOAMI, - self.PATH_SLAPD, self.PATH_SLAPTEST - ] - for binary in binaries: - if not os.path.isfile(binary): - raise ValueError('Binary {} is missing.'.format(binary)) - if self.SCHEMADIR is None: - raise ValueError('SCHEMADIR is None, ldap schemas are missing.') - - def setup_rundir(self): - """ - creates rundir structure - - for setting up a custom directory structure you have to override - this method - """ - os.mkdir(self.testrundir) - os.mkdir(self._db_directory) - self._create_sub_dirs(self.testrunsubdirs) - self._ln_schema_files(self.openldap_schema_files, self.SCHEMADIR) - - def _cleanup_rundir(self): - """ - Recursively delete whole directory specified by `path' - """ - # cleanup_rundir() is called in atexit handler. Until Python 3.4, - # the rest of the world is already destroyed. - import os, os.path - if not os.path.exists(self.testrundir): - return - self._log.debug('clean-up %s', self.testrundir) - for dirpath, dirnames, filenames in os.walk( - self.testrundir, - topdown=False - ): - for filename in filenames: - self._log.debug('remove %s', os.path.join(dirpath, filename)) - os.remove(os.path.join(dirpath, filename)) - for dirname in dirnames: - self._log.debug('rmdir %s', os.path.join(dirpath, dirname)) - os.rmdir(os.path.join(dirpath, dirname)) - os.rmdir(self.testrundir) - self._log.info('cleaned-up %s', self.testrundir) - - def _avail_tcp_port(self): - """ - find an available port for TCP connection - """ - sock = socket.socket() - try: - sock.bind((self.local_host, 0)) - port = sock.getsockname()[1] - finally: - sock.close() - self._log.info('Found available port %d', port) - return port - - def gen_config(self): - """ - generates a slapd.conf and returns it as one string - - for generating specific static configuration files you have to - override this method - """ - config_dict = { - 'serverid': hex(self.server_id), - 'schema_prefix':self._schema_prefix, - 'loglevel': self.slapd_loglevel, - 'database': self.database, - 'directory': self._db_directory, - 'suffix': self.suffix, - 'rootdn': self.root_dn, - 'rootpw': self.root_pw, - 'root_uid': os.getuid(), - 'root_gid': os.getgid(), - 'cafile': self.cafile, - 'servercert': self.servercert, - 'serverkey': self.serverkey, - } - return self.slapd_conf_template % config_dict - - def _create_sub_dirs(self, dir_names): - """ - create sub-directories beneath self.testrundir - """ - for dname in dir_names: - dir_name = os.path.join(self.testrundir, dname) - self._log.debug('Create directory %s', dir_name) - os.mkdir(dir_name) - - def _ln_schema_files(self, file_names, source_dir): - """ - write symbolic links to original schema files - """ - for fname in file_names: - ln_source = os.path.join(source_dir, fname) - ln_target = os.path.join(self._schema_prefix, fname) - self._log.debug('Create symlink %s -> %s', ln_source, ln_target) - os.symlink(ln_source, ln_target) - - def _write_config(self): - """Writes the slapd.conf file out, and returns the path to it.""" - self._log.debug('Writing config to %s', self._slapd_conf) - with open(self._slapd_conf, 'w') as config_file: - config_file.write(self.gen_config()) - self._log.info('Wrote config to %s', self._slapd_conf) - - def _test_config(self): - self._log.debug('testing config %s', self._slapd_conf) - popen_list = [ - self.PATH_SLAPTEST, - "-f", self._slapd_conf, - '-u', - ] - if self._log.isEnabledFor(logging.DEBUG): - popen_list.append('-v') - popen_list.extend(['-d', 'config']) - else: - popen_list.append('-Q') - proc = subprocess.Popen(popen_list) - if proc.wait() != 0: - raise RuntimeError("configuration test failed") - self._log.info("config ok: %s", self._slapd_conf) - - def _start_slapd(self): - """ - Spawns/forks the slapd process - """ - slapd_args = [ - self.PATH_SLAPD, - '-f', self._slapd_conf, - '-F', self.testrundir, - '-h', '%s' % ' '.join((self.ldap_uri, self.ldapi_uri)), - ] - if self._log.isEnabledFor(logging.DEBUG): - slapd_args.extend(['-d', '-1']) - else: - slapd_args.extend(['-d', '0']) - self._log.info('starting slapd: %r', ' '.join(slapd_args)) - self._proc = subprocess.Popen(slapd_args) - # Waits until the LDAP server socket is open, or slapd crashed - while 1: - if self._proc.poll() is not None: - self._stopped() - raise RuntimeError("slapd exited before opening port") - time.sleep(self._start_sleep) - try: - self._log.debug("slapd connection check to %s", self.ldapi_uri) - self.ldapwhoami() - except RuntimeError: - pass - else: - return - - def start(self): - """ - Starts the slapd server process running, and waits for it to come up. - """ - - if self._proc is None: - self._check_requirements() - # prepare directory structure - atexit.register(self.stop) - self._cleanup_rundir() - self.setup_rundir() - self._write_config() - self._test_config() - self._start_slapd() - self._log.debug( - 'slapd with pid=%d listening on %s and %s', - self._proc.pid, self.ldap_uri, self.ldapi_uri - ) - - def stop(self): - """ - Stops the slapd server, and waits for it to terminate and cleans up - """ - if self._proc is not None: - self._log.debug('stopping slapd with pid %d', self._proc.pid) - self._proc.terminate() - self.wait() - self._cleanup_rundir() - if hasattr(atexit, 'unregister'): - # Python 3 - atexit.unregister(self.stop) - elif hasattr(atexit, '_exithandlers'): - # Python 2, can be None during process shutdown - try: - atexit._exithandlers.remove(self.stop) - except ValueError: - pass - - def restart(self): - """ - Restarts the slapd server with same data - """ - self._proc.terminate() - self.wait() - self._start_slapd() - - def wait(self): - """Waits for the slapd process to terminate by itself.""" - if self._proc: - self._proc.wait() - self._stopped() - - def _stopped(self): - """Called when the slapd server is known to have terminated""" - if self._proc is not None: - self._log.info('slapd[%d] terminated', self._proc.pid) - self._proc = None - - def _cli_auth_args(self): - if self.cli_sasl_external: - authc_args = [ - '-Y', 'EXTERNAL', - ] - if not self._log.isEnabledFor(logging.DEBUG): - authc_args.append('-Q') - else: - authc_args = [ - '-x', - '-D', self.root_dn, - '-w', self.root_pw, - ] - return authc_args - - def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None, stdin_data=None): - args = [ - ldapcommand, - '-H', ldap_uri or self.ldapi_uri, - ] + self._cli_auth_args() + (extra_args or []) - self._log.debug('Run command: %r', ' '.join(args)) - proc = subprocess.Popen( - args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE - ) - self._log.debug('stdin_data=%r', stdin_data) - stdout_data, stderr_data = proc.communicate(stdin_data) - if stdout_data is not None: - self._log.debug('stdout_data=%r', stdout_data) - if stderr_data is not None: - self._log.debug('stderr_data=%r', stderr_data) - if proc.wait() != 0: - raise RuntimeError( - '{!r} process failed:\n{!r}\n{!r}'.format( - args, stdout_data, stderr_data - ) - ) - return stdout_data, stderr_data - - def ldapwhoami(self, extra_args=None): - """ - Runs ldapwhoami on this slapd instance - """ - self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args) - - def ldapadd(self, ldif, extra_args=None): - """ - Runs ldapadd on this slapd instance, passing it the ldif content - """ - self._cli_popen(self.PATH_LDAPADD, extra_args=extra_args, - stdin_data=ldif.encode('utf-8')) - - def ldapmodify(self, ldif, extra_args=None): - """ - Runs ldapadd on this slapd instance, passing it the ldif content - """ - self._cli_popen(self.PATH_LDAPMODIFY, extra_args=extra_args, - stdin_data=ldif.encode('utf-8')) - - def ldapdelete(self, dn, recursive=False, extra_args=None): - """ - Runs ldapdelete on this slapd instance, deleting 'dn' - """ - if extra_args is None: - extra_args = [] - if recursive: - extra_args.append('-r') - extra_args.append(dn) - self._cli_popen(self.PATH_LDAPDELETE, extra_args=extra_args) - - -class SlapdTestCase(unittest.TestCase): - """ - test class which also clones or initializes a running slapd - """ - - server_class = SlapdObject - server = None - ldap_object_class = None - - def _open_ldap_conn(self, who=None, cred=None, **kwargs): - """ - return a LDAPObject instance after simple bind - """ - ldap_conn = self.ldap_object_class(self.server.ldap_uri, **kwargs) - ldap_conn.protocol_version = 3 - #ldap_conn.set_option(ldap.OPT_REFERRALS, 0) - ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) - return ldap_conn - - @classmethod - def setUpClass(cls): - cls.server = cls.server_class() - cls.server.start() - cls.server = cls.server - - @classmethod - def tearDownClass(cls): - cls.server.stop() +from slapdtest._slapdtest import SlapdObject, SlapdTestCase, SysLogHandler +from slapdtest._slapdtest import skip_unless_ci, requires_tls diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py new file mode 100644 index 0000000..884a1ee --- /dev/null +++ b/Lib/slapdtest/_slapdtest.py @@ -0,0 +1,512 @@ +# -*- coding: utf-8 -*- +""" +slapdtest - module for spawning test instances of OpenLDAP's slapd server + +See https://www.python-ldap.org/ for details. +""" + +from __future__ import unicode_literals + +import os +import socket +import time +import subprocess +import logging +import atexit +from logging.handlers import SysLogHandler +import unittest + +# Switch off processing .ldaprc or ldap.conf before importing _ldap +os.environ['LDAPNOINIT'] = '1' + +import ldap +from ldap.compat import quote_plus + +HERE = os.path.abspath(os.path.dirname(__file__)) + +# a template string for generating simple slapd.conf file +SLAPD_CONF_TEMPLATE = r""" +serverID %(serverid)s +moduleload back_%(database)s +include "%(schema_prefix)s/core.schema" +loglevel %(loglevel)s +allow bind_v2 + +authz-regexp + "gidnumber=%(root_gid)s\\+uidnumber=%(root_uid)s,cn=peercred,cn=external,cn=auth" + "%(rootdn)s" + +database %(database)s +directory "%(directory)s" +suffix "%(suffix)s" +rootdn "%(rootdn)s" +rootpw "%(rootpw)s" + +TLSCACertificateFile "%(cafile)s" +TLSCertificateFile "%(servercert)s" +TLSCertificateKeyFile "%(serverkey)s" +# ignore missing client cert but fail with invalid client cert +TLSVerifyClient try + +authz-regexp + "C=DE, O=python-ldap, OU=slapd-test, CN=([A-Za-z]+)" + "ldap://ou=people,dc=local???($1)" + +""" + +LOCALHOST = '127.0.0.1' + + +def identity(test_item): + """Identity decorator + + """ + return test_item + + +def skip_unless_travis(reason): + """Skip test unless test case is executed on CI like Travis CI + """ + if os.environ.get('CI', False): + return identity + else: + return unittest.skip(reason) + + +def requires_tls(skip_nss=False): + """Decorator for TLS tests + + Tests are not skipped on CI (e.g. Travis CI) + + :param skip_nss: Skip test when libldap is compiled with NSS as TLS lib + """ + if not ldap.TLS_AVAIL: + return skip_unless_travis("test needs ldap.TLS_AVAIL") + elif skip_nss and ldap.get_option(ldap.OPT_X_TLS_PACKAGE) == 'MozNSS': + return skip_unless_travis( + "Test doesn't work correctly with Mozilla NSS, see " + "https://bugzilla.redhat.com/show_bug.cgi?id=1519167" + ) + else: + return identity + + +def combined_logger( + log_name, + log_level=logging.WARN, + sys_log_format='%(levelname)s %(message)s', + console_log_format='%(asctime)s %(levelname)s %(message)s', + ): + """ + Returns a combined SysLogHandler/StreamHandler logging instance + with formatters + """ + if 'LOGLEVEL' in os.environ: + log_level = os.environ['LOGLEVEL'] + try: + log_level = int(log_level) + except ValueError: + pass + # for writing to syslog + new_logger = logging.getLogger(log_name) + if sys_log_format and os.path.exists('/dev/log'): + my_syslog_formatter = logging.Formatter( + fmt=' '.join((log_name, sys_log_format))) + my_syslog_handler = logging.handlers.SysLogHandler( + address='/dev/log', + facility=SysLogHandler.LOG_DAEMON, + ) + my_syslog_handler.setFormatter(my_syslog_formatter) + new_logger.addHandler(my_syslog_handler) + if console_log_format: + my_stream_formatter = logging.Formatter(fmt=console_log_format) + my_stream_handler = logging.StreamHandler() + my_stream_handler.setFormatter(my_stream_formatter) + new_logger.addHandler(my_stream_handler) + new_logger.setLevel(log_level) + return new_logger # end of combined_logger() + + +class SlapdObject(object): + """ + Controller class for a slapd instance, OpenLDAP's server. + + This class creates a temporary data store for slapd, runs it + listening on a private Unix domain socket and TCP port, + and initializes it with a top-level entry and the root user. + + When a reference to an instance of this class is lost, the slapd + server is shut down. + """ + slapd_conf_template = SLAPD_CONF_TEMPLATE + database = 'mdb' + suffix = 'dc=slapd-test,dc=python-ldap,dc=org' + root_cn = 'Manager' + root_dn = 'cn=%s,%s' % (root_cn, suffix) + root_pw = 'password' + slapd_loglevel = 'stats stats2' + # use SASL/EXTERNAL via LDAPI when invoking OpenLDAP CLI tools + cli_sasl_external = True + local_host = '127.0.0.1' + testrunsubdirs = ( + 'schema', + ) + openldap_schema_files = ( + 'core.schema', + ) + + TMPDIR = os.environ.get('TMP', os.getcwd()) + SBINDIR = os.environ.get('SBIN', '/usr/sbin') + BINDIR = os.environ.get('BIN', '/usr/bin') + if 'SCHEMA' in os.environ: + SCHEMADIR = os.environ['SCHEMA'] + elif os.path.isdir("/etc/openldap/schema"): + SCHEMADIR = "/etc/openldap/schema" + elif os.path.isdir("/etc/ldap/schema"): + SCHEMADIR = "/etc/ldap/schema" + else: + SCHEMADIR = None + PATH_LDAPADD = os.path.join(BINDIR, 'ldapadd') + PATH_LDAPDELETE = os.path.join(BINDIR, 'ldapdelete') + PATH_LDAPMODIFY = os.path.join(BINDIR, 'ldapmodify') + PATH_LDAPWHOAMI = os.path.join(BINDIR, 'ldapwhoami') + PATH_SLAPD = os.environ.get('SLAPD', os.path.join(SBINDIR, 'slapd')) + PATH_SLAPTEST = os.path.join(SBINDIR, 'slaptest') + + # time in secs to wait before trying to access slapd via LDAP (again) + _start_sleep = 1.5 + + # create loggers once, multiple calls mess up refleak tests + _log = combined_logger('python-ldap-test') + + def __init__(self): + self._proc = None + self._port = self._avail_tcp_port() + self.server_id = self._port % 4096 + self.testrundir = os.path.join(self.TMPDIR, 'python-ldap-test-%d' % self._port) + self._schema_prefix = os.path.join(self.testrundir, 'schema') + self._slapd_conf = os.path.join(self.testrundir, 'slapd.conf') + self._db_directory = os.path.join(self.testrundir, "openldap-data") + self.ldap_uri = "ldap://%s:%d/" % (LOCALHOST, self._port) + ldapi_path = os.path.join(self.testrundir, 'ldapi') + self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path) + # TLS certs + self.cafile = os.path.join(HERE, 'certs/ca.pem') + self.servercert = os.path.join(HERE, 'certs/server.pem') + self.serverkey = os.path.join(HERE, 'certs/server.key') + self.clientcert = os.path.join(HERE, 'certs/client.pem') + self.clientkey = os.path.join(HERE, 'certs/client.key') + + def _check_requirements(self): + binaries = [ + self.PATH_LDAPADD, self.PATH_LDAPMODIFY, self.PATH_LDAPWHOAMI, + self.PATH_SLAPD, self.PATH_SLAPTEST + ] + for binary in binaries: + if not os.path.isfile(binary): + raise ValueError('Binary {} is missing.'.format(binary)) + if self.SCHEMADIR is None: + raise ValueError('SCHEMADIR is None, ldap schemas are missing.') + + def setup_rundir(self): + """ + creates rundir structure + + for setting up a custom directory structure you have to override + this method + """ + os.mkdir(self.testrundir) + os.mkdir(self._db_directory) + self._create_sub_dirs(self.testrunsubdirs) + self._ln_schema_files(self.openldap_schema_files, self.SCHEMADIR) + + def _cleanup_rundir(self): + """ + Recursively delete whole directory specified by `path' + """ + # cleanup_rundir() is called in atexit handler. Until Python 3.4, + # the rest of the world is already destroyed. + import os, os.path + if not os.path.exists(self.testrundir): + return + self._log.debug('clean-up %s', self.testrundir) + for dirpath, dirnames, filenames in os.walk( + self.testrundir, + topdown=False + ): + for filename in filenames: + self._log.debug('remove %s', os.path.join(dirpath, filename)) + os.remove(os.path.join(dirpath, filename)) + for dirname in dirnames: + self._log.debug('rmdir %s', os.path.join(dirpath, dirname)) + os.rmdir(os.path.join(dirpath, dirname)) + os.rmdir(self.testrundir) + self._log.info('cleaned-up %s', self.testrundir) + + def _avail_tcp_port(self): + """ + find an available port for TCP connection + """ + sock = socket.socket() + try: + sock.bind((self.local_host, 0)) + port = sock.getsockname()[1] + finally: + sock.close() + self._log.info('Found available port %d', port) + return port + + def gen_config(self): + """ + generates a slapd.conf and returns it as one string + + for generating specific static configuration files you have to + override this method + """ + config_dict = { + 'serverid': hex(self.server_id), + 'schema_prefix':self._schema_prefix, + 'loglevel': self.slapd_loglevel, + 'database': self.database, + 'directory': self._db_directory, + 'suffix': self.suffix, + 'rootdn': self.root_dn, + 'rootpw': self.root_pw, + 'root_uid': os.getuid(), + 'root_gid': os.getgid(), + 'cafile': self.cafile, + 'servercert': self.servercert, + 'serverkey': self.serverkey, + } + return self.slapd_conf_template % config_dict + + def _create_sub_dirs(self, dir_names): + """ + create sub-directories beneath self.testrundir + """ + for dname in dir_names: + dir_name = os.path.join(self.testrundir, dname) + self._log.debug('Create directory %s', dir_name) + os.mkdir(dir_name) + + def _ln_schema_files(self, file_names, source_dir): + """ + write symbolic links to original schema files + """ + for fname in file_names: + ln_source = os.path.join(source_dir, fname) + ln_target = os.path.join(self._schema_prefix, fname) + self._log.debug('Create symlink %s -> %s', ln_source, ln_target) + os.symlink(ln_source, ln_target) + + def _write_config(self): + """Writes the slapd.conf file out, and returns the path to it.""" + self._log.debug('Writing config to %s', self._slapd_conf) + with open(self._slapd_conf, 'w') as config_file: + config_file.write(self.gen_config()) + self._log.info('Wrote config to %s', self._slapd_conf) + + def _test_config(self): + self._log.debug('testing config %s', self._slapd_conf) + popen_list = [ + self.PATH_SLAPTEST, + "-f", self._slapd_conf, + '-u', + ] + if self._log.isEnabledFor(logging.DEBUG): + popen_list.append('-v') + popen_list.extend(['-d', 'config']) + else: + popen_list.append('-Q') + proc = subprocess.Popen(popen_list) + if proc.wait() != 0: + raise RuntimeError("configuration test failed") + self._log.info("config ok: %s", self._slapd_conf) + + def _start_slapd(self): + """ + Spawns/forks the slapd process + """ + slapd_args = [ + self.PATH_SLAPD, + '-f', self._slapd_conf, + '-F', self.testrundir, + '-h', '%s' % ' '.join((self.ldap_uri, self.ldapi_uri)), + ] + if self._log.isEnabledFor(logging.DEBUG): + slapd_args.extend(['-d', '-1']) + else: + slapd_args.extend(['-d', '0']) + self._log.info('starting slapd: %r', ' '.join(slapd_args)) + self._proc = subprocess.Popen(slapd_args) + # Waits until the LDAP server socket is open, or slapd crashed + while 1: + if self._proc.poll() is not None: + self._stopped() + raise RuntimeError("slapd exited before opening port") + time.sleep(self._start_sleep) + try: + self._log.debug("slapd connection check to %s", self.ldapi_uri) + self.ldapwhoami() + except RuntimeError: + pass + else: + return + + def start(self): + """ + Starts the slapd server process running, and waits for it to come up. + """ + + if self._proc is None: + self._check_requirements() + # prepare directory structure + atexit.register(self.stop) + self._cleanup_rundir() + self.setup_rundir() + self._write_config() + self._test_config() + self._start_slapd() + self._log.debug( + 'slapd with pid=%d listening on %s and %s', + self._proc.pid, self.ldap_uri, self.ldapi_uri + ) + + def stop(self): + """ + Stops the slapd server, and waits for it to terminate and cleans up + """ + if self._proc is not None: + self._log.debug('stopping slapd with pid %d', self._proc.pid) + self._proc.terminate() + self.wait() + self._cleanup_rundir() + if hasattr(atexit, 'unregister'): + # Python 3 + atexit.unregister(self.stop) + elif hasattr(atexit, '_exithandlers'): + # Python 2, can be None during process shutdown + try: + atexit._exithandlers.remove(self.stop) + except ValueError: + pass + + def restart(self): + """ + Restarts the slapd server with same data + """ + self._proc.terminate() + self.wait() + self._start_slapd() + + def wait(self): + """Waits for the slapd process to terminate by itself.""" + if self._proc: + self._proc.wait() + self._stopped() + + def _stopped(self): + """Called when the slapd server is known to have terminated""" + if self._proc is not None: + self._log.info('slapd[%d] terminated', self._proc.pid) + self._proc = None + + def _cli_auth_args(self): + if self.cli_sasl_external: + authc_args = [ + '-Y', 'EXTERNAL', + ] + if not self._log.isEnabledFor(logging.DEBUG): + authc_args.append('-Q') + else: + authc_args = [ + '-x', + '-D', self.root_dn, + '-w', self.root_pw, + ] + return authc_args + + def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None, stdin_data=None): + args = [ + ldapcommand, + '-H', ldap_uri or self.ldapi_uri, + ] + self._cli_auth_args() + (extra_args or []) + self._log.debug('Run command: %r', ' '.join(args)) + proc = subprocess.Popen( + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + self._log.debug('stdin_data=%r', stdin_data) + stdout_data, stderr_data = proc.communicate(stdin_data) + if stdout_data is not None: + self._log.debug('stdout_data=%r', stdout_data) + if stderr_data is not None: + self._log.debug('stderr_data=%r', stderr_data) + if proc.wait() != 0: + raise RuntimeError( + '{!r} process failed:\n{!r}\n{!r}'.format( + args, stdout_data, stderr_data + ) + ) + return stdout_data, stderr_data + + def ldapwhoami(self, extra_args=None): + """ + Runs ldapwhoami on this slapd instance + """ + self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args) + + def ldapadd(self, ldif, extra_args=None): + """ + Runs ldapadd on this slapd instance, passing it the ldif content + """ + self._cli_popen(self.PATH_LDAPADD, extra_args=extra_args, + stdin_data=ldif.encode('utf-8')) + + def ldapmodify(self, ldif, extra_args=None): + """ + Runs ldapadd on this slapd instance, passing it the ldif content + """ + self._cli_popen(self.PATH_LDAPMODIFY, extra_args=extra_args, + stdin_data=ldif.encode('utf-8')) + + def ldapdelete(self, dn, recursive=False, extra_args=None): + """ + Runs ldapdelete on this slapd instance, deleting 'dn' + """ + if extra_args is None: + extra_args = [] + if recursive: + extra_args.append('-r') + extra_args.append(dn) + self._cli_popen(self.PATH_LDAPDELETE, extra_args=extra_args) + + +class SlapdTestCase(unittest.TestCase): + """ + test class which also clones or initializes a running slapd + """ + + server_class = SlapdObject + server = None + ldap_object_class = None + + def _open_ldap_conn(self, who=None, cred=None, **kwargs): + """ + return a LDAPObject instance after simple bind + """ + ldap_conn = self.ldap_object_class(self.server.ldap_uri, **kwargs) + ldap_conn.protocol_version = 3 + #ldap_conn.set_option(ldap.OPT_REFERRALS, 0) + ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) + return ldap_conn + + @classmethod + def setUpClass(cls): + cls.server = cls.server_class() + cls.server.start() + cls.server = cls.server + + @classmethod + def tearDownClass(cls): + cls.server.stop() From 53fd80a2da59520391e738634f7191e3973a427e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 1 Dec 2017 18:03:40 +0100 Subject: [PATCH 4/5] slapdtest: Use "CI" instead of "Travis" in function name We want this to work on any kind of CI, not just the one we use now. --- Lib/slapdtest/_slapdtest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index 884a1ee..2900581 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -64,7 +64,7 @@ def identity(test_item): return test_item -def skip_unless_travis(reason): +def skip_unless_ci(reason): """Skip test unless test case is executed on CI like Travis CI """ if os.environ.get('CI', False): @@ -81,9 +81,9 @@ def requires_tls(skip_nss=False): :param skip_nss: Skip test when libldap is compiled with NSS as TLS lib """ if not ldap.TLS_AVAIL: - return skip_unless_travis("test needs ldap.TLS_AVAIL") + return skip_unless_ci("test needs ldap.TLS_AVAIL") elif skip_nss and ldap.get_option(ldap.OPT_X_TLS_PACKAGE) == 'MozNSS': - return skip_unless_travis( + return skip_unless_ci( "Test doesn't work correctly with Mozilla NSS, see " "https://bugzilla.redhat.com/show_bug.cgi?id=1519167" ) From 04e6f18eed7e2453dc5639bcac09c5182d2626e1 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 4 Dec 2017 11:10:55 +0100 Subject: [PATCH 5/5] Announce that slapdtest is now a package --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b64c263..05283bf 100644 --- a/CHANGES +++ b/CHANGES @@ -70,10 +70,11 @@ and, thanks to Michael Ströder: * module ldif now uses functions b64encode() and b64decode() * fixed pickling and restoring of ReconnectLDAPObject -Lib/slapdtest.py +Lib/slapdtest * Automatically try some common locations for SCHEMADIR * Ensure server is stopped when the process exits * Check for LDAP schema and slapd binaries +* slapdtest is now a package and includes testing certificates Tests/ * Expand cidict membership test