##// END OF EJS Templates
permissions: explicitly register all permissions set for user. Fixes #4217...
permissions: explicitly register all permissions set for user. Fixes #4217 - in order to get a proper inheritance chain of permissions we'll register each step. This allows to get full inheritance chain. Final permissions will be the same becuase the only thing we change is we register each step before permissions final value. - Also display the permissions summary in a nicer way more explicitly stating what permissions overwrites which.

File last commit:

r1993:dab53d0e default
r2063:8a6e9139 default
Show More
audit_logger.py
257 lines | 8.2 KiB | text/x-python | PythonLexer
audit-logs: introducing new audit logger for actions....
r1694 # -*- coding: utf-8 -*-
# Copyright (C) 2017-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import logging
import datetime
from rhodecode.model import meta
audit-logs: add push/pull actions to audit logs.
r1736 from rhodecode.model.db import User, UserLog, Repository
audit-logs: introducing new audit logger for actions....
r1694
log = logging.getLogger(__name__)
audit-logs: added audit-logs on user actions....
r1801 # action as key, and expected action_data as value
audit-logs: implemented pull request and comment events.
r1807 ACTIONS_V1 = {
audit-logs: fill in some default values for the expected action data.
r1802 'user.login.success': {'user_agent': ''},
'user.login.failure': {'user_agent': ''},
'user.logout': {'user_agent': ''},
audit-logs: use new v2 api on login/logout/password reset views.
r1697 'user.password.reset_request': {},
audit-logs: fill in some default values for the expected action data.
r1802 'user.push': {'user_agent': '', 'commit_ids': []},
'user.pull': {'user_agent': ''},
audit-logs: use new v2 api on login/logout/password reset views.
r1697
audit-logs: added audit-logs on user actions....
r1801 'user.create': {'data': {}},
'user.delete': {'old_data': {}},
'user.edit': {'old_data': {}},
'user.edit.permissions': {},
audit-logs: updated action data attrbiutes.
r1823 'user.edit.ip.add': {'ip': {}, 'user': {}},
'user.edit.ip.delete': {'ip': {}, 'user': {}},
'user.edit.token.add': {'token': {}, 'user': {}},
'user.edit.token.delete': {'token': {}, 'user': {}},
'user.edit.email.add': {'email': ''},
'user.edit.email.delete': {'email': ''},
users: added SSH key management for user admin pages
r1993 'user.edit.ssh_key.add': {'token': {}, 'user': {}},
'user.edit.ssh_key.delete': {'token': {}, 'user': {}},
audit-logs: added audit-logs on user actions....
r1801 'user.edit.password_reset.enabled': {},
'user.edit.password_reset.disabled': {},
audit-logs: added audit logs on user groups admin page.
r1805 'user_group.create': {'data': {}},
'user_group.delete': {'old_data': {}},
'user_group.edit': {'old_data': {}},
'user_group.edit.permissions': {},
audit-logs: implemented full audit logs across application....
r1829 'user_group.edit.member.add': {'user': {}},
'user_group.edit.member.delete': {'user': {}},
audit-logs: added audit logs on user groups admin page.
r1805
audit-logs: fill in some default values for the expected action data.
r1802 'repo.create': {'data': {}},
audit-logs: moved async tasks from old deprecated action_logger.
r1803 'repo.fork': {'data': {}},
audit-logs: fill in some default values for the expected action data.
r1802 'repo.edit': {'old_data': {}},
repo-permissions: moved permissions into pyramid....
r1734 'repo.edit.permissions': {},
audit-logs: fill in some default values for the expected action data.
r1802 'repo.delete': {'old_data': {}},
audit-logs: updated action data attrbiutes.
r1823 'repo.commit.strip': {'commit_id': ''},
'repo.archive.download': {'user_agent': '', 'archive_name': '',
'archive_spec': '', 'archive_cached': ''},
audit-logs: implemented pull request and comment events.
r1807 'repo.pull_request.create': '',
'repo.pull_request.edit': '',
'repo.pull_request.delete': '',
'repo.pull_request.close': '',
'repo.pull_request.merge': '',
'repo.pull_request.vote': '',
'repo.pull_request.comment.create': '',
'repo.pull_request.comment.delete': '',
'repo.pull_request.reviewer.add': '',
'repo.pull_request.reviewer.delete': '',
audit-logs: implemented full audit logs across application....
r1829 'repo.commit.comment.create': {'data': {}},
'repo.commit.comment.delete': {'data': {}},
audit-logs: implemented pull request and comment events.
r1807 'repo.commit.vote': '',
audit-logs: fill in some default values for the expected action data.
r1802 'repo_group.create': {'data': {}},
'repo_group.edit': {'old_data': {}},
audit-logs: added action logs for repository groups.
r1799 'repo_group.edit.permissions': {},
audit-logs: fill in some default values for the expected action data.
r1802 'repo_group.delete': {'old_data': {}},
audit-logs: introducing new audit logger for actions....
r1694 }
audit-logs: implemented pull request and comment events.
r1807 ACTIONS = ACTIONS_V1
audit-logs: introducing new audit logger for actions....
r1694
audit-logs: implement enum sources that should be re-used.
r1798 SOURCE_WEB = 'source_web'
SOURCE_API = 'source_api'
audit-logs: introducing new audit logger for actions....
r1694
class UserWrap(object):
"""
Fake object used to imitate AuthUser
"""
def __init__(self, user_id=None, username=None, ip_addr=None):
self.user_id = user_id
self.username = username
self.ip_addr = ip_addr
audit-logs: add push/pull actions to audit logs.
r1736 class RepoWrap(object):
"""
Fake object used to imitate RepoObject that audit logger requires
"""
def __init__(self, repo_id=None, repo_name=None):
self.repo_id = repo_id
self.repo_name = repo_name
audit-logs: introducing new audit logger for actions....
r1694 def _store_log(action_name, action_data, user_id, username, user_data,
ip_address, repository_id, repository_name):
user_log = UserLog()
user_log.version = UserLog.VERSION_2
user_log.action = action_name
user_log.action_data = action_data
user_log.user_ip = ip_address
user_log.user_id = user_id
user_log.username = username
user_log.user_data = user_data
user_log.repository_id = repository_id
user_log.repository_name = repository_name
user_log.action_date = datetime.datetime.now()
log.info('AUDIT: Logging action: `%s` by user:id:%s[%s] ip:%s',
action_name, user_id, username, ip_address)
return user_log
audit-logger: added convinience wrappers to store web or api action.
r1800 def store_web(*args, **kwargs):
if 'action_data' not in kwargs:
kwargs['action_data'] = {}
kwargs['action_data'].update({
'source': SOURCE_WEB
})
return store(*args, **kwargs)
def store_api(*args, **kwargs):
if 'action_data' not in kwargs:
kwargs['action_data'] = {}
kwargs['action_data'].update({
'source': SOURCE_API
})
return store(*args, **kwargs)
audit-logs: added audit-logs on user actions....
r1801 def store(action, user, action_data=None, user_data=None, ip_addr=None,
repo=None, sa_session=None, commit=False):
audit-logs: introducing new audit logger for actions....
r1694 """
audit-logger: added convinience wrappers to store web or api action.
r1800 Audit logger for various actions made by users, typically this
results in a call such::
audit-logs: introducing new audit logger for actions....
r1694
from rhodecode.lib import audit_logger
audit-logger: added entry for archive download.
r1743 audit_logger.store(
audit-logs: implemented full audit logs across application....
r1829 'repo.edit', user=self._rhodecode_user)
audit-logger: added entry for archive download.
r1743 audit_logger.store(
audit-logs: implemented full audit logs across application....
r1829 'repo.delete', action_data={'data': repo_data},
audit-logger: added entry for archive download.
r1743 user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'))
# repo action
audit_logger.store(
audit-logs: implemented full audit logs across application....
r1829 'repo.delete',
audit-logger: added entry for archive download.
r1743 user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'),
repo=audit_logger.RepoWrap(repo_name='some-repo'))
# repo action, when we know and have the repository object already
audit_logger.store(
audit-logs: implemented full audit logs across application....
r1829 'repo.delete', action_data={'source': audit_logger.SOURCE_WEB, },
audit-logs: implement enum sources that should be re-used.
r1798 user=self._rhodecode_user,
audit-logger: added entry for archive download.
r1743 repo=repo_object)
audit-logs: introducing new audit logger for actions....
r1694
audit-logger: added convinience wrappers to store web or api action.
r1800 # alternative wrapper to the above
audit_logger.store_web(
audit-logs: implemented full audit logs across application....
r1829 'repo.delete', action_data={},
audit-logger: added convinience wrappers to store web or api action.
r1800 user=self._rhodecode_user,
repo=repo_object)
audit-logs: introducing new audit logger for actions....
r1694 # without an user ?
audit-logger: added entry for archive download.
r1743 audit_logger.store(
audit-logs: implemented full audit logs across application....
r1829 'user.login.failure',
audit-logger: added entry for archive download.
r1743 user=audit_logger.UserWrap(
username=self.request.params.get('username'),
ip_addr=self.request.remote_addr))
audit-logs: introducing new audit logger for actions....
r1694 """
from rhodecode.lib.utils2 import safe_unicode
from rhodecode.lib.auth import AuthUser
audit-logs: fill in some default values for the expected action data.
r1802 action_spec = ACTIONS.get(action, None)
if action_spec is None:
raise ValueError('Action `{}` is not supported'.format(action))
audit-logs: introducing new audit logger for actions....
r1694
if not sa_session:
sa_session = meta.Session()
try:
username = getattr(user, 'username', None)
if not username:
pass
user_id = getattr(user, 'user_id', None)
if not user_id:
# maybe we have username ? Try to figure user_id from username
if username:
user_id = getattr(
User.get_by_username(username), 'user_id', None)
ip_addr = ip_addr or getattr(user, 'ip_addr', None)
if not ip_addr:
pass
if not user_data:
# try to get this from the auth user
if isinstance(user, AuthUser):
audit-logger: store some user details on we have proper object of auth-user.
r1701 user_data = {
'username': user.username,
'email': user.email,
}
audit-logs: introducing new audit logger for actions....
r1694
audit-logs: add push/pull actions to audit logs.
r1736 repository_name = getattr(repo, 'repo_name', None)
audit-logs: introducing new audit logger for actions....
r1694 repository_id = getattr(repo, 'repo_id', None)
audit-logs: add push/pull actions to audit logs.
r1736 if not repository_id:
# maybe we have repo_name ? Try to figure repo_id from repo_name
if repository_name:
repository_id = getattr(
Repository.get_by_repo_name(repository_name), 'repo_id', None)
audit-logs: introducing new audit logger for actions....
r1694
user_log = _store_log(
action_name=safe_unicode(action),
action_data=action_data or {},
user_id=user_id,
username=username,
user_data=user_data or {},
ip_address=safe_unicode(ip_addr),
repository_id=repository_id,
repository_name=repository_name
)
sa_session.add(user_log)
if commit:
sa_session.commit()
except Exception:
log.exception('AUDIT: failed to store audit log')