Skip to content

Commit 06a4389

Browse files
authored
Adjust README to pyproject.toml and fix coverage (#413)
* Adjust README to pyproject.toml * Adjust coverage coveralls to pyproject.toml
1 parent 7658b88 commit 06a4389

File tree

5 files changed

+94
-82
lines changed

5 files changed

+94
-82
lines changed

.github/workflows/python-package.yml

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ jobs:
4747
run: make pytest
4848
lint:
4949
runs-on: ubuntu-22.04
50-
environment: CI
5150
steps:
5251
- uses: actions/checkout@v4
5352
- uses: actions/setup-python@v5
@@ -64,18 +63,37 @@ jobs:
6463
pip install -U setuptools
6564
sudo apt-get update -qq
6665
sudo apt-get install -qq swig libxml2-dev libxmlsec1-dev
67-
pip install --force-reinstall --no-binary lxml lxml
6866
make install-req
6967
make install-lint
7068
- name: Run linters
7169
run: |
7270
make flake8
7371
make black
72+
coveralls:
73+
runs-on: ubuntu-22.04
74+
environment: CI
75+
steps:
76+
- uses: actions/checkout@v4
77+
- uses: actions/setup-python@v5
78+
with:
79+
python-version: "3.12"
80+
- uses: actions/cache@v4
81+
with:
82+
path: ~/.cache/pip
83+
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }}
84+
restore-keys: |
85+
${{ runner.os }}-pip-
86+
- name: Install dependencies
87+
run: |
88+
pip install -U setuptools
89+
sudo apt-get update -qq
90+
sudo apt-get install -qq swig libxml2-dev libxmlsec1-dev
91+
make install-req
92+
make install-test
7493
- name: Run coveralls
7594
env:
7695
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
7796
run: |
7897
pip install coveralls
79-
coverage run setup.py test
80-
coverage report -m
81-
coveralls
98+
make coverage
99+
make coveralls

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ FLAKE8=flake8
44
PYTEST=pytest
55
COVERAGE=coverage
66
COVERAGE_CONFIG=tests/coverage.rc
7+
COVERALLS=coveralls
78
MAIN_SOURCE=src/onelogin/saml2
89
DEMOS=demo-django demo-flask demo-tornado demo_pyramid
910
TESTS=tests/src/OneLogin/saml2_tests
@@ -19,8 +20,14 @@ install-lint:
1920
$(PIP) install -e ".[lint]"
2021

2122
pytest:
22-
$(COVERAGE) run --source $(MAIN_SOURCE) --rcfile=$(COVERAGE_CONFIG) -m pytest
23-
$(COVERAGE) report -m --rcfile=$(COVERAGE_CONFIG)
23+
$(pytest)
24+
25+
coverage:
26+
$(COVERAGE) run -m $(PYTEST)
27+
$(COVERAGE) report -m
28+
29+
coveralls:
30+
$(COVERALLS)
2431

2532
black:
2633
$(BLACK) $(SOURCES)

README.md

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
![PyPI Downloads](https://img.shields.io/pypi/dm/python3-saml.svg?label=PyPI%20Downloads)
55
[![Coverage Status](https://coveralls.io/repos/github/SAML-Toolkits/python3-saml/badge.svg?branch=master)](https://coveralls.io/github/SAML-Toolkits/python3-saml?branch=master)
66
[![PyPi Version](https://img.shields.io/pypi/v/python3-saml.svg)](https://pypi.python.org/pypi/python3-saml)
7-
![Python versions](https://img.shields.io/pypi/pyversions/python3-saml.svg)
7+
![Python versions](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FSAML-Toolkits%2Fpython3-saml%2Fmaster%2Fpyproject.toml)
88

99
Add SAML support to your Python software using this library.
1010
Forget those complicated libraries and use the open source library provided by the SAML tool community.
@@ -13,8 +13,6 @@ This version supports Python3. Python 2 support was deprecated on Jan 1st, 2020:
1313

1414
#### Warning ####
1515

16-
Version 1.16.X is the latest version supporting Python2, consider its use deprecated. 1.17 won't be Python2 compatible.
17-
1816
Version 1.13.0 sets sha256 and rsa-sha256 as default algorithms
1917

2018
Version 1.8.0 sets strict mode active by default
@@ -90,13 +88,13 @@ Installation
9088

9189
### Dependencies ###
9290

93-
* python 3.5
91+
* python => 3.7
9492
* [xmlsec](https://pypi.python.org/pypi/xmlsec) Python bindings for the XML Security Library.
9593
* [lxml](https://pypi.python.org/pypi/lxml) Python bindings for the libxml2 and libxslt libraries.
9694
* [isodate](https://pypi.python.org/pypi/isodate) An ISO 8601 date/time/
9795
duration parser and formatter
9896

99-
Review the ``setup.py`` file to know the version of the library that ``python3-saml`` is using
97+
Review the ``pyproject.toml`` file to know the version of the library that ``python3-saml`` is using
10098

10199
### Code ###
102100

@@ -107,7 +105,7 @@ The toolkit is hosted on GitHub. You can download it from:
107105
* Latest release: https://github.com/saml-toolkits/python3-saml/releases/latest
108106
* Master repo: https://github.com/saml-toolkits/python3-saml/tree/master
109107

110-
Copy the core of the library ``(src/onelogin/saml2 folder)`` and merge the ``setup.py`` inside the Python application. (Each application has its structure so take your time to locate the Python SAML toolkit in the best place).
108+
Find the core of the library at ``src/onelogin/saml2`` folder.
111109

112110
#### Option 2. Download from pypi ####
113111

@@ -156,13 +154,13 @@ A replay attack is basically try to reuse an intercepted valid SAML Message in o
156154
SAML Messages have a limited timelife (NotBefore, NotOnOrAfter) that
157155
make harder this kind of attacks, but they are still possible.
158156

159-
In order to avoid them, the SP can keep a list of SAML Messages or Assertion IDs already validated and processed. Those values only need
157+
In order to avoid them, the SP can keep a list of SAML Messages or Assertion IDs alredy valdidated and processed. Those values only need
160158
to be stored the amount of time of the SAML Message life time, so
161159
we don't need to store all processed message/assertion Ids, but the most recent ones.
162160

163161
The OneLogin_Saml2_Auth class contains the [get_last_request_id](https://github.com/onelogin/python3-saml/blob/ab62b0d6f3e5ac2ae8e95ce3ed2f85389252a32d/src/onelogin/saml2/auth.py#L357), [get_last_message_id](https://github.com/onelogin/python3-saml/blob/ab62b0d6f3e5ac2ae8e95ce3ed2f85389252a32d/src/onelogin/saml2/auth.py#L364) and [get_last_assertion_id](https://github.com/onelogin/python3-saml/blob/ab62b0d6f3e5ac2ae8e95ce3ed2f85389252a32d/src/onelogin/saml2/auth.py#L371) methods to retrieve the IDs
164162

165-
Checking that the ID of the current Message/Assertion does not exists in the list of the ones already processed will prevent replay attacks.
163+
Checking that the ID of the current Message/Assertion does not exists in the lis of the ones already processed will prevent replay attacks.
166164

167165

168166
Getting Started
@@ -217,31 +215,32 @@ This folder contains a Pyramid project that will be used as demo to show how to
217215

218216
This folder contains a Tornado project that will be used as demo to show how to add SAML support to the Tornado Framework. ``views.py`` (with its ``settings.py``) is the main Flask file that has all the code, this file uses the templates stored at the ``templates`` folder. In the ``saml`` folder we found the ``certs`` folder to store the X.509 public and private key, and the SAML toolkit settings (``settings.json`` and ``advanced_settings.json``).
219217

218+
It requires python3.8 (it's using tornado 6.4.1)
220219

221-
#### setup.py ####
222-
223-
Setup script is the centre of all activity in building, distributing, and installing modules.
224-
Read more at https://pythonhosted.org/an_example_pypi_project/setuptools.html
225220

226221
#### tests ####
227222

228223
Contains the unit test of the toolkit.
229224

230225
In order to execute the test you only need to load the virtualenv with the toolkit installed on it properly:
231226
```
232-
pip install -e ".[test]"
227+
make install-test
233228
```
234229

235230
and execute:
236231
```
237-
python setup.py test
232+
make pytest
238233
```
239234
The previous line will run the tests for the whole toolkit. You can also run the tests for a specific module. To do so for the auth module you would have to execute this:
240235
```
241-
python setup.py test --test-suite tests.src.OneLogin.saml2_tests.auth_test.OneLogin_Saml2_Auth_Test
236+
pytest tests/src/OneLogin/saml2_tests/auth_test.py::OneLogin_Saml2_Auth_Test
237+
```
238+
239+
Or for an specific method:
240+
```
241+
pytest tests/src/OneLogin/saml2_tests/auth_test.py::OneLogin_Saml2_Auth_Test::testBuildRequestSignature
242242
```
243243

244-
With the ``--test-suite`` parameter you can specify the module to test. You'll find all the module available and their class names at ``tests/src/OneLogin/saml2_tests/``.
245244

246245
### How It Works ###
247246

@@ -298,9 +297,9 @@ This is the ``settings.json`` file:
298297
},
299298
// If you need to specify requested attributes, set a
300299
// attributeConsumingService. nameFormat, attributeValue and
301-
// friendlyName can be omitted
300+
// friendlyName can be ommited
302301
"attributeConsumingService": {
303-
// OPTIONAL: only specify if SP requires this.
302+
// OPTIONAL: only specifiy if SP requires this.
304303
// index is an integer which identifies the attributeConsumingService used
305304
// to the SP. SAML toolkit supports configuring only one attributeConsumingService
306305
// but in certain cases the SP requires a different value. Defaults to '1'.
@@ -367,7 +366,7 @@ This is the ``settings.json`` file:
367366
/*
368367
* Instead of using the whole X.509cert you can use a fingerprint in order to
369368
* validate a SAMLResponse (but you still need the X.509cert to validate LogoutRequest and LogoutResponse using the HTTP-Redirect binding).
370-
* But take in mind that the algorithm for the fingerprint should be as strong as the algorithm in a normal certificate signature
369+
* But take in mind that the algortithm for the fingerprint should be as strong as the algorithm in a normal certificate signature
371370
* (e.g. SHA256 or strong)
372371
*
373372
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
@@ -502,7 +501,7 @@ In addition to the required settings data (idp, sp), extra settings can be defin
502501
'allowRepeatAttributeName': false,
503502

504503
// If the toolkit receive a message signed with a
505-
// deprecated algorithm (defined at the constant class)
504+
// deprecated algoritm (defined at the constant class)
506505
// will raise an error and reject the message
507506
"rejectDeprecatedAlgorithm": true
508507
},
@@ -521,7 +520,7 @@ In addition to the required settings data (idp, sp), extra settings can be defin
521520
},
522521

523522
// Organization information template, the info in en_US lang is
524-
// recommended, add more if required.
523+
// recomended, add more if required.
525524
"organization": {
526525
"en-US": {
527526
"name": "sp_test",
@@ -649,7 +648,7 @@ def prepare_from_django_request(request):
649648
def prepare_from_flask_request(request):
650649
url_data = urlparse(request.url)
651650
return {
652-
'http_host': request.host,
651+
'http_host': request.netloc,
653652
'script_name': request.path,
654653
'get_data': request.args.copy(),
655654
'post_data': request.form.copy()
@@ -678,8 +677,7 @@ req = prepare_request_for_toolkit(request)
678677
auth = OneLogin_Saml2_Auth(req) # Constructor of the SP, loads settings.json
679678
# and advanced_settings.json
680679

681-
auth.login() # This method will build and return a AuthNRequest URL that can be
682-
# either redirected to, or printed out onto the screen as a hyperlink
680+
auth.login() # Method that builds and sends the AuthNRequest
683681
```
684682

685683
The ``AuthNRequest`` will be sent signed or unsigned based on the security info of the ``advanced_settings.json`` file (i.e. ``authnRequestsSigned``).
@@ -692,7 +690,7 @@ We can set a ``return_to`` url parameter to the login function and that will be
692690
target_url = 'https://example.com'
693691
auth.login(return_to=target_url)
694692
```
695-
The login method can receive 3 more optional parameters:
693+
The login method can recieve 3 more optional parameters:
696694

697695
* ``force_authn`` When ``true``, the ``AuthNReuqest`` will set the ``ForceAuthn='true'``
698696
* ``is_passive`` When true, the ``AuthNReuqest`` will set the ``Ispassive='true'``
@@ -771,7 +769,7 @@ Notice that we saved the user data in the session before the redirection to have
771769
In order to retrieve attributes we use:
772770

773771
```python
774-
attributes = auth.get_attributes()
772+
attributes = auth.get_attributes();
775773
```
776774

777775
With this method we get a dict with all the user data provided by the IdP in the assertion of the SAML response.
@@ -787,12 +785,12 @@ If we execute print attributes we could get:
787785
}
788786
```
789787

790-
Each attribute name can be used as a key to obtain the value. Every attribute is a list of values. A single-valued attribute is a list of a single element.
788+
Each attribute name can be used as a key to obtain the value. Every attribute is a list of values. A single-valued attribute is a listy of a single element.
791789

792790
The following code is equivalent:
793791

794792
```python
795-
attributes = auth.get_attributes()
793+
attributes = auth.get_attributes();
796794
print(attributes['cn'])
797795

798796
print(auth.get_attribute('cn'))
@@ -815,7 +813,7 @@ if len(errors) == 0:
815813
# the value of the url is a trusted URL.
816814
return redirect(url)
817815
else:
818-
print("Successfully Logged out")
816+
print("Sucessfully Logged out")
819817
else:
820818
print("Error when processing SLO: %s %s" % (', '.join(errors), auth.get_last_error_reason()))
821819
```
@@ -957,7 +955,7 @@ elif 'sls' in request.args: # Single
957955
# the value of the url is a trusted URL.
958956
return redirect(url)
959957
else:
960-
msg = "Successfully logged out"
958+
msg = "Sucessfully logged out"
961959

962960
if len(errors) == 0:
963961
print(msg)
@@ -1073,7 +1071,7 @@ SAML 2 Logout Request class
10731071
* ***get_nameid*** Gets the NameID of the Logout Request Message (returns a string).
10741072
* ***get_issuer*** Gets the Issuer of the Logout Request Message.
10751073
* ***get_session_indexes*** Gets the ``SessionIndexes`` from the Logout Request.
1076-
* ***is_valid*** Checks if the Logout Request received is valid.
1074+
* ***is_valid*** Checks if the Logout Request recieved is valid.
10771075
* ***get_error*** After execute a validation process, if fails this method returns the cause.
10781076
* ***get_xml*** Returns the XML that will be sent as part of the request or that was received at the SP
10791077

@@ -1156,7 +1154,7 @@ Auxiliary class that contains several methods
11561154
* ***get_expire_time*** Compares 2 dates and returns the earliest.
11571155
* ***delete_local_session*** Deletes the local session.
11581156
* ***calculate_X.509_fingerprint*** Calculates the fingerprint of a X.509 cert.
1159-
* ***format_finger_print*** Formats a fingerprint.
1157+
* ***format_finger_print*** Formates a fingerprint.
11601158
* ***generate_name_id*** Generates a nameID.
11611159
* ***get_status*** Gets Status from a Response.
11621160
* ***decrypt_element*** Decrypts an encrypted element.
@@ -1206,22 +1204,14 @@ let's see how fast is it to deploy them.
12061204
The use of a [virtualenv](http://virtualenv.readthedocs.org/en/latest/) is
12071205
highly recommended.
12081206

1209-
Virtualenv helps isolating the python environment used to run the toolkit. You
1207+
Virtualenv helps isolating the python enviroment used to run the toolkit. You
12101208
can find more details and an installation guide in the
12111209
[official documentation](http://virtualenv.readthedocs.org/en/latest/).
12121210

12131211
Once you have your virtualenv ready and loaded, then you can install the
1214-
toolkit on it in development mode executing this:
1212+
toolkit executing this:
12151213
```
1216-
python setup.py develop
1217-
```
1218-
1219-
Using this method of deployment the toolkit files will be linked instead of
1220-
copied, so if you make changes on them you won't need to reinstall the toolkit.
1221-
1222-
If you want install it in a normal mode, execute:
1223-
```
1224-
python setup.py install
1214+
make install-req
12251215
```
12261216

12271217
### Demo Flask ###
@@ -1510,7 +1500,7 @@ Once the SP is configured, the metadata of the SP is published at the ``/metadat
15101500

15111501
4. We are logged in the app and the user attributes are showed. At this point, we can test the single log out functionality.
15121502

1513-
The single log out functionality could be tested by 2 ways.
1503+
The single log out funcionality could be tested by 2 ways.
15141504

15151505
5.1 SLO Initiated by SP. Click on the "logout" link at the SP, after that a Logout Request is sent to the IdP, the session at the IdP is closed and replies through the client to the SP with a Logout Response (sent to the Single Logout Service endpoint). The SLS endpoint /?sls of the SP process the Logout Response and if is valid, close the user session of the local app. Notice that the SLO Workflow starts and ends at the SP.
15161506

pyproject.toml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Changelog = "https://github.com/SAML-Toolkits/python3-saml/blob/master/changelog
4646

4747
[project.optional-dependencies]
4848
test = [
49-
"coverage>=4.5.2",
49+
"coverage[toml]>=4.5.2",
5050
"pytest>=4.6",
5151
]
5252
lint = [
@@ -93,3 +93,30 @@ atomic = true
9393
ignore_comments = true
9494
skip_gitignore = true
9595
src_paths = ['src']
96+
97+
[tool.coverage.run]
98+
branch = true
99+
100+
[tool.coverage.paths]
101+
source = [
102+
"src/onelogin/saml2"
103+
]
104+
105+
[tool.coverage.report]
106+
# Regexes for lines to exclude from consideration
107+
exclude_lines = [
108+
"pragma: no cover",
109+
"def __repr__",
110+
"if self.debug",
111+
"if debug",
112+
"raise AssertionError",
113+
"raise NotImplementedError",
114+
"if 0:",
115+
"if __name__ == .__main__.:"
116+
]
117+
show_missing = true
118+
ignore_errors = true
119+
120+
121+
[tool.coverage.html]
122+
directory = "coverage_html_report"

0 commit comments

Comments
 (0)