diff --git a/conf/init/certs_install.sh b/conf/init/certs_install.sh index 34f0d4ac3..981064f70 100755 --- a/conf/init/certs_install.sh +++ b/conf/init/certs_install.sh @@ -1,36 +1,36 @@ #! /bin/bash set -e QUAYPATH=${QUAYPATH:-"."} -QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf"} +QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf/stack"} -cd ${QUAYDIR:-"/"} +cd ${QUAYDIR:-"/quay-registry"} # Add the custom LDAP certificate -if [ -e $QUAYCONF/stack/ldap.crt ] +if [ -e $QUAYCONF/ldap.crt ] then - cp $QUAYCONF/stack/ldap.crt /usr/local/share/ca-certificates/ldap.crt + cp $QUAYCONF/ldap.crt /usr/local/share/ca-certificates/ldap.crt fi # Add extra trusted certificates (as a directory) -if [ -d $QUAYCONF/stack/extra_ca_certs ]; then - if test "$(ls -A "$QUAYCONF/stack/extra_ca_certs")"; then - echo "Installing extra certificates found in $QUAYCONF/stack/extra_ca_certs directory" - cp $QUAYCONF/stack/extra_ca_certs/* /usr/local/share/ca-certificates/ - cat $QUAYCONF/stack/extra_ca_certs/* >> venv/lib/python2.7/site-packages/requests/cacert.pem - cat $QUAYCONF/stack/extra_ca_certs/* >> venv/lib/python2.7/site-packages/certifi/cacert.pem +if [ -d $QUAYCONF/extra_ca_certs ]; then + if test "$(ls -A "$QUAYCONF/extra_ca_certs")"; then + echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs directory" + cp $QUAYCONF/extra_ca_certs/* /usr/local/share/ca-certificates/ + cat $QUAYCONF/extra_ca_certs/* >> venv/lib/python2.7/site-packages/requests/cacert.pem + cat $QUAYCONF/extra_ca_certs/* >> venv/lib/python2.7/site-packages/certifi/cacert.pem fi fi # Add extra trusted certificates (as a file) -if [ -f $QUAYCONF/stack/extra_ca_certs ]; then - echo "Installing extra certificates found in $QUAYCONF/stack/extra_ca_certs file" - csplit -z -f /usr/local/share/ca-certificates/extra-ca- $QUAYCONF/stack/extra_ca_certs '/-----BEGIN CERTIFICATE-----/' '{*}' - cat $QUAYCONF/stack/extra_ca_certs >> venv/lib/python2.7/site-packages/requests/cacert.pem - cat $QUAYCONF/stack/extra_ca_certs >> venv/lib/python2.7/site-packages/certifi/cacert.pem +if [ -f $QUAYCONF/extra_ca_certs ]; then + echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs file" + csplit -z -f /usr/local/share/ca-certificates/extra-ca- $QUAYCONF/extra_ca_certs '/-----BEGIN CERTIFICATE-----/' '{*}' + cat $QUAYCONF/extra_ca_certs >> venv/lib/python2.7/site-packages/requests/cacert.pem + cat $QUAYCONF/extra_ca_certs >> venv/lib/python2.7/site-packages/certifi/cacert.pem fi # Add extra trusted certificates (prefixed) -for f in $(find $QUAYCONF/stack/ -maxdepth 1 -type f -name "extra_ca*") +for f in $(find $QUAYCONF/ -maxdepth 1 -type f -name "extra_ca*") do echo "Installing extra cert $f" cp "$f" /usr/local/share/ca-certificates/ diff --git a/config_app/c_app.py b/config_app/c_app.py index 8e116a3cb..a1e25304a 100644 --- a/config_app/c_app.py +++ b/config_app/c_app.py @@ -16,7 +16,7 @@ app = Flask(__name__) logger = logging.getLogger(__name__) OVERRIDE_CONFIG_DIRECTORY = os.path.join(ROOT_DIR, 'config_app/conf/stack') -INIT_SCRIPTS_LOCATION = '/quay-registry/config_app/init/' +INIT_SCRIPTS_LOCATION = '/conf/init/' is_testing = 'TEST' in os.environ diff --git a/config_app/config_endpoints/api/suconfig.py b/config_app/config_endpoints/api/suconfig.py index 6bae4b89b..d83ad88eb 100644 --- a/config_app/config_endpoints/api/suconfig.py +++ b/config_app/config_endpoints/api/suconfig.py @@ -4,11 +4,9 @@ from flask import abort, request from config_app.config_endpoints.api.suconfig_models_pre_oci import pre_oci_model as model from config_app.config_endpoints.api import resource, ApiResource, nickname, validate_json_request -from config_app.c_app import (app, config_provider, superusers, OVERRIDE_CONFIG_DIRECTORY, - ip_resolver, instance_keys, INIT_SCRIPTS_LOCATION) +from config_app.c_app import (app, config_provider, superusers, ip_resolver, + instance_keys, INIT_SCRIPTS_LOCATION) -from auth.auth_context import get_authenticated_user -from data.users import get_federated_service_name, get_users_handler from data.database import configure from data.runmigration import run_alembic_migration from util.config.configutil import add_enterprise_config_defaults @@ -75,27 +73,6 @@ class SuperUserConfig(ApiResource): # Write the configuration changes to the config override file. config_provider.save_config(config_object) - # If the authentication system is federated, link the superuser account to the - # the authentication system chosen. - service_name = get_federated_service_name(config_object['AUTHENTICATION_TYPE']) - if service_name is not None: - current_user = get_authenticated_user() - if current_user is None: - abort(401) - - service_name = get_federated_service_name(config_object['AUTHENTICATION_TYPE']) - if not model.has_federated_login(current_user.username, service_name): - # Verify the user's credentials and retrieve the user's external username+email. - handler = get_users_handler(config_object, config_provider, OVERRIDE_CONFIG_DIRECTORY) - (result, err_msg) = handler.verify_credentials(current_user.username, - request.get_json().get('password', '')) - if not result: - logger.error('Could not save configuration due to external auth failure: %s', err_msg) - abort(400) - - # Link the existing user to the external user. - model.attach_federated_login(current_user.username, service_name, result.username) - return { 'exists': True, 'config': config_object diff --git a/config_app/config_endpoints/api/superuser.py b/config_app/config_endpoints/api/superuser.py index a0848fb93..7eceac565 100644 --- a/config_app/config_endpoints/api/superuser.py +++ b/config_app/config_endpoints/api/superuser.py @@ -49,10 +49,9 @@ class SuperUserCustomCertificate(ApiResource): logger.exception('Got IO error for cert %s', certpath) return '', 204 - # TODO(QUAY-991): properly install the custom certs provided by user # Call the update script with config dir location to install the certificate immediately. if subprocess.call([os.path.join(INIT_SCRIPTS_LOCATION, 'certs_install.sh')], - env={ 'QUAYCONF': config_provider.get_config_dir_path() }) != 0: + env={ 'QUAYCONF': config_provider.get_config_dir_path() }) != 0: raise Exception('Could not install certificates') return '', 204 diff --git a/config_app/init/certs_install.sh b/config_app/init/certs_install.sh deleted file mode 100755 index 45a08f5ce..000000000 --- a/config_app/init/certs_install.sh +++ /dev/null @@ -1,43 +0,0 @@ -#! /bin/bash -set -e -QUAYPATH=${QUAYPATH:-"."} -QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf/stack"} - -cd ${QUAYDIR:-"/quay-registry"} -pwd - -# Add the custom LDAP certificate -if [ -e $QUAYCONF/ldap.crt ] -then - cp $QUAYCONF/ldap.crt /usr/local/share/ca-certificates/ldap.crt -fi - -# Add extra trusted certificates (as a directory) -if [ -d $QUAYCONF/extra_ca_certs ]; then - if test "$(ls -A "$QUAYCONF/extra_ca_certs")"; then - echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs directory" - cp $QUAYCONF/extra_ca_certs/* /usr/local/share/ca-certificates/ - cat $QUAYCONF/extra_ca_certs/* >> venv/lib/python2.7/site-packages/requests/cacert.pem - cat $QUAYCONF/extra_ca_certs/* >> venv/lib/python2.7/site-packages/certifi/cacert.pem - fi -fi - -# Add extra trusted certificates (as a file) -if [ -f $QUAYCONF/extra_ca_certs ]; then - echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs file" - csplit -z -f /usr/local/share/ca-certificates/extra-ca- $QUAYCONF/extra_ca_certs '/-----BEGIN CERTIFICATE-----/' '{*}' - cat $QUAYCONF/extra_ca_certs >> venv/lib/python2.7/site-packages/requests/cacert.pem - cat $QUAYCONF/extra_ca_certs >> venv/lib/python2.7/site-packages/certifi/cacert.pem -fi - -# Add extra trusted certificates (prefixed) -for f in $(find $QUAYCONF/ -maxdepth 1 -type f -name "extra_ca*") -do - echo "Installing extra cert $f" - cp "$f" /usr/local/share/ca-certificates/ - cat "$f" >> venv/lib/python2.7/site-packages/requests/cacert.pem - cat "$f" >> venv/lib/python2.7/site-packages/certifi/cacert.pem -done - -# Update all CA certificates. -update-ca-certificates diff --git a/data/users/externalldap.py b/data/users/externalldap.py index f2c7e298f..53248be00 100644 --- a/data/users/externalldap.py +++ b/data/users/externalldap.py @@ -205,6 +205,32 @@ class LDAPUsers(FederatedUsers): return (True, None) + def at_least_one_user_exists(self): + logger.debug('Checking if any users exist in LDAP') + try: + with self._ldap.get_connection(): + pass + except ldap.INVALID_CREDENTIALS: + return (None, 'LDAP Admin dn or password is invalid') + + with self._ldap.get_connection() as conn: + for user_search_dn in self._user_dns: + try: + (pairs, err_msg) = conn.search_ext_s(user_search_dn, ldap.SCOPE_SUBTREE) + except Exception as e: + # Catch ldap exceptions to give the user our custom error message + return (False, e.message) + + # if we find any users at all the ldap is valid + if pairs is not None and len(pairs) > 0: + return (True, None) + + if err_msg is not None: + return (None, err_msg) + + return (False, None) + + def get_user(self, username_or_email): """ Looks up a username or email in LDAP. """ logger.debug('Looking up LDAP username or email %s', username_or_email) diff --git a/util/config/validators/validate_ldap.py b/util/config/validators/validate_ldap.py index ec1dafe8d..595487587 100644 --- a/util/config/validators/validate_ldap.py +++ b/util/config/validators/validate_ldap.py @@ -23,7 +23,8 @@ class LDAPValidator(BaseValidator): # 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([os.path.join(init_scripts_location, 'certs_install.sh')]) + subprocess.check_call([os.path.join(init_scripts_location, 'certs_install.sh')], + env={ 'QUAYCONF': config_provider.get_config_dir_path() }) # Note: raises ldap.INVALID_CREDENTIALS on failure admin_dn = config.get('LDAP_ADMIN_DN') @@ -61,10 +62,10 @@ class LDAPValidator(BaseValidator): users = LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr, allow_tls_fallback, requires_email=requires_email) - username = user.username - (result, err_msg) = users.verify_credentials(username, user_password) + # Ensure at least one user exists to verify the connection is setup properly + (result, err_msg) = users.at_least_one_user_exists() if not result: - msg = ('Verification of superuser %s failed: %s. \n\nThe user either does not exist ' + + msg = ('Verification that users exist failed: %s. \n\nNo users exist ' + 'in the remote authentication system ' + - 'OR LDAP auth is misconfigured.') % (username, err_msg) + 'OR LDAP auth is misconfigured.') % err_msg raise ConfigValidationException(msg)