Skip to content

Commit

Permalink
Merge pull request #216 from gregorywong/configure-encryption-keypairs
Browse files Browse the repository at this point in the history
Add ENCRYPTION_KEYPAIRS to settings
  • Loading branch information
mostafa authored Nov 9, 2023
2 parents 08e0753 + 8cf2f6e commit 7a5723f
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ an issue.
- [Paolo Romolini](https://github.com/paoloromolini)
- [Uraiz Ali](https://github.com/UraizAli)
- [Santiago Gandolfo](https://github.com/santigandolfo)
- [Greg Wong](https://github.com/gregorywong)
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ python setup.py install
'METADATA_LOCAL_FILE_PATH': '[The metadata configuration file path]',
'KEY_FILE': '[The key file path]',
'CERT_FILE': '[The certificate file path]',

# If both `KEY_FILE` and `CERT_FILE` are provided, `ENCRYPTION_KEYPAIRS` will be added automatically. There is no need to provide it unless you wish to override the default value.
'ENCRYPTION_KEYPAIRS': [
{
"key_file": '[The key file path]',
"cert_file": '[The certificate file path]',
}
],

'DEBUG': False, # Send debug information to a log file
# Optional logging configuration.
Expand Down Expand Up @@ -221,6 +229,7 @@ Some of the following settings are related to how this module operates. The rest
| **METADATA\_LOCAL\_FILE\_PATH** | SAML2 metadata configuration file path | `str` | `None` | `/path/to/the/metadata.xml` |
| **KEY_FILE** | SAML2 private key file path | `str` | `None` | `/path/to/the/key.pem` |
| **CERT_FILE** | SAML2 public certificate file path | `str` | `None` | `/path/to/the/cert.pem` |
| **ENCRYPTION_KEYPAIRS** | Required for handling encrypted assertions. Will be automatically set if both `KEY_FILE` and `CERT_FILE` are set. | `list` | Not set. | `[ { 'key_file': '[The key file path]', 'cert_file': '[The certificate file path]' } ]` |
| **DEBUG** | Send debug information to a log file | `bool` | `False` | |
| **LOGGING** | Logging configuration dictionary | `dict` | Not set. | |
| **DEFAULT\_NEXT\_URL** | Custom target redirect URL after the user get logged in. Default to /admin if not set. This setting will be overwritten if you have parameter `?next=` specificed in the login URL. | `str` | `admin:index` | `https://app.example.com/account/login` |
Expand Down
11 changes: 11 additions & 0 deletions django_saml2_auth/saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ def get_saml_client(domain: str,
if cert_file:
saml_settings['cert_file'] = cert_file

encryption_keypairs = saml2_auth_settings.get("ENCRYPTION_KEYPAIRS")
if encryption_keypairs:
saml_settings["encryption_keypairs"] = encryption_keypairs
elif key_file and cert_file:
saml_settings["encryption_keypairs"] = [
{
"key_file": key_file,
"cert_file": cert_file,
}
]

try:
sp_config = Saml2Config()
sp_config.load(saml_settings)
Expand Down
32 changes: 32 additions & 0 deletions django_saml2_auth/tests/dummy_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFbTCCA1WgAwIBAgIUbcK0caWcYgQq/PgM/HpXsfGc7xYwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzExMDkxMzI4MTNaGA8zMDIz
MDMxMjEzMjgxM1owRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAO0hfWkIoYvRBSvSQJazwp2NadhPCJEPliY0ZgKu
dQibzV1oav6DdxZWxs3ys3HKpUnfRTsMXMXzYFJv3M17X8kAsEAfjLKIC3POV/Og
73fW7T/2uJubIE0bI6whe44/4vV6JVKuZUf7N/eD2k0x9t7O+ljITdnFyNbwLJ24
ZoVSB9VhhAN+gVlR+D9yr5NwcWSVSnn9wxKh5cHpNu85g/dpQ7sA8QNSQGgJ763V
WiITxGQ1S13+RKRDdtzaahjkEezh0nCeVBypQ2u4zMj3jEVgnSqcxIaGoSyRlsr4
kyoeFVHFJq3vVOMHa21luPaDsskssBMu13udVUmsaiEQc4Z7ItlHeXgQc0cy6N94
uZw+qw+CMRWvZGsyKWuvNfQu/ZAME8MrhveLot9pcf2PFXLG+kitE741m0A1JP3v
xRaGRHU4L0fkBalTVUncLo6hBAvgH+uN+Dl2p7KnIanHgMXQXv/UdRyzuJ5E7q+B
yHnwXwNRcCOWrOFe07yQetc5f+Z8+p2X6lkjgMD+d6IrKIsYCMU1ZMHi+oWkSbei
oDx/kk7xPnNLM1hbmQPNrbt19M49rGg6CN8Z6vjVavdJ5Rpj0Tq13JWA52eJu/NT
wpxYaWeh7WkzhHAS9bgyOX/ot9iJSPicLdrl5qMkwmPqi8UyXrVLA2LCG0SH2Oz5
YT8TAgMBAAGjUzBRMB0GA1UdDgQWBBQzOZToKlK9pjiv6JG78CLq/+GJuTAfBgNV
HSMEGDAWgBQzOZToKlK9pjiv6JG78CLq/+GJuTAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4ICAQAygpKdXrSPYdTSuLfDXHAo+CPSynNFBUUbbQta23r+
ucJVc79fgIT+lZbXm35ddQ2uhCuZuQy+K2JSBv7Zcr7xii89YyMkHGKINvJVhjgG
aZQARrdWcd1c8DnSfC144TITDFC2uqX0L2f6m/V//J8y7Dwetqh13nzKXE8xmWc5
fmwiULXQrJ1cqn1cEB/1y1rQOT+bAbsJ6gzpSyxf8gRklKYQmkPvATvOOg+GK1d3
GeQLhw6KcDql1d2VnHb7vQRow7Uidtxi7lKcj6k4R+7hg8BBNtrsHH0GsGCfun8O
+VxtS+YT6xM7LYwuyTEtcHz1pyqyIpFBYsyNm8WH/F9i1Is1Jj5om5Zx6inL31YV
RRKujvvRjRe3g3uZY15p5/HHNK5riPkVZRPT9qVPDxnScjgaI5EhLw173sEt6ktG
7zrlC7yZFpNMkGSs5SkT8lUQTmGr2gD5b02N4UNdhCF+WZOmMLjQAvinMGfdjqek
3e6llupoyNOzG+4LvI/HzVHqg6WjVO5QSP/4gt21SSgUo7mHa0GQMymVmkCrWEMY
+PhpuNE5fv9CGyi22f+LZ988jGhpHApzrdGBY/M3h7k4mD7Ap/a8J3inJPLKOgIG
z1VT29ZzR8R7NpkoJV1zX9/wFUf5lZMi3UJPuj/LPOf0jcoZbV8B/E7ydf6akm69
Xg==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions django_saml2_auth/tests/dummy_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
K1a3lfdFi6tz5qORy3yofYqvqi6wEko=
-----END PRIVATE KEY-----
57 changes: 56 additions & 1 deletion django_saml2_auth/tests/test_saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Tests for saml.py
"""

from typing import Optional, List, Mapping
from typing import Dict, Optional, List, Mapping, Union

import pytest
import responses
Expand Down Expand Up @@ -349,6 +349,61 @@ def test_get_saml_client_failure_with_invalid_file(settings: SettingsWrapper):
assert isinstance(exc_info.value.extra["exc"], FileNotFoundError)


@pytest.mark.parametrize(
"supplied_config_values,expected_encryption_keypairs",
[
(
{
"KEY_FILE": "django_saml2_auth/tests/dummy_key.pem",
},
None,
),
(
{
"CERT_FILE": "django_saml2_auth/tests/dummy_cert.pem",
},
None,
),
(
{
"KEY_FILE": "django_saml2_auth/tests/dummy_key.pem",
"CERT_FILE": "django_saml2_auth/tests/dummy_cert.pem",
},
[
{
"key_file": "django_saml2_auth/tests/dummy_key.pem",
"cert_file": "django_saml2_auth/tests/dummy_cert.pem",
}
],
),
],
)
def test_get_saml_client_success_with_key_and_cert_files(
settings: SettingsWrapper,
supplied_config_values: Dict[str, str],
expected_encryption_keypairs: Union[List, None],
):
"""Test get_saml_client function to verify that it is correctly instantiated with encryption_keypairs
if both key_file and cert_file are provided (even if encryption_keypairs isn't).
Args:
settings (SettingsWrapper): Fixture for django settings
"""

settings.SAML2_AUTH["METADATA_LOCAL_FILE_PATH"] = "django_saml2_auth/tests/metadata.xml"

for key, value in supplied_config_values.items():
settings.SAML2_AUTH[key] = value

result = get_saml_client("example.com", acs)
assert isinstance(result, Saml2Client)
assert result.config.encryption_keypairs == expected_encryption_keypairs

for key, value in supplied_config_values.items():
# ensure that the added settings do not get carried over to other tests
del settings.SAML2_AUTH[key]


@responses.activate
def test_decode_saml_response_success(
settings: SettingsWrapper, monkeypatch: "MonkeyPatch"): # type: ignore
Expand Down

0 comments on commit 7a5723f

Please sign in to comment.