##// END OF EJS Templates
auth: add scope and login restrictions to rhodecode plugin, and scope restriction to token plugin....
marcink -
r3392:5cc5c872 default
parent child Browse files
Show More
@@ -109,7 +109,17 b' class TestLoginController(object):'
109
109
110 def test_login_regular_forbidden_when_super_admin_restriction(self):
110 def test_login_regular_forbidden_when_super_admin_restriction(self):
111 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
111 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
112 with fixture.login_restriction(RhodeCodeAuthPlugin.LOGIN_RESTRICTION_SUPER_ADMIN):
112 with fixture.auth_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN):
113 response = self.app.post(route_path('login'),
114 {'username': 'test_regular',
115 'password': 'test12'})
116
117 response.mustcontain('invalid user name')
118 response.mustcontain('invalid password')
119
120 def test_login_regular_forbidden_when_scope_restriction(self):
121 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
122 with fixture.scope_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS):
113 response = self.app.post(route_path('login'),
123 response = self.app.post(route_path('login'),
114 {'username': 'test_regular',
124 {'username': 'test_regular',
115 'password': 'test12'})
125 'password': 'test12'})
@@ -26,13 +26,13 b' import logging'
26
26
27 import colander
27 import colander
28
28
29 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
30 from rhodecode.translation import _
29 from rhodecode.translation import _
31
32 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
33 from rhodecode.authentication.routes import AuthnPluginResourceBase
34 from rhodecode.lib.utils2 import safe_str
30 from rhodecode.lib.utils2 import safe_str
35 from rhodecode.model.db import User
31 from rhodecode.model.db import User
32 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
33 from rhodecode.authentication.base import (
34 RhodeCodeAuthPluginBase, hybrid_property, HTTP_TYPE, VCS_TYPE)
35 from rhodecode.authentication.routes import AuthnPluginResourceBase
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
@@ -48,8 +48,11 b' class RhodecodeAuthnResource(AuthnPlugin'
48
48
49 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
49 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
50 uid = 'rhodecode'
50 uid = 'rhodecode'
51 LOGIN_RESTRICTION_NONE = 'none'
51 AUTH_RESTRICTION_NONE = 'user_all'
52 LOGIN_RESTRICTION_SUPER_ADMIN = 'super_admin'
52 AUTH_RESTRICTION_SUPER_ADMIN = 'user_super_admin'
53 AUTH_RESTRICTION_SCOPE_ALL = 'scope_all'
54 AUTH_RESTRICTION_SCOPE_HTTP = 'scope_http'
55 AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs'
53
56
54 def includeme(self, config):
57 def includeme(self, config):
55 config.add_authn_plugin(self)
58 config.add_authn_plugin(self)
@@ -104,16 +107,32 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
104 return None
107 return None
105
108
106 if userobj.extern_type != self.name:
109 if userobj.extern_type != self.name:
107 log.warning(
110 log.warning("userobj:%s extern_type mismatch got:`%s` expected:`%s`",
108 "userobj:%s extern_type mismatch got:`%s` expected:`%s`",
109 userobj, userobj.extern_type, self.name)
111 userobj, userobj.extern_type, self.name)
110 return None
112 return None
111
113
112 login_restriction = settings.get('login_restriction', '')
114 # check scope of auth
113 if login_restriction == self.LOGIN_RESTRICTION_SUPER_ADMIN and userobj.admin is False:
115 scope_restriction = settings.get('scope_restriction', '')
114 log.info(
116
115 "userobj:%s is not super-admin and login restriction is set to %s",
117 if scope_restriction == self.AUTH_RESTRICTION_SCOPE_HTTP \
116 userobj, login_restriction)
118 and self.auth_type != HTTP_TYPE:
119 log.warning("userobj:%s tried scope type %s and scope restriction is set to %s",
120 userobj, self.auth_type, scope_restriction)
121 return None
122
123 if scope_restriction == self.AUTH_RESTRICTION_SCOPE_VCS \
124 and self.auth_type != VCS_TYPE:
125 log.warning("userobj:%s tried scope type %s and scope restriction is set to %s",
126 userobj, self.auth_type, scope_restriction)
127 return None
128
129 # check super-admin restriction
130 auth_restriction = settings.get('auth_restriction', '')
131
132 if auth_restriction == self.AUTH_RESTRICTION_SUPER_ADMIN \
133 and userobj.admin is False:
134 log.warning("userobj:%s is not super-admin and auth restriction is set to %s",
135 userobj, auth_restriction)
117 return None
136 return None
118
137
119 user_attrs = {
138 user_attrs = {
@@ -154,30 +173,45 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
154 elif userobj.username == username and password_match:
173 elif userobj.username == username and password_match:
155 log.info('user `%s` authenticated correctly', userobj.username)
174 log.info('user `%s` authenticated correctly', userobj.username)
156 return user_attrs
175 return user_attrs
157 log.warn("user `%s` used a wrong password when "
176 log.warning("user `%s` used a wrong password when "
158 "authenticating on this plugin", userobj.username)
177 "authenticating on this plugin", userobj.username)
159 return None
178 return None
160 else:
179 else:
161 log.warning(
180 log.warning('user `%s` failed to authenticate via %s, reason: account not '
162 'user `%s` failed to authenticate via %s, reason: account not '
163 'active.', username, self.name)
181 'active.', username, self.name)
164 return None
182 return None
165
183
166
184
167 class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
185 class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
168 login_restriction_choices = [
186
169 (RhodeCodeAuthPlugin.LOGIN_RESTRICTION_NONE, 'All users'),
187 auth_restriction_choices = [
170 (RhodeCodeAuthPlugin.LOGIN_RESTRICTION_SUPER_ADMIN, 'Super admins only')
188 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE, 'All users'),
189 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN, 'Super admins only'),
190 ]
191
192 auth_scope_choices = [
193 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL, 'HTTP and VCS'),
194 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_HTTP, 'HTTP only'),
171 ]
195 ]
172
196
173 login_restriction = colander.SchemaNode(
197 auth_restriction = colander.SchemaNode(
174 colander.String(),
198 colander.String(),
175 default=login_restriction_choices[0],
199 default=auth_restriction_choices[0],
176 description=_('Choose login restrition for users.'),
200 description=_('Allowed user types for authentication using this plugin.'),
177 title=_('Login restriction'),
201 title=_('User restriction'),
178 validator=colander.OneOf([x[0] for x in login_restriction_choices]),
202 validator=colander.OneOf([x[0] for x in auth_restriction_choices]),
179 widget='select_with_labels',
203 widget='select_with_labels',
180 choices=login_restriction_choices
204 choices=auth_restriction_choices
205 )
206 scope_restriction = colander.SchemaNode(
207 colander.String(),
208 default=auth_scope_choices[0],
209 description=_('Allowed protocols for authentication using this plugin. '
210 'VCS means GIT/HG/SVN. HTTP is web based login.'),
211 title=_('Scope restriction'),
212 validator=colander.OneOf([x[0] for x in auth_scope_choices]),
213 widget='select_with_labels',
214 choices=auth_scope_choices
181 )
215 )
182
216
183
217
@@ -23,7 +23,9 b' RhodeCode authentication token plugin fo'
23 """
23 """
24
24
25 import logging
25 import logging
26 import colander
26
27
28 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
27 from rhodecode.translation import _
29 from rhodecode.translation import _
28 from rhodecode.authentication.base import (
30 from rhodecode.authentication.base import (
29 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
31 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
@@ -48,6 +50,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
48 Enables usage of authentication tokens for vcs operations.
50 Enables usage of authentication tokens for vcs operations.
49 """
51 """
50 uid = 'token'
52 uid = 'token'
53 AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs'
51
54
52 def includeme(self, config):
55 def includeme(self, config):
53 config.add_authn_plugin(self)
56 config.add_authn_plugin(self)
@@ -67,6 +70,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
67 route_name='auth_home',
70 route_name='auth_home',
68 context=RhodecodeAuthnResource)
71 context=RhodecodeAuthnResource)
69
72
73 def get_settings_schema(self):
74 return RhodeCodeSettingsSchema()
75
70 def get_display_name(self):
76 def get_display_name(self):
71 return _('Rhodecode Token')
77 return _('Rhodecode Token')
72
78
@@ -142,12 +148,10 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
142 'user `%s` successfully authenticated via %s',
148 'user `%s` successfully authenticated via %s',
143 user_attrs['username'], self.name)
149 user_attrs['username'], self.name)
144 return user_attrs
150 return user_attrs
145 log.warn(
151 log.warning('user `%s` failed to authenticate via %s, reason: bad or '
146 'user `%s` failed to authenticate via %s, reason: bad or '
147 'inactive token.', username, self.name)
152 'inactive token.', username, self.name)
148 else:
153 else:
149 log.warning(
154 log.warning('user `%s` failed to authenticate via %s, reason: account not '
150 'user `%s` failed to authenticate via %s, reason: account not '
151 'active.', username, self.name)
155 'active.', username, self.name)
152 return None
156 return None
153
157
@@ -155,3 +159,19 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
155 def includeme(config):
159 def includeme(config):
156 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
160 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
157 plugin_factory(plugin_id).includeme(config)
161 plugin_factory(plugin_id).includeme(config)
162
163
164 class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
165 auth_scope_choices = [
166 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS, 'VCS only'),
167 ]
168
169 scope_restriction = colander.SchemaNode(
170 colander.String(),
171 default=auth_scope_choices[0],
172 description=_('Choose operation scope restriction when authenticating.'),
173 title=_('Scope restriction'),
174 validator=colander.OneOf([x[0] for x in auth_scope_choices]),
175 widget='select_with_labels',
176 choices=auth_scope_choices
177 )
@@ -122,15 +122,15 b' class Fixture(object):'
122
122
123 return context()
123 return context()
124
124
125 def login_restriction(self, login_restriction):
125 def auth_restriction(self, auth_restriction):
126 """
126 """
127 Context process for changing the builtin rhodecode plugin login restrictions.
127 Context process for changing the builtin rhodecode plugin auth restrictions.
128 Use like:
128 Use like:
129 fixture = Fixture()
129 fixture = Fixture()
130 with fixture.login_restriction('super_admin'):
130 with fixture.auth_restriction('super_admin'):
131 #tests
131 #tests
132
132
133 after this block login restriction will be taken off
133 after this block auth restriction will be taken off
134 """
134 """
135
135
136 class context(object):
136 class context(object):
@@ -143,13 +143,45 b' class Fixture(object):'
143 def __enter__(self):
143 def __enter__(self):
144 plugin = self._get_pluing()
144 plugin = self._get_pluing()
145 plugin.create_or_update_setting(
145 plugin.create_or_update_setting(
146 'login_restriction', login_restriction)
146 'auth_restriction', auth_restriction)
147 Session().commit()
147 Session().commit()
148
148
149 def __exit__(self, exc_type, exc_val, exc_tb):
149 def __exit__(self, exc_type, exc_val, exc_tb):
150 plugin = self._get_pluing()
150 plugin = self._get_pluing()
151 plugin.create_or_update_setting(
151 plugin.create_or_update_setting(
152 'login_restriction', RhodeCodeAuthPlugin.LOGIN_RESTRICTION_NONE)
152 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE)
153 Session().commit()
154
155 return context()
156
157 def scope_restriction(self, scope_restriction):
158 """
159 Context process for changing the builtin rhodecode plugin scope restrictions.
160 Use like:
161 fixture = Fixture()
162 with fixture.scope_restriction('scope_http'):
163 #tests
164
165 after this block scope restriction will be taken off
166 """
167
168 class context(object):
169 def _get_pluing(self):
170 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(
171 RhodeCodeAuthPlugin.uid)
172 plugin = RhodeCodeAuthPlugin(plugin_id)
173 return plugin
174
175 def __enter__(self):
176 plugin = self._get_pluing()
177 plugin.create_or_update_setting(
178 'scope_restriction', scope_restriction)
179 Session().commit()
180
181 def __exit__(self, exc_type, exc_val, exc_tb):
182 plugin = self._get_pluing()
183 plugin.create_or_update_setting(
184 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL)
153 Session().commit()
185 Session().commit()
154
186
155 return context()
187 return context()
General Comments 0
You need to be logged in to leave comments. Login now