Show More
@@ -56,7 +56,7 b' def includeme(config):' | |||||
56 | config.set_authentication_policy(authn_policy) |
|
56 | config.set_authentication_policy(authn_policy) | |
57 |
|
57 | |||
58 | # Create authentication plugin registry and add it to the pyramid registry. |
|
58 | # Create authentication plugin registry and add it to the pyramid registry. | |
59 | authn_registry = AuthenticationPluginRegistry() |
|
59 | authn_registry = AuthenticationPluginRegistry(config.get_settings()) | |
60 | config.add_directive('add_authn_plugin', authn_registry.add_authn_plugin) |
|
60 | config.add_directive('add_authn_plugin', authn_registry.add_authn_plugin) | |
61 | config.registry.registerUtility(authn_registry) |
|
61 | config.registry.registerUtility(authn_registry) | |
62 |
|
62 |
@@ -26,23 +26,16 b' import logging' | |||||
26 | import time |
|
26 | import time | |
27 | import traceback |
|
27 | import traceback | |
28 |
|
28 | |||
29 | from authomatic import Authomatic |
|
|||
30 | from authomatic.adapters import WebObAdapter |
|
|||
31 | from authomatic.providers import oauth2, oauth1 |
|
|||
32 | from pylons import url |
|
|||
33 | from pylons.controllers.util import Response |
|
|||
34 | from pylons.i18n.translation import _ |
|
|||
35 | from pyramid.threadlocal import get_current_registry |
|
29 | from pyramid.threadlocal import get_current_registry | |
36 | from sqlalchemy.ext.hybrid import hybrid_property |
|
30 | from sqlalchemy.ext.hybrid import hybrid_property | |
37 |
|
31 | |||
38 | import rhodecode.lib.helpers as h |
|
|||
39 | from rhodecode.authentication.interface import IAuthnPluginRegistry |
|
32 | from rhodecode.authentication.interface import IAuthnPluginRegistry | |
40 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase |
|
33 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
41 | from rhodecode.lib import caches |
|
34 | from rhodecode.lib import caches | |
42 | from rhodecode.lib.auth import PasswordGenerator, _RhodeCodeCryptoBCrypt |
|
35 | from rhodecode.lib.auth import PasswordGenerator, _RhodeCodeCryptoBCrypt | |
43 | from rhodecode.lib.utils2 import md5_safe, safe_int |
|
36 | from rhodecode.lib.utils2 import md5_safe, safe_int | |
44 | from rhodecode.lib.utils2 import safe_str |
|
37 | from rhodecode.lib.utils2 import safe_str | |
45 |
from rhodecode.model.db import User |
|
38 | from rhodecode.model.db import User | |
46 | from rhodecode.model.meta import Session |
|
39 | from rhodecode.model.meta import Session | |
47 | from rhodecode.model.settings import SettingsModel |
|
40 | from rhodecode.model.settings import SettingsModel | |
48 | from rhodecode.model.user import UserModel |
|
41 | from rhodecode.model.user import UserModel | |
@@ -518,50 +511,40 b' def authenticate(username, password, env' | |||||
518 | raise ValueError('auth type must be on of http, vcs got "%s" instead' |
|
511 | raise ValueError('auth type must be on of http, vcs got "%s" instead' | |
519 | % auth_type) |
|
512 | % auth_type) | |
520 | container_only = environ and not (username and password) |
|
513 | container_only = environ and not (username and password) | |
521 | auth_plugins = SettingsModel().get_auth_plugins() |
|
|||
522 | for plugin_id in auth_plugins: |
|
|||
523 | plugin = loadplugin(plugin_id) |
|
|||
524 |
|
514 | |||
525 | if plugin is None: |
|
515 | authn_registry = get_current_registry().getUtility(IAuthnPluginRegistry) | |
526 | log.warning('Authentication plugin missing: "{}"'.format( |
|
516 | for plugin in authn_registry.get_plugins_for_authentication(): | |
527 | plugin_id)) |
|
|||
528 | continue |
|
|||
529 |
|
||||
530 | if not plugin.is_active(): |
|
|||
531 | log.info('Authentication plugin is inactive: "{}"'.format( |
|
|||
532 | plugin_id)) |
|
|||
533 | continue |
|
|||
534 |
|
||||
535 | plugin.set_auth_type(auth_type) |
|
517 | plugin.set_auth_type(auth_type) | |
536 | user = plugin.get_user(username) |
|
518 | user = plugin.get_user(username) | |
537 | display_user = user.username if user else username |
|
519 | display_user = user.username if user else username | |
538 |
|
520 | |||
539 | if container_only and not plugin.is_container_auth: |
|
521 | if container_only and not plugin.is_container_auth: | |
540 | log.debug('Auth type is for container only and plugin `%s` is not ' |
|
522 | log.debug('Auth type is for container only and plugin `%s` is not ' | |
541 | 'container plugin, skipping...', plugin_id) |
|
523 | 'container plugin, skipping...', plugin.get_id()) | |
542 | continue |
|
524 | continue | |
543 |
|
525 | |||
544 | # load plugin settings from RhodeCode database |
|
526 | # load plugin settings from RhodeCode database | |
545 | plugin_settings = plugin.get_settings() |
|
527 | plugin_settings = plugin.get_settings() | |
546 | log.debug('Plugin settings:%s', plugin_settings) |
|
528 | log.debug('Plugin settings:%s', plugin_settings) | |
547 |
|
529 | |||
548 | log.debug('Trying authentication using ** %s **', plugin_id) |
|
530 | log.debug('Trying authentication using ** %s **', plugin.get_id()) | |
549 | # use plugin's method of user extraction. |
|
531 | # use plugin's method of user extraction. | |
550 | user = plugin.get_user(username, environ=environ, |
|
532 | user = plugin.get_user(username, environ=environ, | |
551 | settings=plugin_settings) |
|
533 | settings=plugin_settings) | |
552 | display_user = user.username if user else username |
|
534 | display_user = user.username if user else username | |
553 | log.debug('Plugin %s extracted user is `%s`', plugin_id, display_user) |
|
535 | log.debug( | |
|
536 | 'Plugin %s extracted user is `%s`', plugin.get_id(), display_user) | |||
554 |
|
537 | |||
555 | if not plugin.allows_authentication_from(user): |
|
538 | if not plugin.allows_authentication_from(user): | |
556 | log.debug('Plugin %s does not accept user `%s` for authentication', |
|
539 | log.debug('Plugin %s does not accept user `%s` for authentication', | |
557 | plugin_id, display_user) |
|
540 | plugin.get_id(), display_user) | |
558 | continue |
|
541 | continue | |
559 | else: |
|
542 | else: | |
560 | log.debug('Plugin %s accepted user `%s` for authentication', |
|
543 | log.debug('Plugin %s accepted user `%s` for authentication', | |
561 | plugin_id, display_user) |
|
544 | plugin.get_id(), display_user) | |
562 |
|
545 | |||
563 | log.info('Authenticating user `%s` using %s plugin', |
|
546 | log.info('Authenticating user `%s` using %s plugin', | |
564 | display_user, plugin_id) |
|
547 | display_user, plugin.get_id()) | |
565 |
|
548 | |||
566 | _cache_ttl = 0 |
|
549 | _cache_ttl = 0 | |
567 |
|
550 | |||
@@ -576,7 +559,7 b' def authenticate(username, password, env' | |||||
576 | # get instance of cache manager configured for a namespace |
|
559 | # get instance of cache manager configured for a namespace | |
577 | cache_manager = get_auth_cache_manager(custom_ttl=_cache_ttl) |
|
560 | cache_manager = get_auth_cache_manager(custom_ttl=_cache_ttl) | |
578 |
|
561 | |||
579 | log.debug('Cache for plugin `%s` active: %s', plugin_id, |
|
562 | log.debug('Cache for plugin `%s` active: %s', plugin.get_id(), | |
580 | plugin_cache_active) |
|
563 | plugin_cache_active) | |
581 |
|
564 | |||
582 | # for environ based password can be empty, but then the validation is |
|
565 | # for environ based password can be empty, but then the validation is | |
@@ -591,7 +574,7 b' def authenticate(username, password, env' | |||||
591 | # then auth is correct. |
|
574 | # then auth is correct. | |
592 | start = time.time() |
|
575 | start = time.time() | |
593 | log.debug('Running plugin `%s` _authenticate method', |
|
576 | log.debug('Running plugin `%s` _authenticate method', | |
594 | plugin_id) |
|
577 | plugin.get_id()) | |
595 |
|
578 | |||
596 | def auth_func(): |
|
579 | def auth_func(): | |
597 | """ |
|
580 | """ | |
@@ -611,7 +594,7 b' def authenticate(username, password, env' | |||||
611 | auth_time = time.time() - start |
|
594 | auth_time = time.time() - start | |
612 | log.debug('Authentication for plugin `%s` completed in %.3fs, ' |
|
595 | log.debug('Authentication for plugin `%s` completed in %.3fs, ' | |
613 | 'expiration time of fetched cache %.1fs.', |
|
596 | 'expiration time of fetched cache %.1fs.', | |
614 | plugin_id, auth_time, _cache_ttl) |
|
597 | plugin.get_id(), auth_time, _cache_ttl) | |
615 |
|
598 | |||
616 | log.debug('PLUGIN USER DATA: %s', plugin_user) |
|
599 | log.debug('PLUGIN USER DATA: %s', plugin_user) | |
617 |
|
600 | |||
@@ -620,5 +603,5 b' def authenticate(username, password, env' | |||||
620 | return plugin_user |
|
603 | return plugin_user | |
621 | # we failed to Auth because .auth() method didn't return proper user |
|
604 | # we failed to Auth because .auth() method didn't return proper user | |
622 | log.debug("User `%s` failed to authenticate against %s", |
|
605 | log.debug("User `%s` failed to authenticate against %s", | |
623 | display_user, plugin_id) |
|
606 | display_user, plugin.get_id()) | |
624 | return None |
|
607 | return None |
@@ -31,8 +31,13 b' log = logging.getLogger(__name__)' | |||||
31 |
|
31 | |||
32 | @implementer(IAuthnPluginRegistry) |
|
32 | @implementer(IAuthnPluginRegistry) | |
33 | class AuthenticationPluginRegistry(object): |
|
33 | class AuthenticationPluginRegistry(object): | |
34 | def __init__(self): |
|
34 | ||
|
35 | # INI settings key to set a fallback authentication plugin. | |||
|
36 | fallback_plugin_key = 'rhodecode.auth_plugin_fallback' | |||
|
37 | ||||
|
38 | def __init__(self, settings): | |||
35 | self._plugins = {} |
|
39 | self._plugins = {} | |
|
40 | self._fallback_plugin = settings.get(self.fallback_plugin_key, None) | |||
36 |
|
41 | |||
37 | def add_authn_plugin(self, config, plugin): |
|
42 | def add_authn_plugin(self, config, plugin): | |
38 | plugin_id = plugin.get_id() |
|
43 | plugin_id = plugin.get_id() | |
@@ -51,3 +56,23 b' class AuthenticationPluginRegistry(objec' | |||||
51 |
|
56 | |||
52 | def get_plugin(self, plugin_id): |
|
57 | def get_plugin(self, plugin_id): | |
53 | return self._plugins.get(plugin_id, None) |
|
58 | return self._plugins.get(plugin_id, None) | |
|
59 | ||||
|
60 | def get_plugins_for_authentication(self): | |||
|
61 | """ | |||
|
62 | Returns a list of plugins which should be consulted when authenticating | |||
|
63 | a user. It only returns plugins which are enabled and active. | |||
|
64 | Additionally it includes the fallback plugin from the INI file, if | |||
|
65 | `rhodecode.auth_plugin_fallback` is set to a plugin ID. | |||
|
66 | """ | |||
|
67 | plugins = [] | |||
|
68 | for plugin in self.get_plugins(): | |||
|
69 | if (self._fallback_plugin and | |||
|
70 | plugin.get_id() == self._fallback_plugin): | |||
|
71 | log.warn( | |||
|
72 | 'Using fallback authentication plugin from INI file: "%s"', | |||
|
73 | plugin.get_id()) | |||
|
74 | plugins.append(plugin) | |||
|
75 | elif plugin.is_enabled() and plugin.is_active(): | |||
|
76 | plugins.append(plugin) | |||
|
77 | ||||
|
78 | return plugins |
@@ -151,8 +151,7 b' class AuthSettingsView(object):' | |||||
151 | @HasPermissionAllDecorator('hg.admin') |
|
151 | @HasPermissionAllDecorator('hg.admin') | |
152 | def index(self, defaults={}, errors=None, prefix_error=False): |
|
152 | def index(self, defaults={}, errors=None, prefix_error=False): | |
153 | authn_registry = self.request.registry.getUtility(IAuthnPluginRegistry) |
|
153 | authn_registry = self.request.registry.getUtility(IAuthnPluginRegistry) | |
154 | default_plugins = ['egg:rhodecode-enterprise-ce#rhodecode'] |
|
154 | enabled_plugins = SettingsModel().get_auth_plugins() | |
155 | enabled_plugins = SettingsModel().get_auth_plugins() or default_plugins |
|
|||
156 |
|
155 | |||
157 | # Create template context and render it. |
|
156 | # Create template context and render it. | |
158 | template_context = { |
|
157 | template_context = { |
General Comments 0
You need to be logged in to leave comments.
Login now