Projet

Général

Profil

0001-auth_saml-reorganize-and-fix-tests-48117.patch

Benjamin Dauvergne, 29 octobre 2020 16:32

Télécharger (9,55 ko)

Voir les différences:

Subject: [PATCH] auth_saml: reorganize and fix tests (#48117)

 tests/test_auth_saml.py | 205 +++++++++++++++++++++-------------------
 1 file changed, 110 insertions(+), 95 deletions(-)
tests/test_auth_saml.py
23 23

  
24 24
from django.contrib.auth import get_user_model
25 25
from authentic2.models import Attribute
26
from authentic2_auth_saml.adapters import MappingError
26
from authentic2_auth_saml.adapters import AuthenticAdapter, MappingError
27

  
28
User = get_user_model()
27 29

  
28 30

  
29 31
def test_providers_on_login_page(db, app, settings):
......
52 54
    assert response.pyquery('button[name="login-saml-1"]')
53 55

  
54 56

  
55
def test_provision_attributes(db, caplog):
56
    from authentic2_auth_saml.adapters import AuthenticAdapter
57
@pytest.fixture
58
def adapter():
59
    return AuthenticAdapter()
60

  
57 61

  
58
    adapter = AuthenticAdapter()
59
    User = get_user_model()
60
    Attribute.objects.create(kind='title', name='title', label='title')
62
@pytest.fixture
63
def idp():
61 64

  
62
    user = User.objects.create()
63
    idp = {
65
    return {
64 66
        'A2_ATTRIBUTE_MAPPING': [
65 67
            {
66 68
                'attribute': 'email',
......
83 85
        ]
84 86
    }
85 87

  
86
    saml_attributes = {
87
        u'issuer': 'https://idp.com/',
88
        u'name_id_content': 'xxx',
89
        u'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
90
        u'mail': [u'john.doe@example.com'],
91
        u'title': [u'Mr.'],
92
        u'http://fucking/attribute/givenName': ['John'],
93
    }
94
    user = adapter.lookup_user(idp, saml_attributes)
95
    user.refresh_from_db()
96
    assert user.email == 'john.doe@example.com'
97
    assert user.attributes.title == 'Mr.'
98
    assert user.first_name == 'John'
99
    user.delete()
100

  
101
    # on missing mandatory attribute, no user is created
102
    del saml_attributes['mail']
103
    assert adapter.lookup_user(idp, saml_attributes) is None
104 88

  
105
    # simulate no attribute value
106
    saml_attributes['first_name'] = []
107
    mapping = {
108
        'attribute': 'first_name',
109
        'saml_attribute': 'first_name',
110
    }
111
    with pytest.raises(MappingError, match='no value for first_name'):
112
        adapter.action_set_attribute(user, idp, saml_attributes, mapping)
89
@pytest.fixture
90
def title_attribute(db):
91
    return Attribute.objects.create(kind='title', name='title', label='title')
113 92

  
114 93

  
115
@pytest.mark.parametrize('action_name', ['add-role', 'toggle-role'])
116
def test_provision_add_role(db, simple_role, action_name):
117
    from authentic2_auth_saml.adapters import AuthenticAdapter
118

  
119
    adapter = AuthenticAdapter()
120
    User = get_user_model()
121
    user = User.objects.create()
122
    idp = {
123
        'A2_ATTRIBUTE_MAPPING': [
124
            {
125
                'action': action_name,
126
                'role': {
127
                    'name': simple_role.name,
128
                    'ou': {
129
                        'name': simple_role.ou.name,
130
                    },
131
                },
132
                'condition': "roles == 'A'",
133
            }
134
        ]
135
    }
136

  
137
    saml_attributes = {
94
@pytest.fixture
95
def saml_attributes():
96
    return {
138 97
        'issuer': 'https://idp.com/',
139 98
        'name_id_content': 'xxx',
140 99
        'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
100
        'mail': ['john.doe@example.com'],
101
        'title': ['Mr.'],
102
        'http://fucking/attribute/givenName': ['John'],
141 103
    }
142
    user = adapter.lookup_user(idp, saml_attributes)
143
    user.refresh_from_db()
144
    assert simple_role not in user.roles.all()
145
    assert user.ou.default is True
146
    user.delete()
147 104

  
148
    # if a toggle-role is mandatory, failure to evaluate condition block user creation
149
    assert idp['A2_ATTRIBUTE_MAPPING'][-1]['action'] == action_name
150
    idp['A2_ATTRIBUTE_MAPPING'][-1]['mandatory'] = True
151
    assert adapter.lookup_user(idp, saml_attributes) is None
152 105

  
153
    saml_attributes['roles'] = ['A']
154
    user = adapter.lookup_user(idp, saml_attributes)
155
    user.refresh_from_db()
156
    assert simple_role in user.roles.all()
157
    user.delete()
106
@pytest.fixture
107
def user(db):
108
    return User.objects.create()
109

  
110

  
111
def test_lookup_user_ok(adapter, idp, saml_attributes, title_attribute):
112
    assert User.objects.count() == 0
158 113

  
159
    idp['A2_ATTRIBUTE_MAPPING'][-1]['condition'] = "'A' in roles__list"
160 114
    user = adapter.lookup_user(idp, saml_attributes)
161 115
    user.refresh_from_db()
162
    assert simple_role in user.roles.all()
116
    assert user.email == 'john.doe@example.com'
117
    assert user.attributes.title == 'Mr.'
118
    assert user.first_name == 'John'
119
    assert user.attributes.title == 'Mr.'
120
    assert user.ou.default is True
163 121

  
164
    saml_attributes['roles'] = []
165
    adapter.provision(user, idp, saml_attributes)
166
    # condition failed, so role should be removed
167
    assert simple_role not in user.roles.all()
168
    user.delete()
169 122

  
170
    # on missing mandatory attribute, no user is created
123
def test_lookup_user_missing_mandatory_attribute(adapter, idp, saml_attributes, title_attribute):
171 124
    del saml_attributes['mail']
125

  
126
    assert User.objects.count() == 0
172 127
    assert adapter.lookup_user(idp, saml_attributes) is None
128
    assert User.objects.count() == 0
129

  
130

  
131
def test_apply_attribute_mapping_missing_attribute_logged(caplog, adapter, idp, saml_attributes, title_attribute, user):
132
    caplog.set_level('WARNING')
133
    saml_attributes['http://fucking/attribute/givenName'] = []
134
    adapter.apply_attribute_mapping(user, idp, saml_attributes, idp['A2_ATTRIBUTE_MAPPING'])
135
    assert re.match('.*no value.*first_name', caplog.records[-1].message)
136

  
137

  
138
def test_apply_attribute_mapping_missing_attribute_exception(adapter, idp, saml_attributes, title_attribute, user):
139
    saml_attributes['http://fucking/attribute/givenName'] = []
140
    idp['A2_ATTRIBUTE_MAPPING'][-1]['mandatory'] = True
141
    with pytest.raises(MappingError, match='no value'):
142
        adapter.apply_attribute_mapping(user, idp, saml_attributes, idp['A2_ATTRIBUTE_MAPPING'])
173 143

  
174
    # simulate no attribute value
175
    saml_attributes['first_name'] = []
176
    attribute_mapping = [
177
        {
178
            'mandatory': True,
179
            'attribute': 'first_name',
180
            'saml_attribute': 'first_name',
144

  
145
@pytest.mark.parametrize('action_name', ['add-role', 'toggle-role'])
146
class TestAddRole:
147
    @pytest.fixture
148
    def idp(self, action_name, simple_role):
149
        return {
150
            'A2_ATTRIBUTE_MAPPING': [
151
                {
152
                    'action': action_name,
153
                    'role': {
154
                        'name': simple_role.name,
155
                        'ou': {
156
                            'name': simple_role.ou.name,
157
                        },
158
                    },
159
                    'condition': "roles == 'A'",
160
                }
161
            ]
181 162
        }
182
    ]
183 163

  
184
    # fail fast
185
    with pytest.raises(MappingError, match='no value.*first_name'):
186
        adapter.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping)
164
    @pytest.fixture
165
    def saml_attributes(self):
166
        return {
167
            'issuer': 'https://idp.com/',
168
            'name_id_content': 'xxx',
169
            'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
170
        }
187 171

  
188
    # or log a warning
189
    caplog.clear()
190
    del attribute_mapping[0]['mandatory']
191
    adapter.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping)
192
    assert re.match('.*no value.*first_name', caplog.records[0].message)
172
    def test_lookup_user_condition_fails(self, adapter, simple_role, idp, saml_attributes):
173
        user = adapter.lookup_user(idp, saml_attributes)
174
        assert simple_role not in user.roles.all()
175

  
176
    def test_lookup_user_condition_success(self, adapter, simple_role, idp, saml_attributes):
177
        saml_attributes['roles'] = ['A']
178
        user = adapter.lookup_user(idp, saml_attributes)
179
        assert simple_role in user.roles.all()
180

  
181
    def test_lookup_user_mandatory_condition(self, adapter, simple_role, idp, saml_attributes):
182
        # if a toggle-role is mandatory, failure to evaluate condition block user creation
183
        idp['A2_ATTRIBUTE_MAPPING'][0]['mandatory'] = True
184
        assert adapter.lookup_user(idp, saml_attributes) is None
185

  
186
    def test_lookup_user_mandatory(self, adapter, simple_role, idp, saml_attributes):
187
        idp['A2_ATTRIBUTE_MAPPING'][0]['mandatory'] = True
188
        saml_attributes['roles'] = ['A']
189
        user = adapter.lookup_user(idp, saml_attributes)
190
        assert simple_role in user.roles.all()
191

  
192
    def test_lookup_user_use_list(self, adapter, simple_role, idp, saml_attributes):
193
        idp['A2_ATTRIBUTE_MAPPING'][0]['condition'] = "'A' in roles__list"
194
        saml_attributes['roles'] = ['A']
195
        user = adapter.lookup_user(idp, saml_attributes)
196
        assert simple_role in user.roles.all()
197

  
198
    def test_lookup_user_add_and_remove(self, adapter, simple_role, idp, saml_attributes, caplog):
199
        saml_attributes['roles'] = ['A']
200
        user = adapter.lookup_user(idp, saml_attributes)
201
        assert simple_role in user.roles.all()
202

  
203
        saml_attributes['roles'] = []
204
        adapter.provision(user, idp, saml_attributes)
205
        # condition failed, so role should be removed
206
        user.refresh_from_db()
207
        assert simple_role not in user.roles.all()
193 208

  
194 209

  
195 210
def test_login_with_conditionnal_authenticators(db, app, settings, caplog):
196
-