Compare commits
13 Commits
tmp-prod-debug
...
v1.0.6
| Author | SHA1 | Date | |
|---|---|---|---|
| 5be05fe43e | |||
| f90df5c2c6 | |||
| 6bbcd95069 | |||
| b839c32b50 | |||
| 9b062aa27d | |||
| 4a2ece217b | |||
| a7577ff85e | |||
| 4e81e1e750 | |||
| c27ebfe6ae | |||
| d84f2b32d5 | |||
| 9cb67bfb87 | |||
| ba1774bdbf | |||
| cb8ff5d878 |
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0),
|
||||
and this project adheres to
|
||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.0.6] - 2025-03-11
|
||||
- upgrade to SATOSA 8.5.1
|
||||
- allow faculty, staff, employee, researcher, teacher affiliations
|
||||
|
||||
## [1.0.5] - 2025-03-06
|
||||
- add allowlist for URL paths to nginx ingress
|
||||
- allow customizing log levels per logger
|
||||
|
||||
## [1.0.4] - 2024-09-11
|
||||
- serve static files
|
||||
|
||||
|
||||
@@ -63,6 +63,13 @@ number and date.
|
||||
3. Commit and push to `main`.
|
||||
4. Update the `production` tag and push it.
|
||||
|
||||
## Environment variables
|
||||
|
||||
| variable | usage |
|
||||
| --- | --- |
|
||||
| `LOG_LEVEL` | Sets the log level for the root logger, i.e. the default. Defaults to `INFO`. |
|
||||
| `LOG_LEVELS` | A JSON object that can be used to set log levels for specific loggers, e.g. `{"satosa.backends.saml2": "DEBUG"}`. Defaults to `{}`. |
|
||||
|
||||
## Contributing
|
||||
|
||||
This project is intended to be community-driven, so please, do not hesitate to
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ services:
|
||||
BASE_URL: https://satosa.traefik.me
|
||||
GUNICORN_CMD_ARGS: --workers=2
|
||||
TEST_E2E: 1
|
||||
#TEST_E2E_AC: 1
|
||||
#TEST_E2E_PC: 1
|
||||
OIDC_DB_URI: redis://redis/0
|
||||
CLIENT_DB_JSON: |
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
@@ -29,6 +30,8 @@ class RequestJSONFormatter(json_log_formatter.JSONFormatter):
|
||||
url += f"?{record.args['q']}"
|
||||
|
||||
return {
|
||||
"logger": record.name,
|
||||
"level": record.levelname,
|
||||
"remote_ip": record.args["h"],
|
||||
"method": record.args["m"],
|
||||
"path": url,
|
||||
@@ -37,7 +40,7 @@ class RequestJSONFormatter(json_log_formatter.JSONFormatter):
|
||||
"user_agent": record.args["a"],
|
||||
"referer": record.args["f"],
|
||||
"duration_in_ms": record.args["M"],
|
||||
"poppid": record.process,
|
||||
"pid": record.process,
|
||||
}
|
||||
|
||||
|
||||
@@ -55,11 +58,23 @@ class DefaultJSONFormatter(json_log_formatter.JSONFormatter):
|
||||
payload: dict[str, str | int | float] = super().json_record(
|
||||
message, extra, record
|
||||
)
|
||||
payload["logger"] = record.name
|
||||
payload["level"] = record.levelname
|
||||
payload["pid"] = record.process
|
||||
return payload
|
||||
|
||||
|
||||
class NoPingFilter(logging.Filter):
|
||||
"""
|
||||
Filters out /ping requests from the access log.
|
||||
"""
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
return not( record.args.get("m", "") == "GET"
|
||||
and record.args.get("U", "") == "/ping"
|
||||
and str(record.args.get("s", "")) == "200" )
|
||||
|
||||
|
||||
bind = ["0.0.0.0:8000"]
|
||||
name = "satosa"
|
||||
python_path = "/app"
|
||||
@@ -76,6 +91,9 @@ accesslog = "-"
|
||||
errorlog = "-"
|
||||
loglevel = os.environ.get("LOG_LEVEL", "INFO")
|
||||
|
||||
loglevels_json = os.environ.get("LOG_LEVELS", "{}")
|
||||
loglevels = json.loads(loglevels_json)
|
||||
|
||||
logconfig_dict = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": True,
|
||||
@@ -95,7 +113,24 @@ logconfig_dict = {
|
||||
"handlers": ["json_request"],
|
||||
"propagate": False,
|
||||
"qualname": "gunicorn.access",
|
||||
"filters": [NoPingFilter()],
|
||||
},
|
||||
"satosa.base": {
|
||||
"level": "INFO",
|
||||
},
|
||||
"satosa.state": {
|
||||
"level": "INFO",
|
||||
},
|
||||
"satosa.proxy_server": {
|
||||
"level": "INFO",
|
||||
},
|
||||
"satosa.routing": {
|
||||
"level": "INFO",
|
||||
},
|
||||
"satosa.frontends.ping": {
|
||||
"level": "INFO",
|
||||
},
|
||||
**{k: {"level": v.upper()} for k, v in loglevels.items()},
|
||||
},
|
||||
"formatters": {
|
||||
"json_request": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
image:
|
||||
repository: lasuite/oidc2fer
|
||||
pullPolicy: Always
|
||||
tag: "v1.0.4"
|
||||
tag: "v1.0.5"
|
||||
|
||||
satosa:
|
||||
replicas: 2
|
||||
@@ -9,7 +9,8 @@ satosa:
|
||||
BASE_URL: https://renater.agentconnect.gouv.fr
|
||||
GUNICORN_CMD_ARGS: --workers=3
|
||||
|
||||
LOG_LEVEL: info
|
||||
LOG_LEVEL: INFO
|
||||
LOG_LEVELS: '{ "satosa.backends.saml2": "DEBUG" }'
|
||||
|
||||
SAML2_DISCOVERY_URL: https://discovery.renater.fr/agentconnect/
|
||||
SAML2_METADATA_URL: https://pub.federation.renater.fr/metadata/renater/main/main-idps-renater-metadata.xml
|
||||
|
||||
@@ -9,7 +9,8 @@ satosa:
|
||||
BASE_URL: https://oidc2fer-staging.beta.numerique.gouv.fr
|
||||
GUNICORN_CMD_ARGS: --workers=3
|
||||
|
||||
LOG_LEVEL: debug
|
||||
LOG_LEVEL: DEBUG
|
||||
LOG_LEVELS: '{ "satosa.backends.saml2": "DEBUG" }'
|
||||
|
||||
SAML2_DISCOVERY_URL: https://discovery.renater.fr/test/
|
||||
SAML2_METADATA_URL: https://pub.federation.renater.fr/metadata/test/preview/preview-idps-test-metadata.xml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "oidc2fer.fullname" . -}}
|
||||
{{- $port := .Values.satosa.service.port -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
@@ -33,13 +34,15 @@ spec:
|
||||
- host: {{ .Values.ingress.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
{{- range .Values.ingress.paths }}
|
||||
- path: {{ .path | quote }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "oidc2fer.satosa.fullname" . }}
|
||||
name: {{ $fullName }}-satosa
|
||||
port:
|
||||
number: {{ .Values.satosa.service.port }}
|
||||
number: {{ $port }}
|
||||
{{- end }}
|
||||
{{- with .Values.ingress.customBackends }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
|
||||
@@ -33,7 +33,9 @@ ingress:
|
||||
enabled: false
|
||||
className: null
|
||||
host: oidc2fer.example.com
|
||||
path: /
|
||||
paths:
|
||||
- path: '/$|^/\.well-known/openid-configuration$|^/images/|^/Saml2/|^/OIDC/|^/ping$'
|
||||
pathType: ImplementationSpecific # enables regex matching
|
||||
## @param ingress.hosts Additional host to configure for the Ingress
|
||||
hosts: []
|
||||
# - chart-example.local
|
||||
@@ -48,6 +50,9 @@ ingress:
|
||||
## @param ingress.customBackends Add custom backends to ingress
|
||||
customBackends: []
|
||||
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
|
||||
## @section satosa
|
||||
|
||||
satosa:
|
||||
|
||||
@@ -3,11 +3,11 @@ name: Saml2
|
||||
config:
|
||||
disco_srv: !ENV SAML2_DISCOVERY_URL
|
||||
entityid_endpoint: true
|
||||
mirror_force_authn: 'no'
|
||||
memorize_idp: 'no'
|
||||
use_memorized_idp_when_force_authn: 'no'
|
||||
send_requester_id: 'no'
|
||||
enable_metadata_reload: 'no'
|
||||
mirror_force_authn: false
|
||||
memorize_idp: false
|
||||
use_memorized_idp_when_force_authn: false
|
||||
send_requester_id: false
|
||||
enable_metadata_reload: false
|
||||
acs_selection_strategy: prefer_matching_host
|
||||
sp_config:
|
||||
name: Passerelle OIDC vers FER
|
||||
|
||||
@@ -13,4 +13,8 @@ config:
|
||||
# later in the PrimaryIdentifier processor.
|
||||
- ".+"
|
||||
eduPersonAffiliation:
|
||||
- "^faculty$"
|
||||
- "^staff$"
|
||||
- "^employee$"
|
||||
- "^researcher$"
|
||||
- "^teacher$"
|
||||
|
||||
@@ -23,7 +23,7 @@ license = { file = "LICENSE" }
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"SATOSA==8.4.0",
|
||||
"SATOSA==8.5.1",
|
||||
"gunicorn==22.0.0",
|
||||
"redis==5.0.4",
|
||||
"JSON-log-formatter==1.0",
|
||||
|
||||
@@ -75,26 +75,26 @@ def test_oidc_to_renater_student_not_allowed(page: Page):
|
||||
expect(page.locator("pre")).to_contain_text('"error":"access_denied"')
|
||||
|
||||
|
||||
def agent_connect_login(page: Page, email):
|
||||
def pro_connect_login(page: Page, email):
|
||||
page.goto("https://fsa1v2.integ01.dev-agentconnect.fr/")
|
||||
page.get_by_label("Connexion à AgentConnect").click()
|
||||
page.get_by_role("button", name="S’identifier avec ProConnect").click()
|
||||
page.get_by_label("Email professionnel").fill(email)
|
||||
page.get_by_test_id("interaction-connection-button").click()
|
||||
|
||||
|
||||
def agent_connect_to_renater(
|
||||
def pro_connect_to_renater(
|
||||
page: Page,
|
||||
login="enseignant1",
|
||||
expected_email="georges.grospieds@formation.renater.fr",
|
||||
expected_given_name="Georges",
|
||||
expected_usual_name="Grospieds",
|
||||
):
|
||||
agent_connect_login(page, email=expected_email)
|
||||
pro_connect_login(page, email=expected_email)
|
||||
renater_wayf(page)
|
||||
renater_test_idp(page, login=login)
|
||||
|
||||
expect(page.locator("body")).to_contain_text(expected_email)
|
||||
text = page.inner_text("#json")
|
||||
text = page.inner_text("#userinfo")
|
||||
result = json.loads(text)
|
||||
assert {
|
||||
"uid": f"{login}@test-renater.fr",
|
||||
@@ -106,22 +106,22 @@ def agent_connect_to_renater(
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
"TEST_E2E_AC" not in os.environ, reason="Depends on staging deployment"
|
||||
"TEST_E2E_PC" not in os.environ, reason="Depends on staging deployment"
|
||||
)
|
||||
def test_agent_connect_to_renater_keeps_sub(browser: Browser):
|
||||
def test_pro_connect_to_renater_keeps_sub(browser: Browser):
|
||||
with browser.new_context().new_page() as page:
|
||||
result1 = agent_connect_to_renater(page)
|
||||
result1 = pro_connect_to_renater(page)
|
||||
with browser.new_context().new_page() as page:
|
||||
result2 = agent_connect_to_renater(page)
|
||||
result2 = pro_connect_to_renater(page)
|
||||
|
||||
assert result1["sub"] == result2["sub"]
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
"TEST_E2E_AC" not in os.environ, reason="Depends on staging deployment"
|
||||
"TEST_E2E_PC" not in os.environ, reason="Depends on staging deployment"
|
||||
)
|
||||
def test_agent_connect_to_renater_student_not_allowed(page: Page):
|
||||
agent_connect_login(page, email="jean.dupont@formation.renater.fr")
|
||||
def test_pro_connect_to_renater_student_not_allowed(page: Page):
|
||||
pro_connect_login(page, email="jean.dupont@formation.renater.fr")
|
||||
renater_wayf(page)
|
||||
renater_test_idp(page, login="etudiant1")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user