Merge pull request #1549 from coreos-inc/certs

Switch to install custom LDAP cert by name
This commit is contained in:
josephschorr 2016-06-21 15:13:44 -04:00 committed by GitHub
commit 7173d53030
4 changed files with 24 additions and 32 deletions

View file

@ -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

View file

@ -46,13 +46,8 @@ def get_users_handler(config, config_provider, override_config_dir):
email_attr = config.get('LDAP_EMAIL_ATTR', 'mail') email_attr = config.get('LDAP_EMAIL_ATTR', 'mail')
allow_tls_fallback = config.get('LDAP_ALLOW_INSECURE_FALLBACK', False) 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, 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': if authentication_type == 'JWT':
verify_url = config.get('JWT_VERIFY_ENDPOINT') verify_url = config.get('JWT_VERIFY_ENDPOINT')

View file

@ -3,31 +3,27 @@ import logging
import os import os
from collections import namedtuple from collections import namedtuple
from datetime import datetime
from data.users.federated import FederatedUsers, VerifiedCredentials from data.users.federated import FederatedUsers, VerifiedCredentials
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class LDAPConnectionBuilder(object): 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._ldap_uri = ldap_uri
self._user_dn = user_dn self._user_dn = user_dn
self._user_pw = user_pw self._user_pw = user_pw
self._tls_cert_path = tls_cert_path
self._allow_tls_fallback = allow_tls_fallback self._allow_tls_fallback = allow_tls_fallback
def get_connection(self): def get_connection(self):
return LDAPConnection(self._ldap_uri, self._user_dn, self._user_pw, return LDAPConnection(self._ldap_uri, self._user_dn, self._user_pw, self._allow_tls_fallback)
self._tls_cert_path, self._allow_tls_fallback )
class LDAPConnection(object): 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._ldap_uri = ldap_uri
self._user_dn = user_dn self._user_dn = user_dn
self._user_pw = user_pw self._user_pw = user_pw
self._tls_cert_path = tls_cert_path
self._allow_tls_fallback = allow_tls_fallback self._allow_tls_fallback = allow_tls_fallback
self._conn = None self._conn = None
@ -37,10 +33,6 @@ class LDAPConnection(object):
self._conn = ldap.initialize(self._ldap_uri, trace_level=trace_level) self._conn = ldap.initialize(self._ldap_uri, trace_level=trace_level)
self._conn.set_option(ldap.OPT_REFERRALS, 1) 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: if self._allow_tls_fallback:
logger.debug('TLS Fallback enabled in LDAP') logger.debug('TLS Fallback enabled in LDAP')
self._conn.set_option(ldap.OPT_X_TLS_TRY, 1) self._conn.set_option(ldap.OPT_X_TLS_TRY, 1)
@ -56,18 +48,15 @@ class LDAPUsers(FederatedUsers):
_LDAPResult = namedtuple('LDAPResult', ['dn', 'attrs']) _LDAPResult = namedtuple('LDAPResult', ['dn', 'attrs'])
def __init__(self, ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, 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') super(LDAPUsers, self).__init__('ldap')
self._ldap = LDAPConnectionBuilder(ldap_uri, admin_dn, admin_passwd, tls_cert_path, self._ldap = LDAPConnectionBuilder(ldap_uri, admin_dn, admin_passwd, allow_tls_fallback)
allow_tls_fallback)
self._ldap_uri = ldap_uri self._ldap_uri = ldap_uri
self._base_dn = base_dn self._base_dn = base_dn
self._user_rdn = user_rdn self._user_rdn = user_rdn
self._uid_attr = uid_attr self._uid_attr = uid_attr
self._email_attr = email_attr self._email_attr = email_attr
self._tls_cert_path = tls_cert_path
self._allow_tls_fallback = allow_tls_fallback self._allow_tls_fallback = allow_tls_fallback
def _get_ldap_referral_dn(self, referral_exception): def _get_ldap_referral_dn(self, referral_exception):
@ -159,7 +148,7 @@ class LDAPUsers(FederatedUsers):
# First validate the password by binding as the user # First validate the password by binding as the user
try: try:
with LDAPConnection(self._ldap_uri, found_dn, password.encode('utf-8'), with LDAPConnection(self._ldap_uri, found_dn, password.encode('utf-8'),
self._tls_cert_path, self._allow_tls_fallback): self._allow_tls_fallback):
pass pass
except ldap.REFERRAL as re: except ldap.REFERRAL as re:
referral_dn = self._get_ldap_referral_dn(re) referral_dn = self._get_ldap_referral_dn(re)
@ -168,7 +157,7 @@ class LDAPUsers(FederatedUsers):
try: try:
with LDAPConnection(self._ldap_uri, referral_dn, password.encode('utf-8'), with LDAPConnection(self._ldap_uri, referral_dn, password.encode('utf-8'),
self._tls_cert_path, self._allow_tls_fallback): self._allow_tls_fallback):
pass pass
except ldap.INVALID_CREDENTIALS: except ldap.INVALID_CREDENTIALS:
logger.exception('Invalid LDAP credentials') logger.exception('Invalid LDAP credentials')

View file

@ -4,6 +4,7 @@ import peewee
import OpenSSL import OpenSSL
import logging import logging
import time import time
import subprocess
from StringIO import StringIO from StringIO import StringIO
from fnmatch import fnmatch from fnmatch import fnmatch
@ -313,6 +314,10 @@ def _validate_ldap(config, password):
if config.get('AUTHENTICATION_TYPE', 'Database') != 'LDAP': if config.get('AUTHENTICATION_TYPE', 'Database') != 'LDAP':
return 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 # Note: raises ldap.INVALID_CREDENTIALS on failure
admin_dn = config.get('LDAP_ADMIN_DN') admin_dn = config.get('LDAP_ADMIN_DN')
admin_passwd = config.get('LDAP_ADMIN_PASSWD') 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://'): if not ldap_uri.startswith('ldap://') and not ldap_uri.startswith('ldaps://'):
raise Exception('LDAP URI must start with ldap:// or 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) allow_tls_fallback = config.get('LDAP_ALLOW_INSECURE_FALLBACK', False)
try: 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 pass
except ldap.LDAPError as ex: except ldap.LDAPError as ex:
values = ex.args[0] if ex.args else {} 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') email_attr = config.get('LDAP_EMAIL_ATTR', 'mail')
users = LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, 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 username = get_authenticated_user().username
(result, err_msg) = users.verify_credentials(username, password) (result, err_msg) = users.verify_credentials(username, password)
@ -432,7 +432,7 @@ def _validate_signer(config, _):
if config['SIGNING_ENGINE'] not in SIGNING_ENGINES: if config['SIGNING_ENGINE'] not in SIGNING_ENGINES:
raise Exception('Unknown signing engine: %s' % config['SIGNING_ENGINE']) 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')) engine.detached_sign(StringIO('test string'))