Projet

Général

Profil

0003-auth-inject-dnsbl-function-in-condition-evaluation-c.patch

Benjamin Dauvergne, 29 novembre 2021 14:35

Télécharger (4,51 ko)

Voir les différences:

Subject: [PATCH 3/3] auth: inject dnsbl function in condition evaluation
 context (#58055)

 src/authentic2/utils/evaluate.py | 17 +++++++++++++++--
 src/authentic2/views.py          |  5 ++---
 tests/test_auth_saml.py          | 21 +++++++++++++++++++++
 3 files changed, 38 insertions(+), 5 deletions(-)
src/authentic2/utils/evaluate.py
93 93
def check_dnsbl(dnsbl, remote_addr):
94 94
    domain = '.'.join(reversed(remote_addr.split('.'))) + '.' + dnsbl
95 95
    exception = None
96
    log = logger.debug
96 97
    try:
97 98
        answers = dns.resolver.resolve(domain, 'A', lifetime=1)
98 99
        result = any(answer.address for answer in answers)
......
104 105
        result = False
105 106
    except dns.exception.DNSException as e:
106 107
        exception = e
107
        logger.warning(f'utils: could not check dnsbl {dnsbl} for domain "%s": %s', domain, e)
108
        log = logger.warning
108 109
        result = False
109
    logger.debug('utils: dnsbl lookup of "%s", result=%s exception=%s', domain, result, exception)
110
    log('utils: dnsbl lookup of "%s", result=%s exception=%s', domain, result, exception)
110 111
    return result
111 112

  
112 113

  
......
299 300
        if on_raise is not None:
300 301
            return on_raise
301 302
        raise e
303

  
304

  
305
def make_condition_context(*, request=None, **kwargs):
306
    '''Helper to make a condition context'''
307
    ctx = {
308
        'dnsbl': dnsbl,
309
    }
310
    if request:
311
        ctx['headers'] = HTTPHeaders(request)
312
        ctx['remote_addr'] = request.META.get('REMOTE_ADDR')
313
    ctx.update(kwargs)
314
    return ctx
src/authentic2/views.py
62 62
from .forms import registration as registration_forms
63 63
from .utils import misc as utils_misc
64 64
from .utils import switch_user as utils_switch_user
65
from .utils.evaluate import HTTPHeaders
65
from .utils.evaluate import make_condition_context
66 66
from .utils.service import get_service_from_request, get_service_from_token, set_service_ref
67 67
from .utils.view_decorators import enable_view_restriction
68 68

  
......
344 344
        else:  # New frontends API
345 345
            auth_blocks = []
346 346
            parameters = {'request': request, 'context': context}
347
            remote_addr = request.META.get('REMOTE_ADDR')
348 347
            login_hint = set(request.session.get('login-hint', []))
349
            show_ctx = dict(remote_addr=remote_addr, login_hint=login_hint, headers=HTTPHeaders(request))
348
            show_ctx = make_condition_context(request=request, login_hint=login_hint)
350 349
            if service:
351 350
                show_ctx['service_ou_slug'] = service.ou and service.ou.slug
352 351
                show_ctx['service_slug'] = service.slug
tests/test_auth_saml.py
16 16

  
17 17
import os
18 18
import re
19
from unittest import mock
19 20

  
20 21
import lasso
21 22
import pytest
......
239 240
    assert 'login-saml-1' not in response
240 241

  
241 242

  
243
def test_login_condition_dnsbl(db, app, settings, caplog):
244
    settings.A2_AUTH_SAML_ENABLE = True
245
    settings.MELLON_IDENTITY_PROVIDERS = [
246
        {"METADATA": os.path.join(os.path.dirname(__file__), 'metadata.xml')},
247
        {"METADATA": os.path.join(os.path.dirname(__file__), 'metadata.xml')},
248
    ]
249
    settings.AUTH_FRONTENDS_KWARGS = {
250
        'saml': {
251
            'show_condition': {
252
                '0': 'remote_addr in dnsbl(\'dnswl.example.com\')',
253
                '1': 'remote_addr not in dnsbl(\'dnswl.example.com\')',
254
            }
255
        }
256
    }
257
    with mock.patch('authentic2.utils.evaluate.check_dnsbl', return_value=True):
258
        response = app.get('/login/')
259
    assert 'login-saml-0' in response
260
    assert 'login-saml-1' not in response
261

  
262

  
242 263
def test_login_autorun(db, app, settings):
243 264
    response = app.get('/login/')
244 265

  
245
-