Modify ldap validator to just check user existence
Remove auth user check from updating config app config remove duplicate certs install script
This commit is contained in:
parent
bd54eacbad
commit
9024419896
7 changed files with 52 additions and 92 deletions
|
@ -1,36 +1,36 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
set -e
|
set -e
|
||||||
QUAYPATH=${QUAYPATH:-"."}
|
QUAYPATH=${QUAYPATH:-"."}
|
||||||
QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf"}
|
QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf/stack"}
|
||||||
|
|
||||||
cd ${QUAYDIR:-"/"}
|
cd ${QUAYDIR:-"/quay-registry"}
|
||||||
|
|
||||||
# Add the custom LDAP certificate
|
# Add the custom LDAP certificate
|
||||||
if [ -e $QUAYCONF/stack/ldap.crt ]
|
if [ -e $QUAYCONF/ldap.crt ]
|
||||||
then
|
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
|
fi
|
||||||
|
|
||||||
# Add extra trusted certificates (as a directory)
|
# Add extra trusted certificates (as a directory)
|
||||||
if [ -d $QUAYCONF/stack/extra_ca_certs ]; then
|
if [ -d $QUAYCONF/extra_ca_certs ]; then
|
||||||
if test "$(ls -A "$QUAYCONF/stack/extra_ca_certs")"; then
|
if test "$(ls -A "$QUAYCONF/extra_ca_certs")"; then
|
||||||
echo "Installing extra certificates found in $QUAYCONF/stack/extra_ca_certs directory"
|
echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs directory"
|
||||||
cp $QUAYCONF/stack/extra_ca_certs/* /usr/local/share/ca-certificates/
|
cp $QUAYCONF/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/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
|
cat $QUAYCONF/extra_ca_certs/* >> venv/lib/python2.7/site-packages/certifi/cacert.pem
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add extra trusted certificates (as a file)
|
# Add extra trusted certificates (as a file)
|
||||||
if [ -f $QUAYCONF/stack/extra_ca_certs ]; then
|
if [ -f $QUAYCONF/extra_ca_certs ]; then
|
||||||
echo "Installing extra certificates found in $QUAYCONF/stack/extra_ca_certs file"
|
echo "Installing extra certificates found in $QUAYCONF/extra_ca_certs file"
|
||||||
csplit -z -f /usr/local/share/ca-certificates/extra-ca- $QUAYCONF/stack/extra_ca_certs '/-----BEGIN CERTIFICATE-----/' '{*}'
|
csplit -z -f /usr/local/share/ca-certificates/extra-ca- $QUAYCONF/extra_ca_certs '/-----BEGIN CERTIFICATE-----/' '{*}'
|
||||||
cat $QUAYCONF/stack/extra_ca_certs >> venv/lib/python2.7/site-packages/requests/cacert.pem
|
cat $QUAYCONF/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
|
cat $QUAYCONF/extra_ca_certs >> venv/lib/python2.7/site-packages/certifi/cacert.pem
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add extra trusted certificates (prefixed)
|
# 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
|
do
|
||||||
echo "Installing extra cert $f"
|
echo "Installing extra cert $f"
|
||||||
cp "$f" /usr/local/share/ca-certificates/
|
cp "$f" /usr/local/share/ca-certificates/
|
||||||
|
|
|
@ -16,7 +16,7 @@ app = Flask(__name__)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
OVERRIDE_CONFIG_DIRECTORY = os.path.join(ROOT_DIR, 'config_app/conf/stack')
|
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
|
is_testing = 'TEST' in os.environ
|
||||||
|
|
||||||
|
|
|
@ -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.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.config_endpoints.api import resource, ApiResource, nickname, validate_json_request
|
||||||
from config_app.c_app import (app, config_provider, superusers, OVERRIDE_CONFIG_DIRECTORY,
|
from config_app.c_app import (app, config_provider, superusers, ip_resolver,
|
||||||
ip_resolver, instance_keys, INIT_SCRIPTS_LOCATION)
|
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.database import configure
|
||||||
from data.runmigration import run_alembic_migration
|
from data.runmigration import run_alembic_migration
|
||||||
from util.config.configutil import add_enterprise_config_defaults
|
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.
|
# Write the configuration changes to the config override file.
|
||||||
config_provider.save_config(config_object)
|
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 {
|
return {
|
||||||
'exists': True,
|
'exists': True,
|
||||||
'config': config_object
|
'config': config_object
|
||||||
|
|
|
@ -49,7 +49,6 @@ class SuperUserCustomCertificate(ApiResource):
|
||||||
logger.exception('Got IO error for cert %s', certpath)
|
logger.exception('Got IO error for cert %s', certpath)
|
||||||
return '', 204
|
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.
|
# 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')],
|
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:
|
||||||
|
|
|
@ -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
|
|
|
@ -205,6 +205,32 @@ class LDAPUsers(FederatedUsers):
|
||||||
|
|
||||||
return (True, None)
|
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):
|
def get_user(self, username_or_email):
|
||||||
""" Looks up a username or email in LDAP. """
|
""" Looks up a username or email in LDAP. """
|
||||||
logger.debug('Looking up LDAP username or email %s', username_or_email)
|
logger.debug('Looking up LDAP username or email %s', username_or_email)
|
||||||
|
|
|
@ -23,7 +23,8 @@ class LDAPValidator(BaseValidator):
|
||||||
|
|
||||||
# If there is a custom LDAP certificate, then reinstall the certificates for the container.
|
# If there is a custom LDAP certificate, then reinstall the certificates for the container.
|
||||||
if config_provider.volume_file_exists(LDAP_CERT_FILENAME):
|
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
|
# Note: raises ldap.INVALID_CREDENTIALS on failure
|
||||||
admin_dn = config.get('LDAP_ADMIN_DN')
|
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,
|
users = LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr,
|
||||||
allow_tls_fallback, requires_email=requires_email)
|
allow_tls_fallback, requires_email=requires_email)
|
||||||
|
|
||||||
username = user.username
|
# Ensure at least one user exists to verify the connection is setup properly
|
||||||
(result, err_msg) = users.verify_credentials(username, user_password)
|
(result, err_msg) = users.at_least_one_user_exists()
|
||||||
if not result:
|
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 ' +
|
'in the remote authentication system ' +
|
||||||
'OR LDAP auth is misconfigured.') % (username, err_msg)
|
'OR LDAP auth is misconfigured.') % err_msg
|
||||||
raise ConfigValidationException(msg)
|
raise ConfigValidationException(msg)
|
||||||
|
|
Reference in a new issue