python3: migrate authentic (#40407)

This commit is contained in:
Paul Marillonnet 2020-03-04 14:31:36 +01:00 committed by Benjamin Dauvergne
parent 5fe3fcb667
commit 0ca228fa96
6 changed files with 327 additions and 230 deletions

View File

@ -1,5 +1,5 @@
import json
from urlparse import urljoin
from django.utils.six.moves.urllib.parse import urljoin
import threading
import copy
import logging
@ -8,6 +8,7 @@ from django.contrib.auth import get_user_model
from django.db import connection
from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils.encoding import force_text
from django_rbac.utils import get_role_model, get_ou_model, get_role_parenting_model
from hobo.agent.common import notify_agents
@ -25,9 +26,9 @@ logger = logging.getLogger(__name__)
class Provisionning(threading.local):
__slots__ = ['threads']
threads = set()
def __init__(self):
self.threads = set()
self.stack = []
def start(self):
@ -100,7 +101,7 @@ class Provisionning(threading.local):
def is_forbidden_technical_role(role):
return role.slug.startswith('_') and not role.slug.startswith(tuple(allowed_technical_roles_prefixes))
issuer = unicode(self.get_entity_id())
issuer = force_text(self.get_entity_id())
if mode == 'provision':
def user_to_json(ou, service, user, user_roles):
@ -151,8 +152,8 @@ class Provisionning(threading.local):
for rp in RoleParenting.objects.filter(child__in=all_roles):
parents.setdefault(rp.child.id, []).append(rp.parent.id)
Through = Role.members.through
for u_id, r_id in Through.objects.filter(role__members__in=users).values_list('user_id',
'role_id'):
qs = Through.objects.filter(role__members__in=users).values_list('user_id', 'role_id')
for u_id, r_id in qs:
user_roles.setdefault(u_id, set()).add(roles[r_id])
for p_id in parents.get(r_id, []):
user_roles[u_id].add(roles[p_id])
@ -163,7 +164,7 @@ class Provisionning(threading.local):
ous.setdefault(r.ou, set()).add(user)
if roles_with_attributes:
for ou, users in ous.iteritems():
for ou, users in ous.items():
for service, audience in self.get_audience(ou):
for user in users:
logger.info(u'provisionning user %s to %s', user, audience)
@ -178,12 +179,12 @@ class Provisionning(threading.local):
}
})
else:
for ou, users in ous.iteritems():
for ou, users in ous.items():
audience = [a for service, a in self.get_audience(ou)]
if not audience:
continue
logger.info(u'provisionning users %s to %s',
u', '.join(map(unicode, users)), u', '.join(audience))
logger.info(u'provisionning users %s to %s', u', '.join(
map(force_text, users)), u', '.join(audience))
notify_agents({
'@type': 'provision',
'issuer': issuer,
@ -197,8 +198,8 @@ class Provisionning(threading.local):
elif users:
audience = [audience for ou in OU.objects.all()
for s, audience in self.get_audience(ou)]
logger.info(u'deprovisionning users %s from %s', u', '.join(map(unicode, users)),
u', '.join(audience))
logger.info(u'deprovisionning users %s from %s', u', '.join(
map(force_text, users)), u', '.join(audience))
notify_agents({
'@type': 'deprovision',
'issuer': issuer,
@ -263,7 +264,7 @@ class Provisionning(threading.local):
})
global_roles = set(ous.get(None, []))
for ou, ou_roles in ous.iteritems():
for ou, ou_roles in ous.items():
sent_roles = set(ou_roles) | global_roles
helper(ou, sent_roles)

View File

@ -1,10 +1,9 @@
import os
import json
import hashlib
from importlib import import_module
from django.conf import settings
from django.utils.encoding import smart_bytes
from django.utils.encoding import force_bytes
from django.utils.http import urlencode
from django.utils.six.moves.urllib import parse as urlparse
@ -277,14 +276,14 @@ class CookieNames(object):
return 0
def update_settings(self, tenant_settings, tenant):
domain_hash = hashlib.md5(smart_bytes(tenant.domain_url)).hexdigest()[:6]
domain_hash = hashlib.md5(force_bytes(tenant.domain_url)).hexdigest()[:6]
tenant_settings.CSRF_COOKIE_NAME = 'csrftoken-%s' % domain_hash
tenant_settings.SESSION_COOKIE_NAME = 'sessionid-%s' % domain_hash
# unique but common name for authentic opened session cookie name
if getattr(tenant_settings, 'TEMPLATE_VARS', None):
idp_url = tenant_settings.TEMPLATE_VARS.get('idp_url')
if idp_url:
idp_hash = hashlib.md5(smart_bytes(idp_url)).hexdigest()[:6]
idp_hash = hashlib.md5(force_bytes(idp_url)).hexdigest()[:6]
cookie_name = 'a2-opened-session-%s' % idp_hash
tenant_settings.A2_OPENED_SESSION_COOKIE_NAME = cookie_name
tenant_settings.MELLON_OPENED_SESSION_COOKIE_NAME = cookie_name
@ -308,7 +307,7 @@ class Authentic(FileBaseSettingsLoader):
if not getattr(tenant_settings, 'A2_IDP_OIDC_JWKSET', None):
from jwcrypto import jwk
jwkkey = jwk.JWK.from_pem(
tenant_settings.A2_IDP_SAML2_SIGNATURE_PRIVATE_KEY)
force_bytes(tenant_settings.A2_IDP_SAML2_SIGNATURE_PRIVATE_KEY))
jwkset = jwk.JWKSet()
jwkset['keys'].add(jwkkey)
tenant_settings.A2_IDP_OIDC_JWKSET = json.loads(jwkset.export())

View File

@ -43,166 +43,38 @@
"uuid": "18e7bf78dc9a432396a99f32060052ec"
},
{
"attributes": [
{
"kind": "string",
"name": "is_superuser",
"value": "true"
}
],
"description": "",
"external_id": "",
"name": "Administrateur de Compte citoyen",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": {
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"slug": "portal"
},
"slug": "_a2-hobo-superuser",
"uuid": "84b3b1ba76e44bcdb4fd4437c448a981"
},
{
"attributes": [
{
"kind": "string",
"name": "is_superuser",
"value": "true"
}
],
"description": "",
"external_id": "",
"name": "Administrateur de D\u00e9marches",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": {
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"slug": "eservices"
},
"slug": "_a2-hobo-superuser",
"uuid": "9054a61ccf684396b38189f1ca1ec087"
},
{
"attributes": [
{
"kind": "string",
"name": "is_superuser",
"value": "true"
}
],
"description": "",
"external_id": "",
"name": "Administrateur de Hobo",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": {
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"slug": "hobo"
},
"slug": "_a2-hobo-superuser",
"uuid": "25f33158b7e2449b9a5b00dbc57bf416"
},
{
"attributes": [
{
"kind": "string",
"name": "is_superuser",
"value": "true"
}
],
"description": "",
"external_id": "",
"name": "Administrateur de Passerelle",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": {
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"slug": "passerelle"
},
"slug": "_a2-hobo-superuser",
"uuid": "243f58712aa248e9b27aae669341c156"
},
{
"attributes": [
{
"kind": "string",
"name": "is_superuser",
"value": "true"
}
],
"description": "",
"external_id": "",
"name": "Administrateur de Portail agent",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": {
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"slug": "portal-agent"
},
"slug": "_a2-hobo-superuser",
"uuid": "e6e22e5c0ca04ac0bf3b50d88eafe6d5"
},
{
"description": "",
"external_id": "",
"name": "Administrateur",
"name": "Manager",
"ou": null,
"parents": [
{
"name": "Administrateur des entit\u00e9s",
"name": "Manager of organizational units",
"ou": null,
"service": null,
"slug": "_a2-administrateur-des-entites",
"uuid": "a1ff1b3da88f47cea91e344998dfdfbf"
"slug": "_a2-manager-of-organizational-units",
"uuid": "b0e5379e65e34494b3d1feb1ffdd5234"
},
{
"name": "Administrateur des r\u00f4les",
"name": "Manager of roles",
"ou": null,
"service": null,
"slug": "_a2-administrateur-des-roles",
"uuid": "8dd625b74cff40aa8531d7d72616550e"
"slug": "_a2-manager-of-roles",
"uuid": "1b58e06308c5493f9571484139b13aa4"
},
{
"name": "Administrateur des utilisateurs",
"name": "Manager of services",
"ou": null,
"service": null,
"slug": "_a2-administrateur-des-utilisateurs",
"uuid": "4ab5effedc404fb1bcba4d21ee89b719"
"slug": "_a2-manager-of-services",
"uuid": "72faf45646c44054a60c11404d526f9b"
},
{
"name": "Manager of users",
"ou": null,
"service": null,
"slug": "_a2-manager-of-users",
"uuid": "47ef76b626c44d5eaf8d6de7fe8c4cdb"
}
],
"permissions": [
@ -212,11 +84,11 @@
},
"ou": null,
"target": {
"name": "Administrateur",
"name": "Manager",
"ou": null,
"service": null,
"slug": "_a2-manager",
"uuid": "81a8708382bb4e8ea12ed0e172aa48b9"
"uuid": "f6a4d39b864a40b68d2e0068ece14e14"
},
"target_ct": {
"app_label": "a2_rbac",
@ -226,12 +98,12 @@
],
"service": null,
"slug": "_a2-manager",
"uuid": "81a8708382bb4e8ea12ed0e172aa48b9"
"uuid": "f6a4d39b864a40b68d2e0068ece14e14"
},
{
"description": "",
"external_id": "",
"name": "Administrateur des entit\u00e9s",
"name": "Manager of organizational units",
"ou": null,
"permissions": [
{
@ -261,30 +133,16 @@
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "view"
},
"ou": null,
"target": {
"app_label": "a2_rbac",
"model": "organizationalunit"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
}
],
"service": null,
"slug": "_a2-administrateur-des-entites",
"uuid": "a1ff1b3da88f47cea91e344998dfdfbf"
"slug": "_a2-manager-of-organizational-units",
"uuid": "b0e5379e65e34494b3d1feb1ffdd5234"
},
{
"description": "",
"external_id": "",
"name": "Administrateur des r\u00f4les",
"name": "Manager of roles",
"ou": null,
"permissions": [
{
@ -315,20 +173,6 @@
"model": "contenttype"
}
},
{
"operation": {
"slug": "view"
},
"ou": null,
"target": {
"app_label": "a2_rbac",
"model": "organizationalunit"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "view"
@ -345,13 +189,52 @@
}
],
"service": null,
"slug": "_a2-administrateur-des-roles",
"uuid": "8dd625b74cff40aa8531d7d72616550e"
"slug": "_a2-manager-of-roles",
"uuid": "1b58e06308c5493f9571484139b13aa4"
},
{
"description": "",
"external_id": "",
"name": "Administrateur des utilisateurs",
"name": "Manager of services",
"ou": null,
"permissions": [
{
"operation": {
"slug": "admin"
},
"ou": null,
"target": {
"app_label": "authentic2",
"model": "service"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "search"
},
"ou": null,
"target": {
"app_label": "a2_rbac",
"model": "organizationalunit"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
}
],
"service": null,
"slug": "_a2-manager-of-services",
"uuid": "72faf45646c44054a60c11404d526f9b"
},
{
"description": "",
"external_id": "",
"name": "Manager of users",
"ou": null,
"permissions": [
{
@ -381,30 +264,77 @@
"app_label": "contenttypes",
"model": "contenttype"
}
}
],
"service": null,
"slug": "_a2-manager-of-users",
"uuid": "47ef76b626c44d5eaf8d6de7fe8c4cdb"
},
{
"description": "",
"external_id": "",
"name": "Managers of \"Collectivit\u00e9 par d\u00e9faut\"",
"ou": null,
"parents": [
{
"name": "Roles - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": null,
"slug": "_a2-manager-of-roles-default",
"uuid": "aeedec8fb6b9499ba3818095fd60d626"
},
{
"name": "Services - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": null,
"slug": "_a2-manager-of-services-default",
"uuid": "3945773a889f4264ac8b0f1f36972d96"
},
{
"name": "Users - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"service": null,
"slug": "_a2-manager-of-users-default",
"uuid": "bd16770736bb42528c780d6e8e38a0de"
}
],
"permissions": [
{
"operation": {
"slug": "view"
},
"ou": null,
"target": {
"app_label": "a2_rbac",
"model": "organizationalunit"
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
"app_label": "a2_rbac",
"model": "organizationalunit"
}
}
],
"service": null,
"slug": "_a2-administrateur-des-utilisateurs",
"uuid": "4ab5effedc404fb1bcba4d21ee89b719"
"slug": "_a2-managers-of-default",
"uuid": "ef5e7ae84bc648608eb10dab6128ac7e"
},
{
"description": "",
"external_id": "",
"name": "Administrateur du r\u00f4le \u00ab\u00a0Debug eo\u00a0\u00bb",
"name": "Managers of role \"Debug eo\"",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
@ -442,7 +372,7 @@
},
"ou": null,
"target": {
"name": "Administrateur du r\u00f4le \u00ab\u00a0Debug eo\u00a0\u00bb",
"name": "Managers of role \"Debug eo\"",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
@ -450,7 +380,7 @@
},
"service": null,
"slug": "_a2-managers-of-role-debug-eo",
"uuid": "3049444b35874b3b9a8377ad2f10b8b6"
"uuid": "ec1bee9eb7c040ad841b03916b593da2"
},
"target_ct": {
"app_label": "a2_rbac",
@ -474,7 +404,169 @@
],
"service": null,
"slug": "_a2-managers-of-role-debug-eo",
"uuid": "3049444b35874b3b9a8377ad2f10b8b6"
"uuid": "ec1bee9eb7c040ad841b03916b593da2"
},
{
"description": "",
"external_id": "",
"name": "Roles - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"permissions": [
{
"operation": {
"slug": "admin"
},
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target": {
"app_label": "a2_rbac",
"model": "role"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "search"
},
"ou": null,
"target": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target_ct": {
"app_label": "a2_rbac",
"model": "organizationalunit"
}
},
{
"operation": {
"slug": "view"
},
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target": {
"app_label": "custom_user",
"model": "user"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
}
],
"service": null,
"slug": "_a2-manager-of-roles-default",
"uuid": "aeedec8fb6b9499ba3818095fd60d626"
},
{
"description": "",
"external_id": "",
"name": "Services - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"permissions": [
{
"operation": {
"slug": "admin"
},
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target": {
"app_label": "authentic2",
"model": "service"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "search"
},
"ou": null,
"target": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target_ct": {
"app_label": "a2_rbac",
"model": "organizationalunit"
}
}
],
"service": null,
"slug": "_a2-manager-of-services-default",
"uuid": "3945773a889f4264ac8b0f1f36972d96"
},
{
"description": "",
"external_id": "",
"name": "Users - Collectivit\u00e9 par d\u00e9faut",
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"permissions": [
{
"operation": {
"slug": "admin"
},
"ou": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target": {
"app_label": "custom_user",
"model": "user"
},
"target_ct": {
"app_label": "contenttypes",
"model": "contenttype"
}
},
{
"operation": {
"slug": "search"
},
"ou": null,
"target": {
"name": "Collectivit\u00e9 par d\u00e9faut",
"slug": "default",
"uuid": "69b0a02cf58a4c71b1ae548f1375baff"
},
"target_ct": {
"app_label": "a2_rbac",
"model": "organizationalunit"
}
}
],
"service": null,
"slug": "_a2-manager-of-users-default",
"uuid": "bd16770736bb42528c780d6e8e38a0de"
}
]
}

View File

@ -44,3 +44,5 @@ HOBO_ROLE_EXPORT = True
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SECURE = False
LANGUAGE_CODE = 'en'

View File

@ -308,7 +308,7 @@ def test_hobo_deploy(monkeypatch, tenant_base, mocker, skeleton_dir):
]
}
hobo_json_content = json.dumps(env)
hobo_json = tempfile.NamedTemporaryFile()
hobo_json = tempfile.NamedTemporaryFile(mode='w')
hobo_json.write(hobo_json_content)
hobo_json.flush()
@ -463,28 +463,31 @@ def test_hobo_deploy(monkeypatch, tenant_base, mocker, skeleton_dir):
def test_import_template(db, tenant_base):
def with_uuid_removed(input):
if isinstance(input, dict):
for key in input.keys():
if key == 'uuid':
input.pop('uuid')
return {k: with_uuid_removed(v) for k, v in input.iteritems()}
elif isinstance(input, list):
return [with_uuid_removed(e) for e in input]
else:
return input
def listify(value):
if isinstance(value, dict):
value = list((k, listify(v)) for k, v in value.items())
value.sort()
if isinstance(value, list):
value = list(listify(x) for x in value)
value.sort()
return value
def with_lists_sorted(input):
if isinstance(input, dict):
return {k: with_lists_sorted(v) for k, v in input.iteritems()}
if isinstance(input, list):
return with_lists_sorted(input.sort())
else:
return input
def sort_and_remove_uuid(value):
if isinstance(value, dict):
if 'uuid' in value:
value.pop('uuid')
value = {k: sort_and_remove_uuid(v) for k, v in value.items()}
if isinstance(value, list):
value = [sort_and_remove_uuid(elt) for elt in value]
value.sort(key=lambda elt: listify(elt))
return value
call_command('create_tenant', 'authentic.example.net')
tenant = TenantMiddleware.get_tenant_by_hostname('authentic.example.net')
connection.set_tenant(tenant)
call_command('import_template', '--basepath=%s' % os.path.dirname(__file__), 'data_authentic_export_site')
content = open('%s/data_authentic_export_site.json' % os.path.dirname(__file__)).read()
assert byteify(with_lists_sorted(with_uuid_removed(export_site()))) == byteify(with_lists_sorted(with_uuid_removed(json.loads(content))))
export_ref = sort_and_remove_uuid(export_site())
file_ref = sort_and_remove_uuid(json.loads(content))
assert export_ref == file_ref

View File

@ -1,5 +1,5 @@
import pytest
import urllib
from django.utils.six.moves.urllib import parse as urllib
from rest_framework.exceptions import AuthenticationFailed