Projet

Général

Profil

0001-settings-set-secure-flag-on-cookies-71880.patch

Benjamin Dauvergne, 30 novembre 2022 15:28

Télécharger (15,9 ko)

Voir les différences:

Subject: [PATCH 1/2] settings: set secure flag on cookies (#71880)

 src/authentic2/settings.py    |  5 +++++
 tests/api/test_all.py         | 16 ++++++++--------
 tests/auth_fc/conftest.py     |  4 ++--
 tests/auth_fc/test_auth_fc.py |  2 +-
 tests/conftest.py             |  6 ++++--
 tests/idp_oidc/test_misc.py   |  4 ++--
 tests/settings.py             |  2 +-
 tests/test_attribute_kinds.py |  2 +-
 tests/test_auth_oidc.py       |  2 +-
 tests/test_commands.py        |  2 +-
 tests/test_csv_import.py      |  2 +-
 tests/test_idp_saml2.py       | 14 ++++++++------
 tests/test_manager.py         |  6 +++---
 tests/test_password_reset.py  |  4 ++--
 14 files changed, 40 insertions(+), 31 deletions(-)
src/authentic2/settings.py
55 55
    }
56 56
}
57 57

  
58
# Cookies
59
SESSION_COOKIE_SECURE = True
60
CSRF_COOKIE_SECURE = True
61
LANGUAGE_COOKIE_SECURE = True
62

  
58 63
# Hey Entr'ouvert is in France !!
59 64
TIME_ZONE = 'Europe/Paris'
60 65
LANGUAGE_CODE = 'fr'
tests/api/test_all.py
100 100
    Role.objects.create(name='Role4', service=service)
101 101

  
102 102
    # test failure when unlogged
103
    response = client.get('/api/user/', HTTP_ORIGIN='http://testserver')
103
    response = client.get('/api/user/', HTTP_ORIGIN='https://testserver')
104 104
    assert response.content == b'{}'
105 105

  
106 106
    # login
107 107
    client.login(request=None, username='john.doe', password='password')
108
    response = client.get('/api/user/', HTTP_ORIGIN='http://testserver')
108
    response = client.get('/api/user/', HTTP_ORIGIN='https://testserver')
109 109
    data = json.loads(force_str(response.content))
110 110
    assert isinstance(data, dict)
111 111
    assert set(data.keys()) == {
......
1055 1055
    assert response.json['user']['last_name'] == last_name
1056 1056
    assert check_password(password, response.json['user']['password'])
1057 1057
    assert response.json['token']
1058
    assert response.json['validation_url'].startswith('http://testserver/accounts/activate/')
1058
    assert response.json['validation_url'].startswith('https://testserver/accounts/activate/')
1059 1059
    assert User.objects.count() == 2
1060 1060
    user = User.objects.latest('id')
1061 1061
    assert user.ou == get_default_ou()
......
1114 1114
    assert response.json['user']['last_name'] == last_name
1115 1115
    assert check_password(password, response.json['user']['password'])
1116 1116
    assert response.json['token']
1117
    assert response.json['validation_url'].startswith('http://testserver/accounts/activate/')
1117
    assert response.json['validation_url'].startswith('https://testserver/accounts/activate/')
1118 1118
    assert User.objects.count() == 2
1119 1119
    user = User.objects.latest('id')
1120 1120
    assert user.username == username
......
1232 1232
    assert len(mailoutbox) == 1
1233 1233
    mail = mailoutbox[0]
1234 1234
    assert mail.to[0] == email
1235
    assert 'http://testserver/password/reset/confirm/' in mail.body
1235
    assert 'https://testserver/password/reset/confirm/' in mail.body
1236 1236
    assert_event('manager.user.password.reset.request', user=admin, api=True)
1237 1237

  
1238 1238

  
......
1265 1265
    mail = mailoutbox[0]
1266 1266

  
1267 1267
    assert mail.to[0] == new_email
1268
    assert 'http://testserver/accounts/change-email/verify/' in mail.body
1268
    assert 'https://testserver/accounts/change-email/verify/' in mail.body
1269 1269

  
1270 1270

  
1271 1271
def test_api_delete_role(app, admin_ou1, role_ou1):
......
2391 2391
    assert len(resp.json['data']) == 6
2392 2392
    login_stats = {
2393 2393
        'name': 'Login count by authentication type',
2394
        'url': 'http://testserver/api/statistics/login/',
2394
        'url': 'https://testserver/api/statistics/login/',
2395 2395
        'id': 'login',
2396 2396
        'filters': [
2397 2397
            {
......
2411 2411
    assert login_stats in resp.json['data']
2412 2412
    assert {
2413 2413
        'name': 'Login count by service',
2414
        'url': 'http://testserver/api/statistics/service_login/',
2414
        'url': 'https://testserver/api/statistics/service_login/',
2415 2415
        'id': 'service-login',
2416 2416
        'filters': [
2417 2417
            {
tests/auth_fc/conftest.py
80 80

  
81 81
    @property
82 82
    def callback_url(self):
83
        return 'http://testserver' + reverse('fc-login-or-link')
83
        return 'https://testserver' + reverse('fc-login-or-link')
84 84

  
85 85
    def login_with_fc_fixed_params(self, app):
86 86
        if app.session:
......
154 154
        assert url.startswith('https://fcp.integ01.dev-franceconnect.fr/api/v1/logout')
155 155
        parsed_url = urllib.parse.urlparse(url)
156 156
        query = QueryDict(parsed_url.query)
157
        assert_equals_url(query['post_logout_redirect_uri'], 'http://testserver' + reverse('fc-logout'))
157
        assert_equals_url(query['post_logout_redirect_uri'], 'https://testserver' + reverse('fc-logout'))
158 158
        assert query['state']
159 159
        self.state = query['state']
160 160
        return app.get(reverse('fc-logout') + '?state=' + self.state)
tests/auth_fc/test_auth_fc.py
128 128
    for body in (mailoutbox[0].body, mailoutbox[0].alternatives[0][0]):
129 129
        assert 'Hi AnonymousUser,' in body
130 130
        assert 'You have just created an account using FranceConnect.' in body
131
        assert 'http://testserver/login/' in body
131
        assert 'https://testserver/login/' in body
132 132

  
133 133
    assert user.verified_attributes.first_name == 'Ÿuñe'
134 134
    assert user.verified_attributes.last_name == 'Frédérique'
tests/conftest.py
63 63
    try:
64 64

  
65 65
        def factory(hostname='testserver'):
66
            return django_webtest.DjangoTestApp(extra_environ={'HTTP_HOST': hostname})
66
            return django_webtest.DjangoTestApp(
67
                extra_environ={'HTTP_HOST': hostname, 'wsgi.url_scheme': 'https'}
68
            )
67 69

  
68 70
        yield factory
69 71
    finally:
......
420 422
    else:
421 423

  
422 424
        def check_location(response, default_return):
423
            assert urllib.parse.urljoin('http://testserver/', default_return).endswith(response['Location'])
425
            assert urllib.parse.urljoin('https://testserver/', default_return).endswith(response['Location'])
424 426

  
425 427
    return check_location
426 428

  
tests/idp_oidc/test_misc.py
353 353
    with open('tests/200x200.jpg', 'rb') as fd:
354 354
        simple_user.attributes.cityscape_image = File(fd)
355 355
    response = app.get(user_info_url, headers=bearer_authentication_headers(access_token))
356
    assert response.json['cityscape_image'].startswith('http://testserver/media/profile-image/')
356
    assert response.json['cityscape_image'].startswith('https://testserver/media/profile-image/')
357 357

  
358 358
    # check against a user without username
359 359
    simple_user.username = None
......
381 381
            src = iframes.attr('src')
382 382
            assert '?' in src
383 383
            src_qd = QueryDict(src.split('?', 1)[1])
384
            assert 'iss' in src_qd and src_qd['iss'] == 'http://testserver/'
384
            assert 'iss' in src_qd and src_qd['iss'] == 'https://testserver/'
385 385
            assert 'sid' in src_qd and src_qd['sid'] == get_session_id(
386 386
                mock.Mock(session=app.session), oidc_client
387 387
            )
tests/settings.py
55 55
TEMPLATES[0]['DIRS'].append('tests/templates')  # pylint: disable=undefined-variable
56 56
TEMPLATES[0]['OPTIONS']['debug'] = True  # pylint: disable=undefined-variable
57 57

  
58
SITE_BASE_URL = 'http://testserver'
58
SITE_BASE_URL = 'https://testserver'
59 59

  
60 60
A2_MAX_EMAILS_PER_IP = None
61 61
A2_MAX_EMAILS_FOR_ADDRESS = None
tests/test_attribute_kinds.py
541 541
    response = app.get('/api/users/%s/' % john().uuid)
542 542
    assert (
543 543
        response.json['cityscape_image']
544
        == 'http://testserver/media/%s' % john().attributes.cityscape_image.name
544
        == 'https://testserver/media/%s' % john().attributes.cityscape_image.name
545 545
    )
546 546
    app.authorization = None
547 547

  
tests/test_auth_oidc.py
511 511
    assert query['response_type'] == 'code'
512 512
    assert query['client_id'] == str(oidc_provider.client_id)
513 513
    assert query['scope'] == 'openid'
514
    assert query['redirect_uri'] == 'http://testserver' + reverse('oidc-login-callback')
514
    assert query['redirect_uri'] == 'https://testserver' + reverse('oidc-login-callback')
515 515
    nonce = query['nonce']
516 516

  
517 517
    if oidc_provider.claims_parameter_supported:
tests/test_commands.py
256 256
    simple_user.save()
257 257
    call_command('clean-unused-accounts')
258 258
    mail = mailoutbox[0]
259
    assert 'href="http://testserver/login/"' in mail.message().as_string()
259
    assert 'href="https://testserver/login/"' in mail.message().as_string()
260 260

  
261 261

  
262 262
def test_clean_unused_account_with_no_email(simple_user, mailoutbox, caplog):
tests/test_csv_import.py
559 559
    assert importer.run()
560 560
    thomas = User.objects.get(email='tnoel@entrouvert.com')
561 561
    assert len(mail.outbox) == 1
562
    assert 'http://testserver/password/reset/confirm/' in mail.outbox[0].body
562
    assert 'https://testserver/password/reset/confirm/' in mail.outbox[0].body
563 563

  
564 564
    password = thomas.password
565 565
    del mail.outbox[0]
tests/test_idp_saml2.py
149 149
        self.base_url = 'https://sp.example.com'
150 150
        self.name = 'Test SP'
151 151
        self.slug = 'test-sp'
152
        self.idp_entity_idp = ('http://testserver/idp/saml2/metadata',)
152
        self.idp_entity_idp = ('https://testserver/idp/saml2/metadata',)
153 153
        self.default_name_id_format = 'email'
154 154
        self.accepted_name_id_format = ['email', 'persistent', 'transient', 'username']
155 155
        self.ou = OrganizationalUnit.objects.get()
......
504 504
            ),
505 505
            (
506 506
                "/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name='avatar']/saml:AttributeValue",
507
                re.compile('^http://testserver/media/profile-image/.*$'),
507
                re.compile('^https://testserver/media/profile-image/.*$'),
508 508
            ),
509 509
            (
510 510
                "/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name='verified_attributes']/@NameFormat",
......
815 815
        == '_' + hashlib.sha256(b'b' + b'https://sp.com/' + b'a').hexdigest().upper()
816 816
    )
817 817

  
818
    edpt = saml2_endpoints.make_edu_person_targeted_id('http://testserver/idp/saml2/metadata', provider, user)
818
    edpt = saml2_endpoints.make_edu_person_targeted_id(
819
        'https://testserver/idp/saml2/metadata', provider, user
820
    )
819 821
    assert edpt is not None
820 822
    node = lasso.Node.newFromXmlNode(force_str(ET.tostring(edpt)))
821 823
    assert isinstance(node, lasso.Saml2NameID)
822 824
    assert force_str(node.content) == '_A485C0ACEEF43A6D39145F5CFE25D9D3B6F15DC6443F412263C76D81C72DA8D5'
823 825
    assert node.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
824 826

  
825
    assert node.nameQualifier == 'http://testserver/idp/saml2/metadata'
827
    assert node.nameQualifier == 'https://testserver/idp/saml2/metadata'
826 828
    assert node.spNameQualifier == 'https://sp.com/'
827 829

  
828 830

  
......
854 856
    assert isinstance(node, lasso.Saml2NameID)
855 857
    assert force_str(node.content) == '_A485C0ACEEF43A6D39145F5CFE25D9D3B6F15DC6443F412263C76D81C72DA8D5'
856 858
    assert node.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
857
    assert node.nameQualifier == 'http://testserver/idp/saml2/metadata'
859
    assert node.nameQualifier == 'https://testserver/idp/saml2/metadata'
858 860
    assert node.spNameQualifier == 'https://sp.com/'
859 861

  
860 862

  
......
886 888
    assert isinstance(node, lasso.Saml2NameID)
887 889
    assert force_str(node.content) == '_A485C0ACEEF43A6D39145F5CFE25D9D3B6F15DC6443F412263C76D81C72DA8D5'
888 890
    assert node.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
889
    assert node.nameQualifier == 'http://testserver/idp/saml2/metadata'
891
    assert node.nameQualifier == 'https://testserver/idp/saml2/metadata'
890 892
    assert node.spNameQualifier == 'https://sp.com/'
891 893

  
892 894

  
tests/test_manager.py
1306 1306
        {
1307 1307
            'label': 'Identity management',
1308 1308
            'slug': 'identity-management',
1309
            'url': 'http://testserver/manage/',
1309
            'url': 'https://testserver/manage/',
1310 1310
            'sub': False,
1311 1311
        },
1312
        {'label': 'Users', 'slug': 'users', 'url': 'http://testserver/manage/users/', 'sub': True},
1313
        {'label': 'Roles', 'slug': 'roles', 'url': 'http://testserver/manage/roles/', 'sub': True},
1312
        {'label': 'Users', 'slug': 'users', 'url': 'https://testserver/manage/users/', 'sub': True},
1313
        {'label': 'Roles', 'slug': 'roles', 'url': 'https://testserver/manage/roles/', 'sub': True},
1314 1314
    ]
1315 1315

  
1316 1316
    response = login(app, admin)
tests/test_password_reset.py
176 176
    for body in (mail.body, mail.alternatives[0][0]):
177 177
        assert 'no account was found associated with this address' in body
178 178
        if settings.REGISTRATION_OPEN:
179
            assert 'http://testserver/register/' in body
179
            assert 'https://testserver/register/' in body
180 180
            # check next_url was preserved
181 181
            assert 'next=/whatever/' in body
182 182
        else:
183
            assert 'http://testserver/register/' not in body
183
            assert 'https://testserver/register/' not in body
184 184

  
185 185

  
186 186
def test_send_password_reset_email_disabled_account(app, simple_user, mailoutbox):
187
-