0002-settings_loaders-compute-a-symmetric-shared-secret-f.patch
hobo/multitenant/settings_loaders.py | ||
---|---|---|
35 | 35 |
class KnownServices(FileBaseSettingsLoader): |
36 | 36 |
FILENAME = 'hobo.json' |
37 | 37 | |
38 |
@classmethod |
|
39 |
def shared_secret(cls, secret1, secret2): |
|
40 |
secret1 = hashlib.sha256(secret1).hexdigest() |
|
41 |
secret2 = hashlib.sha256(secret2).hexdigest() |
|
42 |
return hex(int(secret1, 16) ^ int(secret2, 16))[2:-1] |
|
43 | ||
38 | 44 |
def update_settings_from_path(self, tenant_settings, path): |
39 | 45 |
known_services = {} |
40 | 46 |
with file(path) as f: |
41 | 47 |
hobo_json = json.load(f) |
42 | 48 |
services = hobo_json.get('services') |
43 |
base_url, secret = [(s.get('base_url'), s.get('secret_key'))
|
|
44 |
for s in services if s.get('this')][0]
|
|
49 |
this = [s for s in services if s.get('this')][0]
|
|
50 |
base_url = this['base_url']
|
|
45 | 51 |
orig = urlparse.urlparse(base_url).netloc.split(':')[0] |
46 |
secret = hashlib.sha1(orig+secret).hexdigest()
|
|
52 |
secret = this['secret_key']
|
|
47 | 53 | |
48 | 54 |
for service in services: |
49 | 55 |
service_id = service.get('service-id') |
50 | ||
56 |
url = service.get('base_url') |
|
57 |
verif_orig = urlparse.urlparse(url).netloc.split(':')[0] |
|
51 | 58 |
service_data = { |
52 |
'url': service.get('base_url'),
|
|
59 |
'url': url,
|
|
53 | 60 |
'backoffice-menu-url': service.get('backoffice-menu-url'), |
54 | 61 |
'title': service.get('title'), |
55 | 62 |
'orig': orig, |
56 |
'secret': secret,
|
|
63 |
'verif_orig': verif_orig,
|
|
57 | 64 |
'variables': service.get('variables') |
58 | 65 |
} |
66 |
# compute a symmetric shared secret using XOR |
|
67 |
# secrets MUST be hexadecimal numbers of the same even length |
|
68 |
if not service.get('this'): |
|
69 |
service_data['secret_key'] = (self.shared_secret(secret, service['secret_key']) if |
|
70 |
'secret_key' in service else None) |
|
59 | 71 |
if service_id in known_services: |
60 | 72 |
known_services[service_id][service.get('slug')] = service_data |
61 | 73 |
else: |
tests_multitenant/conftest.py | ||
---|---|---|
27 | 27 |
'services': [ |
28 | 28 |
{'slug': 'test', |
29 | 29 |
'title': 'Test', |
30 |
'service-id': 'welco', |
|
30 | 31 |
'this': True, |
31 | 32 |
'secret_key': '12345', |
32 | 33 |
'base_url': 'http://%s' % name, |
... | ... | |
41 | 42 |
}, |
42 | 43 |
{'slug': 'other', |
43 | 44 |
'title': 'Other', |
45 |
'secret_key': 'abcde', |
|
46 |
'service-id': 'authentic', |
|
44 | 47 |
'base_url': 'http://other.example.net'}, |
45 | 48 |
]}, fd) |
46 | 49 |
t = Tenant(domain_url=name, |
tests_multitenant/test_settings.py | ||
---|---|---|
141 | 141 |
t2 = threading.Thread(target=g) |
142 | 142 |
t2.start() |
143 | 143 |
t2.join() |
144 | ||
145 | ||
146 |
def test_shared_secret(): |
|
147 |
from hobo.multitenant.settings_loaders import KnownServices |
|
148 | ||
149 |
secrets = set() |
|
150 |
for i in range(100): |
|
151 |
a = str(random.getrandbits(160)) |
|
152 |
b = str(random.getrandbits(160)) |
|
153 |
assert KnownServices.shared_secret(a, b) == KnownServices.shared_secret(b, a) |
|
154 |
secrets.add(KnownServices.shared_secret(a, b)) |
|
155 |
# Verify minimum entropy |
|
156 |
assert len(secrets) == 100 |
|
157 | ||
158 | ||
159 |
def test_known_services(tenants, settings): |
|
160 |
from hobo.multitenant.settings_loaders import KnownServices |
|
161 | ||
162 |
settings.clear_tenants_settings() |
|
163 | ||
164 |
for tenant in tenants: |
|
165 |
with tenant_context(tenant): |
|
166 |
hobo_json = tenant.get_hobo_json() |
|
167 |
assert hasattr(settings, 'KNOWN_SERVICES') |
|
168 |
assert 'authentic' in settings.KNOWN_SERVICES |
|
169 |
assert 'other' in settings.KNOWN_SERVICES['authentic'] |
|
170 |
assert (set(['url', 'backoffice-menu-url', 'title', 'orig', 'verif_orig', 'secret', 'variables']) |
|
171 |
== set(settings.KNOWN_SERVICES['authentic']['other'].keys())) |
|
172 |
assert (settings.KNOWN_SERVICES['authentic']['other']['url'] |
|
173 |
== hobo_json['services'][2]['base_url']) |
|
174 |
assert (settings.KNOWN_SERVICES['authentic']['other']['variables'] |
|
175 |
== hobo_json['services'][2].get('variables')) |
|
176 |
assert (settings.KNOWN_SERVICES['authentic']['other']['title'] |
|
177 |
== hobo_json['services'][2]['title']) |
|
178 |
assert settings.KNOWN_SERVICES['authentic']['other']['orig'] == tenant.domain_url |
|
179 |
assert (settings.KNOWN_SERVICES['authentic']['other']['verif_orig'] == |
|
180 |
'other.example.net') |
|
181 |
key1 = hobo_json['services'][0]['secret_key'] |
|
182 |
key2 = hobo_json['services'][2]['secret_key'] |
|
183 |
assert (settings.KNOWN_SERVICES['authentic']['other']['secret'] == |
|
184 |
KnownServices.shared_secret(key1, key2)) |
|
144 |
- |