Pull out keystone validation into validator class
This commit is contained in:
parent
c55ddf7341
commit
678f868bc4
3 changed files with 95 additions and 41 deletions
|
@ -15,9 +15,6 @@ from boot import setup_jwt_proxy
|
|||
from data.database import validate_database_url
|
||||
from data.users import LDAP_CERT_FILENAME
|
||||
from data.users.externaljwt import ExternalJWTAuthN
|
||||
from data.users.externalldap import LDAPConnection, LDAPUsers
|
||||
from data.users.keystone import get_keystone_users
|
||||
from storage import get_storage_driver
|
||||
from oauth.services.github import GithubOAuthService
|
||||
from oauth.services.google import GoogleOAuthService
|
||||
from oauth.services.gitlab import GitLabOAuthService
|
||||
|
@ -31,6 +28,7 @@ from util.config.validators.validate_redis import RedisValidator
|
|||
from util.config.validators.validate_storage import StorageValidator
|
||||
from util.config.validators.validate_email import EmailValidator
|
||||
from util.config.validators.validate_ldap import LDAPValidator
|
||||
from util.config.validators.validate_keystone import KeystoneValidator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -293,43 +291,6 @@ def _validate_jwt(config, user_obj, password):
|
|||
'properly: %s' % err_msg)
|
||||
|
||||
|
||||
def _validate_keystone(config, user_obj, password):
|
||||
""" Validates the Keystone authentication system. """
|
||||
if config.get('AUTHENTICATION_TYPE', 'Database') != 'Keystone':
|
||||
return
|
||||
|
||||
auth_url = config.get('KEYSTONE_AUTH_URL')
|
||||
auth_version = int(config.get('KEYSTONE_AUTH_VERSION', 2))
|
||||
admin_username = config.get('KEYSTONE_ADMIN_USERNAME')
|
||||
admin_password = config.get('KEYSTONE_ADMIN_PASSWORD')
|
||||
admin_tenant = config.get('KEYSTONE_ADMIN_TENANT')
|
||||
|
||||
if not auth_url:
|
||||
raise ConfigValidationException('Missing authentication URL')
|
||||
|
||||
if not admin_username:
|
||||
raise ConfigValidationException('Missing admin username')
|
||||
|
||||
if not admin_password:
|
||||
raise ConfigValidationException('Missing admin password')
|
||||
|
||||
if not admin_tenant:
|
||||
raise ConfigValidationException('Missing admin tenant')
|
||||
|
||||
requires_email = config.get('FEATURE_MAILING', True)
|
||||
users = get_keystone_users(auth_version, auth_url, admin_username, admin_password, admin_tenant,
|
||||
requires_email)
|
||||
|
||||
# Verify that the superuser exists. If not, raise an exception.
|
||||
username = user_obj.username
|
||||
(result, err_msg) = users.verify_credentials(username, password)
|
||||
if not result:
|
||||
msg = ('Verification of superuser %s failed: %s \n\nThe user either does not ' +
|
||||
'exist in the remote authentication system ' +
|
||||
'OR Keystone auth is misconfigured.') % (username, err_msg)
|
||||
raise ConfigValidationException(msg)
|
||||
|
||||
|
||||
def _validate_signer(config, user_obj, _):
|
||||
""" Validates the GPG public+private key pair used for signing converted ACIs. """
|
||||
if config.get('SIGNING_ENGINE') is None:
|
||||
|
@ -420,7 +381,7 @@ VALIDATORS = {
|
|||
'ssl': _validate_ssl,
|
||||
LDAPValidator.name: LDAPValidator.validate,
|
||||
'jwt': _validate_jwt,
|
||||
'keystone': _validate_keystone,
|
||||
KeystoneValidator.name: KeystoneValidator.validate,
|
||||
'signer': _validate_signer,
|
||||
'security-scanner': _validate_security_scanner,
|
||||
'bittorrent': _validate_bittorrent,
|
||||
|
|
51
util/config/validators/test/test_validate_keystone.py
Normal file
51
util/config/validators/test/test_validate_keystone.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import pytest
|
||||
|
||||
from util.config.validators import ConfigValidationException
|
||||
from util.config.validators.validate_keystone import KeystoneValidator
|
||||
from util.morecollections import AttrDict
|
||||
|
||||
from test.test_keystone_auth import fake_keystone
|
||||
|
||||
|
||||
@pytest.mark.parametrize('unvalidated_config', [
|
||||
({}),
|
||||
({'AUTHENTICATION_TYPE': 'Database'}),
|
||||
])
|
||||
def test_validate_noop(unvalidated_config):
|
||||
KeystoneValidator.validate(unvalidated_config, None, None)
|
||||
|
||||
@pytest.mark.parametrize('unvalidated_config', [
|
||||
({'AUTHENTICATION_TYPE': 'Keystone'}),
|
||||
({'AUTHENTICATION_TYPE': 'Keystone', 'KEYSTONE_AUTH_URL': 'foo'}),
|
||||
({'AUTHENTICATION_TYPE': 'Keystone', 'KEYSTONE_AUTH_URL': 'foo',
|
||||
'KEYSTONE_ADMIN_USERNAME': 'bar'}),
|
||||
({'AUTHENTICATION_TYPE': 'Keystone', 'KEYSTONE_AUTH_URL': 'foo',
|
||||
'KEYSTONE_ADMIN_USERNAME': 'bar', 'KEYSTONE_ADMIN_PASSWORD': 'baz'}),
|
||||
])
|
||||
def test_invalid_config(unvalidated_config):
|
||||
with pytest.raises(ConfigValidationException):
|
||||
KeystoneValidator.validate(unvalidated_config, None, None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('username, password, expected_exception', [
|
||||
('invaliduser', 'invalidpass', ConfigValidationException),
|
||||
('cool.user', 'invalidpass', ConfigValidationException),
|
||||
('invaliduser', 'somepass', ConfigValidationException),
|
||||
('cool.user', 'password', None),
|
||||
])
|
||||
def test_validated_keystone(username, password, expected_exception):
|
||||
with fake_keystone(2) as keystone_auth:
|
||||
auth_url = keystone_auth.auth_url
|
||||
|
||||
config = {}
|
||||
config['AUTHENTICATION_TYPE'] = 'Keystone'
|
||||
config['KEYSTONE_AUTH_URL'] = auth_url
|
||||
config['KEYSTONE_ADMIN_USERNAME'] = 'adminuser'
|
||||
config['KEYSTONE_ADMIN_PASSWORD'] = 'adminpass'
|
||||
config['KEYSTONE_ADMIN_TENANT'] = 'admintenant'
|
||||
|
||||
if expected_exception is not None:
|
||||
with pytest.raises(ConfigValidationException):
|
||||
KeystoneValidator.validate(config, AttrDict(dict(username=username)), password)
|
||||
else:
|
||||
KeystoneValidator.validate(config, AttrDict(dict(username=username)), password)
|
42
util/config/validators/validate_keystone.py
Normal file
42
util/config/validators/validate_keystone.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
from util.config.validators import BaseValidator, ConfigValidationException
|
||||
from data.users.keystone import get_keystone_users
|
||||
|
||||
class KeystoneValidator(BaseValidator):
|
||||
name = "keystone"
|
||||
|
||||
@classmethod
|
||||
def validate(cls, config, user, user_password):
|
||||
""" Validates the Keystone authentication system. """
|
||||
if config.get('AUTHENTICATION_TYPE', 'Database') != 'Keystone':
|
||||
return
|
||||
|
||||
auth_url = config.get('KEYSTONE_AUTH_URL')
|
||||
auth_version = int(config.get('KEYSTONE_AUTH_VERSION', 2))
|
||||
admin_username = config.get('KEYSTONE_ADMIN_USERNAME')
|
||||
admin_password = config.get('KEYSTONE_ADMIN_PASSWORD')
|
||||
admin_tenant = config.get('KEYSTONE_ADMIN_TENANT')
|
||||
|
||||
if not auth_url:
|
||||
raise ConfigValidationException('Missing authentication URL')
|
||||
|
||||
if not admin_username:
|
||||
raise ConfigValidationException('Missing admin username')
|
||||
|
||||
if not admin_password:
|
||||
raise ConfigValidationException('Missing admin password')
|
||||
|
||||
if not admin_tenant:
|
||||
raise ConfigValidationException('Missing admin tenant')
|
||||
|
||||
requires_email = config.get('FEATURE_MAILING', True)
|
||||
users = get_keystone_users(auth_version, auth_url, admin_username, admin_password, admin_tenant,
|
||||
requires_email)
|
||||
|
||||
# Verify that the superuser exists. If not, raise an exception.
|
||||
username = user.username
|
||||
(result, err_msg) = users.verify_credentials(username, user_password)
|
||||
if not result:
|
||||
msg = ('Verification of superuser %s failed: %s \n\nThe user either does not ' +
|
||||
'exist in the remote authentication system ' +
|
||||
'OR Keystone auth is misconfigured.') % (username, err_msg)
|
||||
raise ConfigValidationException(msg)
|
Reference in a new issue