From 66ec1d81ce7f092fb690e94768972329ae936cb7 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 9 Jun 2016 14:47:08 -0400 Subject: [PATCH] Switch to install custom LDAP cert by name --- conf/init/install_custom_certs.sh | 8 ++++++++ data/users/__init__.py | 7 +------ data/users/externalldap.py | 25 +++++++------------------ util/config/validator.py | 16 ++++++++-------- 4 files changed, 24 insertions(+), 32 deletions(-) create mode 100755 conf/init/install_custom_certs.sh diff --git a/conf/init/install_custom_certs.sh b/conf/init/install_custom_certs.sh new file mode 100755 index 000000000..ed60227b8 --- /dev/null +++ b/conf/init/install_custom_certs.sh @@ -0,0 +1,8 @@ +#! /bin/bash +set -e + +if [ -e /conf/stack/ldap.crt ] +then + cp /conf/stack/ldap.crt /usr/local/share/ca-certificates/ldap.crt + /usr/sbin/update-ca-certificates +fi \ No newline at end of file diff --git a/data/users/__init__.py b/data/users/__init__.py index 4c1f2ba4c..e093f6993 100644 --- a/data/users/__init__.py +++ b/data/users/__init__.py @@ -46,13 +46,8 @@ def get_users_handler(config, config_provider, override_config_dir): email_attr = config.get('LDAP_EMAIL_ATTR', 'mail') allow_tls_fallback = config.get('LDAP_ALLOW_INSECURE_FALLBACK', False) - tls_cert_path = None - if config_provider.volume_file_exists(LDAP_CERT_FILENAME): - with config_provider.get_volume_file(LDAP_CERT_FILENAME) as f: - tls_cert_path = f.name - return LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, - tls_cert_path, allow_tls_fallback) + allow_tls_fallback) if authentication_type == 'JWT': verify_url = config.get('JWT_VERIFY_ENDPOINT') diff --git a/data/users/externalldap.py b/data/users/externalldap.py index aba863b5d..561891438 100644 --- a/data/users/externalldap.py +++ b/data/users/externalldap.py @@ -3,31 +3,27 @@ import logging import os from collections import namedtuple -from datetime import datetime from data.users.federated import FederatedUsers, VerifiedCredentials logger = logging.getLogger(__name__) class LDAPConnectionBuilder(object): - def __init__(self, ldap_uri, user_dn, user_pw, tls_cert_path=None, allow_tls_fallback=False): + def __init__(self, ldap_uri, user_dn, user_pw, allow_tls_fallback=False): self._ldap_uri = ldap_uri self._user_dn = user_dn self._user_pw = user_pw - self._tls_cert_path = tls_cert_path self._allow_tls_fallback = allow_tls_fallback def get_connection(self): - return LDAPConnection(self._ldap_uri, self._user_dn, self._user_pw, - self._tls_cert_path, self._allow_tls_fallback ) + return LDAPConnection(self._ldap_uri, self._user_dn, self._user_pw, self._allow_tls_fallback) class LDAPConnection(object): - def __init__(self, ldap_uri, user_dn, user_pw, tls_cert_path=None, allow_tls_fallback=False): + def __init__(self, ldap_uri, user_dn, user_pw, allow_tls_fallback=False): self._ldap_uri = ldap_uri self._user_dn = user_dn self._user_pw = user_pw - self._tls_cert_path = tls_cert_path self._allow_tls_fallback = allow_tls_fallback self._conn = None @@ -37,10 +33,6 @@ class LDAPConnection(object): self._conn = ldap.initialize(self._ldap_uri, trace_level=trace_level) self._conn.set_option(ldap.OPT_REFERRALS, 1) - if self._tls_cert_path is not None: - logger.debug('LDAP using custom TLS certificate path %s', self._tls_cert_path) - self._conn.set_option(ldap.OPT_X_TLS_CERTFILE, self._tls_cert_path) - if self._allow_tls_fallback: logger.debug('TLS Fallback enabled in LDAP') self._conn.set_option(ldap.OPT_X_TLS_TRY, 1) @@ -56,18 +48,15 @@ class LDAPUsers(FederatedUsers): _LDAPResult = namedtuple('LDAPResult', ['dn', 'attrs']) def __init__(self, ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, - tls_cert_path=None, allow_tls_fallback=False): + allow_tls_fallback=False): super(LDAPUsers, self).__init__('ldap') - self._ldap = LDAPConnectionBuilder(ldap_uri, admin_dn, admin_passwd, tls_cert_path, - allow_tls_fallback) - + self._ldap = LDAPConnectionBuilder(ldap_uri, admin_dn, admin_passwd, allow_tls_fallback) self._ldap_uri = ldap_uri self._base_dn = base_dn self._user_rdn = user_rdn self._uid_attr = uid_attr self._email_attr = email_attr - self._tls_cert_path = tls_cert_path self._allow_tls_fallback = allow_tls_fallback def _get_ldap_referral_dn(self, referral_exception): @@ -159,7 +148,7 @@ class LDAPUsers(FederatedUsers): # First validate the password by binding as the user try: with LDAPConnection(self._ldap_uri, found_dn, password.encode('utf-8'), - self._tls_cert_path, self._allow_tls_fallback): + self._allow_tls_fallback): pass except ldap.REFERRAL as re: referral_dn = self._get_ldap_referral_dn(re) @@ -168,7 +157,7 @@ class LDAPUsers(FederatedUsers): try: with LDAPConnection(self._ldap_uri, referral_dn, password.encode('utf-8'), - self._tls_cert_path, self._allow_tls_fallback): + self._allow_tls_fallback): pass except ldap.INVALID_CREDENTIALS: logger.exception('Invalid LDAP credentials') diff --git a/util/config/validator.py b/util/config/validator.py index 80c9b3abb..50253bf63 100644 --- a/util/config/validator.py +++ b/util/config/validator.py @@ -4,6 +4,7 @@ import peewee import OpenSSL import logging import time +import subprocess from StringIO import StringIO from fnmatch import fnmatch @@ -313,6 +314,10 @@ def _validate_ldap(config, password): if config.get('AUTHENTICATION_TYPE', 'Database') != 'LDAP': return + # If there is a custom LDAP certificate, then reinstall the certificates for the container. + if config_provider.volume_file_exists(LDAP_CERT_FILENAME): + subprocess.check_call(['/conf/init/install_custom_certs.sh']) + # Note: raises ldap.INVALID_CREDENTIALS on failure admin_dn = config.get('LDAP_ADMIN_DN') admin_passwd = config.get('LDAP_ADMIN_PASSWD') @@ -327,15 +332,10 @@ def _validate_ldap(config, password): if not ldap_uri.startswith('ldap://') and not ldap_uri.startswith('ldaps://'): raise Exception('LDAP URI must start with ldap:// or ldaps://') - tls_cert_path = None - if config_provider.volume_file_exists(LDAP_CERT_FILENAME): - with config_provider.get_volume_file(LDAP_CERT_FILENAME) as f: - tls_cert_path = f.name - allow_tls_fallback = config.get('LDAP_ALLOW_INSECURE_FALLBACK', False) try: - with LDAPConnection(ldap_uri, admin_dn, admin_passwd, tls_cert_path, allow_tls_fallback): + with LDAPConnection(ldap_uri, admin_dn, admin_passwd, allow_tls_fallback): pass except ldap.LDAPError as ex: values = ex.args[0] if ex.args else {} @@ -351,7 +351,7 @@ def _validate_ldap(config, password): email_attr = config.get('LDAP_EMAIL_ATTR', 'mail') users = LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, - tls_cert_path, allow_tls_fallback) + allow_tls_fallback) username = get_authenticated_user().username (result, err_msg) = users.verify_credentials(username, password) @@ -432,7 +432,7 @@ def _validate_signer(config, _): if config['SIGNING_ENGINE'] not in SIGNING_ENGINES: raise Exception('Unknown signing engine: %s' % config['SIGNING_ENGINE']) - engine = SIGNING_ENGINES[config['SIGNING_ENGINE']](config, OVERRIDE_CONFIG_DIRECTORY) + engine = SIGNING_ENGINES[config['SIGNING_ENGINE']](config, config_provider) engine.detached_sign(StringIO('test string'))