def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False): _set = set() if inherit_from_default: default_ips = UserIpMap.query().filter( UserIpMap.user == User.get_default_user(cache=True)) if cache: default_ips = default_ips.options( FromCache("sql_cache_short", "get_user_ips_default")) # populate from default user for ip in default_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id) if cache: user_ips = user_ips.options( FromCache("sql_cache_short", "get_user_ips_%s" % user_id)) for ip in user_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass return _set or set(['0.0.0.0/0', '::/0'])
def test_ip_restriction_git(self, webserver): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) # The message apparently changed in Git 1.8.3, so match it loosely. assert re.search(r'\b403\b', stderr) finally: #release IP restrictions for ip in UserIpMap.query(): UserIpMap.delete(ip.ip_id) Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'git clone', clone_url, _get_tmp_dir()) assert 'Cloning into' in stdout + stderr assert stderr == '' or stdout == ''
def test_ip_restriction_hg(self, webserver): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) assert 'abort: HTTP Error 403: Forbidden' in stderr finally: #release IP restrictions for ip in UserIpMap.query(): UserIpMap.delete(ip.ip_id) Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir()) assert 'requesting all changes' in stdout assert 'adding changesets' in stdout assert 'adding manifests' in stdout assert 'adding file changes' in stdout assert stderr == ''
def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False): _set = set() if inherit_from_default: default_ips = UserIpMap.query().filter(UserIpMap.user == User.get_default_user(cache=True)) if cache: default_ips = default_ips.options(FromCache("sql_cache_short", "get_user_ips_default")) # populate from default user for ip in default_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id) if cache: user_ips = user_ips.options(FromCache("sql_cache_short", "get_user_ips_%s" % user_id)) for ip in user_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass return _set or set(['0.0.0.0/0', '::/0'])
def test_ip_restriction_hg(self, webserver): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) assert 'abort: HTTP Error 403: Forbidden' in stderr finally: #release IP restrictions for ip in UserIpMap.query(): UserIpMap.delete(ip.ip_id) Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'hg clone', clone_url, _get_tmp_dir()) assert 'requesting all changes' in stdout assert 'adding changesets' in stdout assert 'adding manifests' in stdout assert 'adding file changes' in stdout assert stderr == ''
def test_add_delete_ips(self, auto_clear_ip_permissions): self.log_user() default_user_id = kallithea.DEFAULT_USER_ID # Add IP and verify it is shown in UI and both gives access and rejects response = self.app.post( base.url('edit_user_ips_update', id=default_user_id), params=dict( new_ip='0.0.0.0/24', _session_csrf_secret_token=self.session_csrf_secret_token())) base.invalidate_all_caches() response = self.app.get(base.url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '0.0.0.1'}) response.mustcontain('0.0.0.0/24') response.mustcontain('0.0.0.0 - 0.0.0.255') response = self.app.get(base.url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '0.0.1.1'}, status=403) # Add another IP and verify previously rejected now works response = self.app.post( base.url('edit_user_ips_update', id=default_user_id), params=dict( new_ip='0.0.1.0/24', _session_csrf_secret_token=self.session_csrf_secret_token())) base.invalidate_all_caches() response = self.app.get(base.url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '0.0.1.1'}) # Delete latest IP and verify same IP is rejected again x = UserIpMap.query().filter_by(ip_addr='0.0.1.0/24').first() response = self.app.post( base.url('edit_user_ips_delete', id=default_user_id), params=dict( del_ip_id=x.ip_id, _session_csrf_secret_token=self.session_csrf_secret_token())) base.invalidate_all_caches() response = self.app.get(base.url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '0.0.1.1'}, status=403) # Delete first IP and verify unlimited access again x = UserIpMap.query().filter_by(ip_addr='0.0.0.0/24').first() response = self.app.post( base.url('edit_user_ips_delete', id=default_user_id), params=dict( del_ip_id=x.ip_id, _session_csrf_secret_token=self.session_csrf_secret_token())) base.invalidate_all_caches() response = self.app.get(base.url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '0.0.1.1'})
def edit_ips(self, id): c.user = self._get_user_or_raise_if_default(id) c.active = 'ips' c.user_ip_map = UserIpMap.query() \ .filter(UserIpMap.user == c.user).all() c.default_user_ip_map = UserIpMap.query() \ .filter(UserIpMap.user_id == kallithea.DEFAULT_USER_ID).all() defaults = c.user.get_dict() return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def edit_ips(self, id): c.user = self._get_user_or_raise_if_default(id) c.active = 'ips' c.user_ip_map = UserIpMap.query() \ .filter(UserIpMap.user == c.user).all() c.inherit_default_ips = c.user.inherit_default_permissions c.default_user_ip_map = UserIpMap.query() \ .filter(UserIpMap.user == User.get_default_user()).all() defaults = c.user.get_dict() return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def permission_ips(self): c.active = 'ips' c.user = User.get_default_user() c.user_ip_map = UserIpMap.query() \ .filter(UserIpMap.user == c.user).all() return render('admin/permissions/permissions.html')
def test_add_ips(self): self.log_user() default_user_id = User.get_default_user().user_id response = self.app.put(url('edit_user_ips', id=default_user_id), params=dict(new_ip='127.0.0.0/24', _authentication_token=self.authentication_token())) response = self.app.get(url('admin_permissions_ips')) response.mustcontain('127.0.0.0/24') response.mustcontain('127.0.0.0 - 127.0.0.255') ## delete default_user_id = User.get_default_user().user_id del_ip_id = UserIpMap.query().filter(UserIpMap.user_id == default_user_id).first().ip_id response = self.app.post(url('edit_user_ips', id=default_user_id), params=dict(_method='delete', del_ip_id=del_ip_id, _authentication_token=self.authentication_token())) response = self.app.get(url('admin_permissions_ips')) response.mustcontain('All IP addresses are allowed') response.mustcontain(no=['127.0.0.0/24']) response.mustcontain(no=['127.0.0.0 - 127.0.0.255'])
def test_add_ips(self): self.log_user() default_user_id = User.get_default_user().user_id response = self.app.put(url('edit_user_ips', id=default_user_id), params=dict(new_ip='127.0.0.0/24', _authentication_token=self.authentication_token())) # sleep more than beaker.cache.sql_cache_short.expire to expire user cache time.sleep(1.5) self.app.get(url('admin_permissions_ips'), status=302) # REMOTE_ADDR must match 127.0.0.0/24 response = self.app.get(url('admin_permissions_ips'), extra_environ={'REMOTE_ADDR': '127.0.0.1'}) response.mustcontain('127.0.0.0/24') response.mustcontain('127.0.0.0 - 127.0.0.255') ## delete default_user_id = User.get_default_user().user_id del_ip_id = UserIpMap.query().filter(UserIpMap.user_id == default_user_id).first().ip_id response = self.app.post(url('edit_user_ips', id=default_user_id), params=dict(_method='delete', del_ip_id=del_ip_id, _authentication_token=self.authentication_token()), extra_environ={'REMOTE_ADDR': '127.0.0.1'}) # sleep more than beaker.cache.sql_cache_short.expire to expire user cache time.sleep(1.5) response = self.app.get(url('admin_permissions_ips')) response.mustcontain('All IP addresses are allowed') response.mustcontain(no=['127.0.0.0/24']) response.mustcontain(no=['127.0.0.0 - 127.0.0.255'])
def add_extra_ip(self, user, ip): """ Adds ip address to UserIpMap :param user: :param ip: """ from kallithea.model import forms form = forms.UserExtraIpForm()() data = form.to_python(dict(ip=ip)) user = self._get_user(user) obj = UserIpMap() obj.user = user obj.ip_addr = data['ip'] self.sa.add(obj) return obj
def add_extra_ip(self, user, ip): """ Adds IP address to UserIpMap :param user: :param ip: """ from kallithea.model import forms form = forms.UserExtraIpForm()() data = form.to_python(dict(ip=ip)) user = User.guess_instance(user) obj = UserIpMap() obj.user = user obj.ip_addr = data['ip'] Session().add(obj) return obj
def test_ip_restriction(self, webserver, vt): user_model = UserModel() try: # Add IP constraint that excludes the test context: user_model.add_extra_ip(base.TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = vt.repo_url_param(webserver, vt.repo_name) stdout, stderr = Command(base.TESTS_TMP_PATH).execute( vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) if vt.repo_type == 'git': # The message apparently changed in Git 1.8.3, so match it loosely. assert re.search( r'\b403\b', stderr ) or 'abort: User test_admin from 127.0.0.127 cannot be authorized' in stderr elif vt.repo_type == 'hg': assert 'abort: HTTP Error 403: Forbidden' in stderr or 'remote: abort: User test_admin from 127.0.0.127 cannot be authorized' in stdout finally: # release IP restrictions for ip in UserIpMap.query(): UserIpMap.delete(ip.ip_id) Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = vt.repo_url_param(webserver, vt.repo_name) stdout, stderr = Command(base.TESTS_TMP_PATH).execute( vt.repo_type, 'clone', clone_url, _get_tmp_dir()) if vt.repo_type == 'git': assert 'Cloning into' in stdout + stderr assert stderr == '' or stdout == '' elif vt.repo_type == 'hg': assert 'requesting all changes' in stdout assert 'adding changesets' in stdout assert 'adding manifests' in stdout assert 'adding file changes' in stdout assert stderr == ''
def edit_ips(self, id): c.user = User.get_or_404(id) if c.user.username == User.DEFAULT_USER: h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) c.active = 'ips' c.user_ip_map = UserIpMap.query()\ .filter(UserIpMap.user == c.user).all() c.inherit_default_ips = c.user.inherit_default_permissions c.default_user_ip_map = UserIpMap.query()\ .filter(UserIpMap.user == User.get_default_user()).all() defaults = c.user.get_dict() return htmlfill.render(render('admin/users/user_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def delete_extra_ip(self, user, ip_id): """ Removes IP address from UserIpMap :param user: :param ip_id: """ user = User.guess_instance(user) obj = UserIpMap.query().get(ip_id) if obj: Session().delete(obj)
def edit_ips(self, id): c.user = User.get_or_404(id) if c.user.username == User.DEFAULT_USER: h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) c.active = 'ips' c.user_ip_map = UserIpMap.query()\ .filter(UserIpMap.user == c.user).all() c.inherit_default_ips = c.user.inherit_default_permissions c.default_user_ip_map = UserIpMap.query()\ .filter(UserIpMap.user == User.get_default_user()).all() defaults = c.user.get_dict() return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def delete_extra_ip(self, user, ip_id): """ Removes ip address from UserIpMap :param user: :param ip_id: """ user = self._get_user(user) obj = UserIpMap.query().get(ip_id) if obj: self.sa.delete(obj)
def test_ip_restriction_git(self): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) msg = ("""The requested URL returned error: 403""") assert msg in stderr finally: #release IP restrictions for ip in UserIpMap.getAll(): UserIpMap.delete(ip.ip_id) Session().commit() time.sleep(2) clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) assert 'Cloning into' in stdout + stderr assert stderr == '' or stdout == ''
def test_ip_restriction_git(self): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) msg = ("""The requested URL returned error: 403""") assert msg in stderr finally: #release IP restrictions for ip in UserIpMap.getAll(): UserIpMap.delete(ip.ip_id) Session().commit() time.sleep(2) clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) assert 'Cloning into' in stdout assert stderr == ''
def get_allowed_ips(cls, user_id): _set = set() default_ips = UserIpMap.query().filter( UserIpMap.user_id == kallithea.DEFAULT_USER_ID) for ip in default_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id) for ip in user_ips: try: _set.add(ip.ip_addr) except ObjectDeletedError: # since we use heavy caching sometimes it happens that we get # deleted objects here, we just skip them pass return _set or set(['0.0.0.0/0', '::/0'])
def test_ip_restriction_git(self, webserver): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) # The message apparently changed in Git 1.8.3, so match it loosely. assert re.search(r'\b403\b', stderr) finally: #release IP restrictions for ip in UserIpMap.query(): UserIpMap.delete(ip.ip_id) Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir()) assert 'Cloning into' in stdout + stderr assert stderr == '' or stdout == ''
def test_ip_restriction_hg(self): user_model = UserModel() try: user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() clone_url = _construct_url(HG_REPO) stdout, stderr = Command('/tmp').execute('hg clone', clone_url) assert 'abort: HTTP Error 403: Forbidden' in stderr finally: #release IP restrictions for ip in UserIpMap.getAll(): UserIpMap.delete(ip.ip_id) Session().commit() time.sleep(2) clone_url = _construct_url(HG_REPO) stdout, stderr = Command('/tmp').execute('hg clone', clone_url) assert 'requesting all changes' in stdout assert 'adding changesets' in stdout assert 'adding manifests' in stdout assert 'adding file changes' in stdout assert stderr == ''
def auto_clear_ip_permissions(): """Fixture that provides nothing but clearing IP permissions upon test exit. This clearing is needed to avoid other test failing to make fake http accesses.""" yield # cleanup user_model = UserModel() user_ids = [] user_ids.append(User.get_default_user().user_id) user_ids.append(User.get_by_username(TEST_USER_REGULAR_LOGIN).user_id) for user_id in user_ids: for ip in UserIpMap.query().filter(UserIpMap.user_id == user_id): user_model.delete_extra_ip(user_id, ip.ip_id) # IP permissions are cached, need to invalidate this cache explicitly invalidate_all_caches()
def test_add_ips(self): self.log_user() default_user_id = User.get_default_user().user_id response = self.app.put(url('edit_user_ips', id=default_user_id), params=dict(new_ip='127.0.0.0/24')) response = self.app.get(url('admin_permissions_ips')) response.mustcontain('127.0.0.0/24') response.mustcontain('127.0.0.0 - 127.0.0.255') ## delete default_user_id = User.get_default_user().user_id del_ip_id = UserIpMap.query().filter( UserIpMap.user_id == default_user_id).first().ip_id response = self.app.post(url('edit_user_ips', id=default_user_id), params=dict(_method='delete', del_ip_id=del_ip_id)) response = self.app.get(url('admin_permissions_ips')) response.mustcontain('All IP addresses are allowed') response.mustcontain(no=['127.0.0.0/24']) response.mustcontain(no=['127.0.0.0 - 127.0.0.255'])
def test_add_ip(self, test_name, ip, ip_range, failure): self.log_user() user = User.get_by_username(TEST_USER_REGULAR_LOGIN) user_id = user.user_id response = self.app.put(url('edit_user_ips', id=user_id), params=dict(new_ip=ip)) if failure: self.checkSessionFlash(response, 'Please enter a valid IPv4 or IpV6 address') response = self.app.get(url('edit_user_ips', id=user_id)) response.mustcontain(no=[ip]) response.mustcontain(no=[ip_range]) else: response = self.app.get(url('edit_user_ips', id=user_id)) response.mustcontain(ip) response.mustcontain(ip_range) ## cleanup for del_ip in UserIpMap.query().filter(UserIpMap.user_id == user_id).all(): Session().delete(del_ip) Session().commit()
def ip_range(ip_addr): from kallithea.model.db import UserIpMap s, e = UserIpMap._get_ip_range(ip_addr) return '%s - %s' % (s, e)