Skip to content

Commit

Permalink
feat: Dynamic ACR response check - fixed #47
Browse files Browse the repository at this point in the history
  • Loading branch information
peppelinux committed Jun 19, 2021
1 parent 18c5d96 commit abcb3d3
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 106 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def readme():

setup(
name='spid_sp_test',
version='0.6.13',
version='0.7.0',
description="SAML2 SPID Service Provider validation tool that can be run from the command line",
long_description=readme(),
long_description_content_type='text/markdown',
Expand Down
2 changes: 1 addition & 1 deletion src/spid_sp_test/indicepa.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import requests
import logging
import requests


API_URL = 'https://indicepa.gov.it/PortaleServices/api/aoo'
Expand Down
32 changes: 29 additions & 3 deletions src/spid_sp_test/response.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import base64
import datetime
import importlib
import json
import logging
import random
Expand Down Expand Up @@ -48,7 +49,8 @@ def __init__(self,
response_attrs={},
authnreq_attrs={},
attributes={},
template_path='./templates'):
template_path='./templates',
status_codes=None):

try:
self.conf = deepcopy(
Expand All @@ -58,6 +60,10 @@ def __init__(self,
except KeyError:
raise Exception(f'Test {conf} doesn\'t exists')

# rewrite, eg: response_mods
if status_codes:
self.conf['status_codes'] = self.status_codes

self.attributes = attributes
self.authnreq_attrs = authnreq_attrs
self.response_attrs = response_attrs
Expand Down Expand Up @@ -139,6 +145,13 @@ def __init__(self, *args, **kwargs):
self.html_path = kwargs.get('html_path')
self.no_send_response = kwargs.get('no_send_response')
self.kwargs = kwargs
self.status_codes = None

def get_acr(self):
_acr = self.authnreq_etree.xpath(
'//RequestedAuthnContext/AuthnContextClassRef')
if _acr:
return _acr[0].text

def do_authnrequest(self):
self.authn_request_data = get_authn_request(self.authn_request_url)
Expand All @@ -152,6 +165,9 @@ def do_authnrequest(self):
self.authnreq_issuer = self.authnreq_etree.xpath(
"/AuthnRequest/Issuer")[0].attrib['NameQualifier']
now = datetime.datetime.utcnow()

self.acr = self.get_acr()

self.response_attrs = {
'ResponseID': saml_rnd_id(),
'AuthnRequestID': self.authnreq_attrs['ID'],
Expand All @@ -165,7 +181,7 @@ def do_authnrequest(self):
'SessionIndex': saml_rnd_id(),
'Issuer': self.issuer,
'Audience': self.authnreq_issuer,
'AuthnContextClassRef': settings.DEFAULT_RESPONSE['AuthnContextClassRef'],
'AuthnContextClassRef': self.acr or settings.DEFAULT_RESPONSE['AuthnContextClassRef'],
'IssueInstantMillis': now.strftime('%Y-%m-%dT%H:%M:%S.%f')
}
self.relay_state = self.kwargs.get('relay_state')
Expand Down Expand Up @@ -241,7 +257,8 @@ def load_test(self, test_name=None, attributes={}, response_attrs={}):
authnreq_attrs=self.authnreq_attrs,
attributes=attributes,
response_attrs=response_attrs or self.response_attrs,
template_path=self.template_path
template_path=self.template_path,
status_codes=self.status_codes
)
conf = settings.RESPONSE_TESTS[test_name]
if conf.get('response'):
Expand All @@ -250,6 +267,15 @@ def load_test(self, test_name=None, attributes={}, response_attrs={}):
f'Test {test_name}: overwriting {k} with {v}'
)
spid_response.response_attrs[k] = v

# response dinamyc mods and rewrites (plugins)
if conf.get('response_mods'):
for mod_func in conf['response_mods']:
n1, _, n2 = mod_func.rpartition('.')
module = importlib.import_module(n1)
func = getattr(module, n2)
func(self, spid_response)

return spid_response

def check_response(self, res, msg: str, attendeds=[]):
Expand Down
7 changes: 7 additions & 0 deletions src/spid_sp_test/responses/response_mods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from spid_sp_test.response import SpidSpResponse, SpidSpResponseCheck
from . settings import HTTP_STATUS_ERROR_CODES


def dynamic_acr(check:SpidSpResponseCheck, response_obj:SpidSpResponse, **kwargs):
if check.get_acr() != check.response_attrs['AuthnContextClassRef']:
response_obj.conf['status_codes'] = HTTP_STATUS_ERROR_CODES
Loading

0 comments on commit abcb3d3

Please sign in to comment.