Show More
@@ -41,6 +41,7 b' from beaker.cache import cache_region, r' | |||||
41 | from webob.exc import HTTPNotFound |
|
41 | from webob.exc import HTTPNotFound | |
42 | from zope.cachedescriptors.property import Lazy as LazyProperty |
|
42 | from zope.cachedescriptors.property import Lazy as LazyProperty | |
43 |
|
43 | |||
|
44 | from rhodecode.lib import enc_utils | |||
44 | from rhodecode.translation import _ |
|
45 | from rhodecode.translation import _ | |
45 |
|
46 | |||
46 | from rhodecode.lib.vcs import get_backend |
|
47 | from rhodecode.lib.vcs import get_backend | |
@@ -69,7 +70,7 b' log = logging.getLogger(__name__)' | |||||
69 |
|
70 | |||
70 | # this is propagated from .ini file beaker.session.secret |
|
71 | # this is propagated from .ini file beaker.session.secret | |
71 | # and initialized at environment.py |
|
72 | # and initialized at environment.py | |
72 |
ENCRYPTION_KEY = |
|
73 | ENCRYPTION_KEY: bytes = b'' | |
73 |
|
74 | |||
74 | # used to sort permissions by types, '#' used here is not allowed to be in |
|
75 | # used to sort permissions by types, '#' used here is not allowed to be in | |
75 | # usernames, and it's very early in sorted string.printable table. |
|
76 | # usernames, and it's very early in sorted string.printable table. | |
@@ -106,30 +107,38 b' class EncryptedValue(TypeDecorator):' | |||||
106 | impl = String |
|
107 | impl = String | |
107 |
|
108 | |||
108 | def process_bind_param(self, value, dialect): |
|
109 | def process_bind_param(self, value, dialect): | |
109 | if not value: |
|
110 | """ | |
110 |
|
|
111 | Setter for storing value | |
111 | if value.startswith('enc$aes$'): |
|
112 | """ | |
112 | # protect against double encrypting if someone manually starts doing |
|
113 | import rhodecode | |
113 | raise ValueError('value needs to be in unencrypted format, ie. ' |
|
|||
114 | 'not starting with enc$aes$') |
|
|||
115 | return 'enc$aes$%s' % AESCipher(ENCRYPTION_KEY).encrypt(value) |
|
|||
116 |
|
||||
117 | def process_result_value(self, value, dialect): |
|
|||
118 | if not value: |
|
114 | if not value: | |
119 | return value |
|
115 | return value | |
120 |
|
116 | |||
121 | parts = value.split('$', 3) |
|
117 | # protect against double encrypting if values is already encrypted | |
122 | if not len(parts) == 3: |
|
118 | if value.startswith('enc$aes$') \ | |
123 | # probably not encrypted values |
|
119 | or value.startswith('enc$aes_hmac$') \ | |
124 | return value |
|
120 | or value.startswith('enc2$'): | |
125 | else: |
|
121 | raise ValueError('value needs to be in unencrypted format, ' | |
126 | if parts[0] != 'enc': |
|
122 | 'ie. not starting with enc$ or enc2$') | |
127 | # parts ok but without our header ? |
|
123 | ||
|
124 | algo = rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes' | |||
|
125 | bytes_val = enc_utils.encrypt_value(value, enc_key=ENCRYPTION_KEY, algo=algo) | |||
|
126 | return safe_str(bytes_val) | |||
|
127 | ||||
|
128 | def process_result_value(self, value, dialect): | |||
|
129 | """ | |||
|
130 | Getter for retrieving value | |||
|
131 | """ | |||
|
132 | ||||
|
133 | import rhodecode | |||
|
134 | if not value: | |||
128 |
|
|
135 | return value | |
129 |
|
136 | |||
130 | # at that stage we know it's our encryption |
|
137 | enc_strict_mode = rhodecode.ConfigGet().get_bool('rhodecode.encrypted_values.strict', missing=True) | |
131 | decrypted_data = AESCipher(ENCRYPTION_KEY).decrypt(parts[2]) |
|
138 | ||
132 | return decrypted_data |
|
139 | bytes_val = enc_utils.decrypt_value(value, enc_key=ENCRYPTION_KEY, strict_mode=enc_strict_mode) | |
|
140 | ||||
|
141 | return safe_str(bytes_val) | |||
133 |
|
142 | |||
134 |
|
143 | |||
135 | class BaseModel(object): |
|
144 | class BaseModel(object): |
@@ -35,7 +35,7 b' def upgrade(migrate_engine):' | |||||
35 | username.create(table=tbl) |
|
35 | username.create(table=tbl) | |
36 |
|
36 | |||
37 | _Session = meta.Session() |
|
37 | _Session = meta.Session() | |
38 |
|
|
38 | # after adding that column fix all usernames | |
39 | users_log = _Session.query(db_1_5_0.UserLog)\ |
|
39 | users_log = _Session.query(db_1_5_0.UserLog)\ | |
40 | .options(joinedload(db_1_5_0.UserLog.user))\ |
|
40 | .options(joinedload(db_1_5_0.UserLog.user))\ | |
41 | .options(joinedload(db_1_5_0.UserLog.repository)).all() |
|
41 | .options(joinedload(db_1_5_0.UserLog.repository)).all() | |
@@ -74,7 +74,7 b' def get_by_name(cls, key):' | |||||
74 |
|
74 | |||
75 | def fixups(models, _SESSION): |
|
75 | def fixups(models, _SESSION): | |
76 | # ** create default permissions ** # |
|
76 | # ** create default permissions ** # | |
77 | #===================================== |
|
77 | ||
78 | for p in models.Permission.PERMS: |
|
78 | for p in models.Permission.PERMS: | |
79 | if not get_by_key(models.Permission, p[0]): |
|
79 | if not get_by_key(models.Permission, p[0]): | |
80 | new_perm = models.Permission() |
|
80 | new_perm = models.Permission() | |
@@ -86,7 +86,6 b' def fixups(models, _SESSION):' | |||||
86 | _SESSION().commit() |
|
86 | _SESSION().commit() | |
87 |
|
87 | |||
88 | # ** populate default permissions ** # |
|
88 | # ** populate default permissions ** # | |
89 | #===================================== |
|
|||
90 |
|
89 | |||
91 | user = models.User.query().filter(models.User.username == 'default').scalar() |
|
90 | user = models.User.query().filter(models.User.username == 'default').scalar() | |
92 |
|
91 | |||
@@ -100,9 +99,10 b' def fixups(models, _SESSION):' | |||||
100 | return '.'.join(perm_name.split('.')[:1]) |
|
99 | return '.'.join(perm_name.split('.')[:1]) | |
101 |
|
100 | |||
102 | perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() |
|
101 | perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() | |
103 | defined_perms_groups = map( |
|
102 | defined_perms_groups = list(map( | |
104 | _get_group, (x.permission.permission_name for x in perms)) |
|
103 | _get_group, (x.permission.permission_name for x in perms))) | |
105 | log.debug('GOT ALREADY DEFINED:%s', perms) |
|
104 | perms_show = [p.__dict__ for p in perms] | |
|
105 | log.debug('GOT ALREADY DEFINED:%s', perms_show) | |||
106 | DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS |
|
106 | DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS | |
107 |
|
107 | |||
108 | # for every default permission that needs to be created, we check if |
|
108 | # for every default permission that needs to be created, we check if |
@@ -70,11 +70,15 b' def downgrade(migrate_engine):' | |||||
70 | meta.bind = migrate_engine |
|
70 | meta.bind = migrate_engine | |
71 |
|
71 | |||
72 |
|
72 | |||
|
73 | def get_by_key(cls, key): | |||
|
74 | return cls.query().filter(cls.permission_name == key).scalar() | |||
|
75 | ||||
|
76 | ||||
73 | def fixups(models, _SESSION): |
|
77 | def fixups(models, _SESSION): | |
74 | # ** create default permissions ** # |
|
78 | # ** create default permissions ** # | |
75 | #===================================== |
|
79 | #===================================== | |
76 | for p in models.Permission.PERMS: |
|
80 | for p in models.Permission.PERMS: | |
77 |
if not models.Permission |
|
81 | if not get_by_key(models.Permission, p[0]): | |
78 | new_perm = models.Permission() |
|
82 | new_perm = models.Permission() | |
79 | new_perm.permission_name = p[0] |
|
83 | new_perm.permission_name = p[0] | |
80 | new_perm.permission_longname = p[0] #translation err with p[1] |
|
84 | new_perm.permission_longname = p[0] # translation err with p[1] | |
@@ -97,8 +101,7 b' def fixups(models, _SESSION):' | |||||
97 | return '.'.join(perm_name.split('.')[:1]) |
|
101 | return '.'.join(perm_name.split('.')[:1]) | |
98 |
|
102 | |||
99 | perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() |
|
103 | perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() | |
100 | defined_perms_groups = map(_get_group, |
|
104 | defined_perms_groups = list(map(_get_group, (x.permission.permission_name for x in perms))) | |
101 | (x.permission.permission_name for x in perms)) |
|
|||
102 | log.debug('GOT ALREADY DEFINED:%s', perms) |
|
105 | log.debug('GOT ALREADY DEFINED:%s', perms) | |
103 | DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS |
|
106 | DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS | |
104 |
|
107 |
@@ -10,6 +10,7 b' from sqlalchemy.engine import reflection' | |||||
10 | from sqlalchemy.sql import text |
|
10 | from sqlalchemy.sql import text | |
11 |
|
11 | |||
12 | from rhodecode.lib.dbmigrate.versions import _reset_base |
|
12 | from rhodecode.lib.dbmigrate.versions import _reset_base | |
|
13 | from rhodecode.lib.hash_utils import sha1_safe | |||
13 | from rhodecode.lib.utils2 import safe_str |
|
14 | from rhodecode.lib.utils2 import safe_str | |
14 | from rhodecode.model import meta, init_model_encryption |
|
15 | from rhodecode.model import meta, init_model_encryption | |
15 |
|
16 | |||
@@ -69,11 +70,9 b' def downgrade(migrate_engine):' | |||||
69 | def _generate_repo_name_hashes(models, op, session): |
|
70 | def _generate_repo_name_hashes(models, op, session): | |
70 | repositories = models.Repository.get_all() |
|
71 | repositories = models.Repository.get_all() | |
71 | for repository in repositories: |
|
72 | for repository in repositories: | |
72 |
hash_ = |
|
73 | hash_ = sha1_safe(repository.repo_name) | |
73 | params = {'hash': hash_, 'id': repository.repo_id} |
|
74 | params = {'hash': hash_, 'id': repository.repo_id} | |
74 | query = text( |
|
75 | query = text('UPDATE repositories SET repo_name_hash = :hash WHERE repo_id = :id').bindparams(**params) | |
75 | 'UPDATE repositories SET repo_name_hash = :hash' |
|
|||
76 | ' WHERE repo_id = :id').bindparams(**params) |
|
|||
77 | op.execute(query) |
|
76 | op.execute(query) | |
78 | session().commit() |
|
77 | session().commit() | |
79 |
|
78 |
@@ -117,9 +117,13 b' class AESCipher(object):' | |||||
117 | def validate_and_decrypt_data(enc_data, enc_key, enc_strict_mode=False, safe=True): |
|
117 | def validate_and_decrypt_data(enc_data, enc_key, enc_strict_mode=False, safe=True): | |
118 | enc_data = safe_str(enc_data) |
|
118 | enc_data = safe_str(enc_data) | |
119 |
|
119 | |||
|
120 | if '$' not in enc_data: | |||
|
121 | # probably not encrypted values | |||
|
122 | return enc_data | |||
|
123 | ||||
120 | parts = enc_data.split('$', 3) |
|
124 | parts = enc_data.split('$', 3) | |
121 | if len(parts) != 3: |
|
125 | if len(parts) != 3: | |
122 | raise ValueError(f'Encrypted Data has invalid format, expected {KEY_FORMAT}, got {parts}') |
|
126 | raise ValueError(f'Encrypted Data has invalid format, expected {KEY_FORMAT}, got {parts}, org value: {enc_data}') | |
123 |
|
127 | |||
124 | enc_type = parts[1] |
|
128 | enc_type = parts[1] | |
125 | enc_data_part = parts[2] |
|
129 | enc_data_part = parts[2] |
General Comments 0
You need to be logged in to leave comments.
Login now