##// END OF EJS Templates
Full IP restrictions enabled...
marcink -
r3146:c5169e44 beta
parent child Browse files
Show More
@@ -43,7 +43,7 b' from webob.exc import HTTPNotFound, HTTP'
43 HTTPBadRequest, HTTPError
43 HTTPBadRequest, HTTPError
44
44
45 from rhodecode.model.db import User
45 from rhodecode.model.db import User
46 from rhodecode.lib.auth import AuthUser, check_ip_access
46 from rhodecode.lib.auth import AuthUser
47 from rhodecode.lib.base import _get_ip_addr, _get_access_path
47 from rhodecode.lib.base import _get_ip_addr, _get_access_path
48 from rhodecode.lib.utils2 import safe_unicode
48 from rhodecode.lib.utils2 import safe_unicode
49
49
@@ -148,17 +148,15 b' class JSONRPCController(WSGIController):'
148 if u is None:
148 if u is None:
149 return jsonrpc_error(retid=self._req_id,
149 return jsonrpc_error(retid=self._req_id,
150 message='Invalid API KEY')
150 message='Invalid API KEY')
151
151 #check if we are allowed to use this IP
152 #check if we are allowed to use this IP
152 allowed_ips = AuthUser.get_allowed_ips(u.user_id)
153 auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr)
153 if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips) is False:
154 if not auth_u.ip_allowed:
154 log.info('Access for IP:%s forbidden, '
155 'not in %s' % (ip_addr, allowed_ips))
156 return jsonrpc_error(retid=self._req_id,
155 return jsonrpc_error(retid=self._req_id,
157 message='request from IP:%s not allowed' % (ip_addr))
156 message='request from IP:%s not allowed' % (ip_addr))
158 else:
157 else:
159 log.info('Access for IP:%s allowed' % (ip_addr))
158 log.info('Access for IP:%s allowed' % (ip_addr))
160
159
161 auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr)
162 except Exception, e:
160 except Exception, e:
163 return jsonrpc_error(retid=self._req_id,
161 return jsonrpc_error(retid=self._req_id,
164 message='Invalid API KEY')
162 message='Invalid API KEY')
@@ -54,10 +54,9 b' class LoginController(BaseController):'
54 def index(self):
54 def index(self):
55 # redirect if already logged in
55 # redirect if already logged in
56 c.came_from = request.GET.get('came_from')
56 c.came_from = request.GET.get('came_from')
57
57 not_default = self.rhodecode_user.username != 'default'
58 if self.rhodecode_user.is_authenticated \
58 ip_allowed = self.rhodecode_user.ip_allowed
59 and self.rhodecode_user.username != 'default':
59 if self.rhodecode_user.is_authenticated and not_default and ip_allowed:
60
61 return redirect(url('home'))
60 return redirect(url('home'))
62
61
63 if request.POST:
62 if request.POST:
@@ -46,6 +46,7 b' from rhodecode.lib.auth_ldap import Auth'
46 from rhodecode.model import meta
46 from rhodecode.model import meta
47 from rhodecode.model.user import UserModel
47 from rhodecode.model.user import UserModel
48 from rhodecode.model.db import Permission, RhodeCodeSetting, User, UserIpMap
48 from rhodecode.model.db import Permission, RhodeCodeSetting, User, UserIpMap
49 from rhodecode.lib.caching_query import FromCache
49
50
50 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
51
52
@@ -327,7 +328,6 b' class AuthUser(object):'
327 self.admin = False
328 self.admin = False
328 self.inherit_default_permissions = False
329 self.inherit_default_permissions = False
329 self.permissions = {}
330 self.permissions = {}
330 self.allowed_ips = set()
331 self._api_key = api_key
331 self._api_key = api_key
332 self.propagate_data()
332 self.propagate_data()
333 self._instance = None
333 self._instance = None
@@ -377,13 +377,29 b' class AuthUser(object):'
377
377
378 log.debug('Auth User is now %s' % self)
378 log.debug('Auth User is now %s' % self)
379 user_model.fill_perms(self)
379 user_model.fill_perms(self)
380 log.debug('Filling Allowed IPs')
381 self.allowed_ips = AuthUser.get_allowed_ips(self.user_id)
382
380
383 @property
381 @property
384 def is_admin(self):
382 def is_admin(self):
385 return self.admin
383 return self.admin
386
384
385 @property
386 def ip_allowed(self):
387 """
388 Checks if ip_addr used in constructor is allowed from defined list of
389 allowed ip_addresses for user
390
391 :returns: boolean, True if ip is in allowed ip range
392 """
393 #check IP
394 allowed_ips = AuthUser.get_allowed_ips(self.user_id, cache=True)
395 if check_ip_access(source_ip=self.ip_addr, allowed_ips=allowed_ips):
396 log.debug('IP:%s is in range of %s' % (self.ip_addr, allowed_ips))
397 return True
398 else:
399 log.info('Access for IP:%s forbidden, '
400 'not in %s' % (self.ip_addr, allowed_ips))
401 return False
402
387 def __repr__(self):
403 def __repr__(self):
388 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
404 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
389 self.is_authenticated)
405 self.is_authenticated)
@@ -411,9 +427,12 b' class AuthUser(object):'
411 return AuthUser(user_id, api_key, username)
427 return AuthUser(user_id, api_key, username)
412
428
413 @classmethod
429 @classmethod
414 def get_allowed_ips(cls, user_id):
430 def get_allowed_ips(cls, user_id, cache=False):
415 _set = set()
431 _set = set()
416 user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id).all()
432 user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id)
433 if cache:
434 user_ips = user_ips.options(FromCache("sql_cache_short",
435 "get_user_ips_%s" % user_id))
417 for ip in user_ips:
436 for ip in user_ips:
418 _set.add(ip.ip_addr)
437 _set.add(ip.ip_addr)
419 return _set or set(['0.0.0.0/0'])
438 return _set or set(['0.0.0.0/0'])
@@ -462,6 +481,15 b' class LoginRequired(object):'
462 def __wrapper(self, func, *fargs, **fkwargs):
481 def __wrapper(self, func, *fargs, **fkwargs):
463 cls = fargs[0]
482 cls = fargs[0]
464 user = cls.rhodecode_user
483 user = cls.rhodecode_user
484 loc = "%s:%s" % (cls.__class__.__name__, func.__name__)
485
486 #check IP
487 ip_access_ok = True
488 if not user.ip_allowed:
489 from rhodecode.lib import helpers as h
490 h.flash(h.literal(_('IP %s not allowed' % (user.ip_addr))),
491 category='warning')
492 ip_access_ok = False
465
493
466 api_access_ok = False
494 api_access_ok = False
467 if self.api_access:
495 if self.api_access:
@@ -470,9 +498,9 b' class LoginRequired(object):'
470 api_access_ok = True
498 api_access_ok = True
471 else:
499 else:
472 log.debug("API KEY token not valid")
500 log.debug("API KEY token not valid")
473 loc = "%s:%s" % (cls.__class__.__name__, func.__name__)
501
474 log.debug('Checking if %s is authenticated @ %s' % (user.username, loc))
502 log.debug('Checking if %s is authenticated @ %s' % (user.username, loc))
475 if user.is_authenticated or api_access_ok:
503 if (user.is_authenticated or api_access_ok) and ip_access_ok:
476 reason = 'RegularAuth' if user.is_authenticated else 'APIAuth'
504 reason = 'RegularAuth' if user.is_authenticated else 'APIAuth'
477 log.info('user %s is authenticated and granted access to %s '
505 log.info('user %s is authenticated and granted access to %s '
478 'using %s' % (user.username, loc, reason)
506 'using %s' % (user.username, loc, reason)
@@ -20,7 +20,7 b' from rhodecode import __version__, BACKE'
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
21 safe_str, safe_int
21 safe_str, safe_int
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
23 HasPermissionAnyMiddleware, CookieStoreWrapper, check_ip_access
23 HasPermissionAnyMiddleware, CookieStoreWrapper
24 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
24 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
25 from rhodecode.model import meta
25 from rhodecode.model import meta
26
26
@@ -146,10 +146,8 b' class BaseVCSController(object):'
146 :param repo_name: repository name
146 :param repo_name: repository name
147 """
147 """
148 #check IP
148 #check IP
149 allowed_ips = AuthUser.get_allowed_ips(user.user_id)
149 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr)
150 if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips) is False:
150 if not authuser.ip_allowed:
151 log.info('Access for IP:%s forbidden, '
152 'not in %s' % (ip_addr, allowed_ips))
153 return False
151 return False
154 else:
152 else:
155 log.info('Access for IP:%s allowed' % (ip_addr))
153 log.info('Access for IP:%s allowed' % (ip_addr))
@@ -536,6 +536,7 b' class UserIpMap(Base, BaseModel):'
536 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
536 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
537 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
537 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
538 ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
538 ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
539 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
539 user = relationship('User', lazy='joined')
540 user = relationship('User', lazy='joined')
540
541
541 @classmethod
542 @classmethod
@@ -27,7 +27,6 b' import logging'
27 import traceback
27 import traceback
28 import itertools
28 import itertools
29 import collections
29 import collections
30 import functools
31 from pylons import url
30 from pylons import url
32 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
33
32
@@ -2002,7 +2002,6 b' a.metatag[tag="license"]:hover {'
2002 }
2002 }
2003
2003
2004 #login div.title {
2004 #login div.title {
2005 width: 420px;
2006 clear: both;
2005 clear: both;
2007 overflow: hidden;
2006 overflow: hidden;
2008 position: relative;
2007 position: relative;
@@ -2021,7 +2020,6 b' a.metatag[tag="license"]:hover {'
2021 }
2020 }
2022
2021
2023 #login div.inner {
2022 #login div.inner {
2024 width: 380px;
2025 background: #FFF url("../images/login.png") no-repeat top left;
2023 background: #FFF url("../images/login.png") no-repeat top left;
2026 border-top: none;
2024 border-top: none;
2027 border-bottom: none;
2025 border-bottom: none;
@@ -2038,7 +2036,6 b' a.metatag[tag="license"]:hover {'
2038 }
2036 }
2039
2037
2040 #login div.form div.fields div.field div.input input {
2038 #login div.form div.fields div.field div.input input {
2041 width: 176px;
2042 background: #FFF;
2039 background: #FFF;
2043 border-top: 1px solid #b3b3b3;
2040 border-top: 1px solid #b3b3b3;
2044 border-left: 1px solid #b3b3b3;
2041 border-left: 1px solid #b3b3b3;
General Comments 0
You need to be logged in to leave comments. Login now