Compare commits

...

39 Commits

Author SHA1 Message Date
dependabot[bot] d606ac7439 Bump flask from 3.0.3 to 3.1.3 in /docker/oidc-test-client
Bumps [flask](https://github.com/pallets/flask) from 3.0.3 to 3.1.3.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/3.0.3...3.1.3)

---
updated-dependencies:
- dependency-name: flask
  dependency-version: 3.1.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-21 00:08:14 +00:00
Jonathan Perret 208c4467df 🔐(secrets) update secrets to current main 2026-02-11 10:35:53 +01:00
Jonathan Perret 0e82e8b771 🔧(siret) fix stray space in SIRET map
This was preventing EHESP users from connecting since
their IdP's entity ID was not matched.
2025-12-03 23:14:01 +01:00
Jonathan Perret 798afdf2a9 Deploy release v1.0.11 to production 2025-11-24 18:06:22 +01:00
Jonathan Perret 7cf9fda7d8 v1.0.11 release 2025-11-24 18:05:40 +01:00
Jonathan Perret 1816d2a8de Merge pull request #36 from proconnect-gouv/update-setuptools
⬆️(setuptools) remove setuptools from production Docker image
2025-11-24 18:04:18 +01:00
Jonathan Perret c89b9b7ada ⬆️(setuptools) remove setuptools from production Docker image
To fix a CVE reported by Cyberwatch. These tools are not required at
runtime so there's no need to keep them around.
2025-11-24 17:51:02 +01:00
Jonathan Perret c0d252f390 🔧(siret) fix entity ID for two entities
As provided by RENATER.
2025-11-24 11:47:36 +01:00
Jonathan Perret fa39964a64 🔧(siret) add new entities to SIRET map
As provided by RENATER.
2025-11-24 09:42:00 +01:00
Jonathan Perret 44b9879a3b Deploy release v1.0.10 to production 2025-11-21 11:10:07 +01:00
Jonathan Perret 7c3a0fccc9 v1.0.10 release 2025-11-21 11:07:03 +01:00
Jonathan Perret c224e31a66 Merge pull request #35 from rouja/helm-refacto
⬆️(helmfile) rename helmfile to be compatible with new helmfile plugin
2025-11-20 16:09:14 +01:00
Jacques ROUSSEL 4892192b85 ⬆️(helmfile) rename helmfile.yaml to helmfile.yaml.gotmpl
For compatibility with helmfile v1.x.
2025-11-20 16:02:50 +01:00
Jonathan Perret 79aee346a2 🔧(siret) update SIRET map to replace closed entities
These new SIRET numbers were found using
https://annuaire-entreprises.data.gouv.fr/
2025-10-23 10:21:57 +02:00
Jonathan Perret 4e84ec0f2b Deploy release v1.0.9 to production 2025-10-03 13:22:03 +02:00
Jonathan Perret 3401da37ff v1.0.9 release 2025-10-03 13:19:29 +02:00
Jonathan Perret 1124893498 Merge pull request #34 from proconnect-gouv/add-siret-mapping 2025-10-03 13:16:09 +02:00
Jonathan Perret 1557f7ba22 🔧(siret) add initial SIRET map to production environment
This mapping was provided by RENATER on 2025-09-19.
2025-10-03 13:10:40 +02:00
Jonathan Perret 6c344fae05 (siret) introduce SIRET mapping from EntityID
The proxy now uses a SIRET_MAP environment variable that must contain
a JSON mapping of SAML entity IDs to SIRET numbers.
These SIRET numbers will be returned to OIDC clients that request the
`siret` scope, in the `siret` claim.
2025-10-02 19:50:40 +02:00
Jonathan Perret cb8352787d Merge pull request #32 from proconnect-gouv/fix-acr-claim 2025-09-17 17:31:38 +02:00
Jonathan Perret 9a33149e9e (e2e) adapt to ProConnect error page wording change
The generic message was replaced by the error code
and description from the IdP.
2025-09-17 16:06:37 +02:00
Jonathan Perret a56ce17b34 ⬆️(oidc-test-client) upgrade oic to 1.7.0
This mainly avoids a conflict with the oidc2fer requirements
when installing both in a local virtualenv for IDE support.
2025-09-17 16:06:36 +02:00
Jonathan Perret a8bf8f61b4 🐛(oidc) stop forcing id_token 'acr' claim
There is a regression in pyop 3.4.2 which causes the configured
extra_id_token_claims to be ignored. Fortunately, ProConnect Core
now requests the required `acr` claim explicitly, so it is no longer
necessary to force it.

The OIDC test client was updated to request the `acr` claim in the
same way that ProConnect does it.
2025-09-17 16:06:35 +02:00
Jonathan Perret 7b1571b0ed (e2e) fix e2e test to more reliably select test IdP
The list of IdPs on the RENATER test federation seems to have
grown enough that the test IdP we want is no longer displayed
by default, so we have to search for it.
2025-09-15 12:15:05 +02:00
Jonathan Perret 3ecbf1a5a0 Fix docker registry for production 2025-09-10 18:23:52 +02:00
Jonathan Perret 445485ecc5 Deploy release 1.0.8 to production 2025-09-10 18:19:49 +02:00
Jonathan Perret 1bceed1373 v1.0.8 release 2025-09-10 18:08:39 +02:00
Jonathan Perret 850636970c 🚀(staging) add missing ghcr.io prefix to image name
Without a registry name, Docker Hub is still the default.
2025-09-10 18:06:02 +02:00
Jonathan Perret 9a1803b3e6 Merge pull request #31 from proconnect-gouv/move-to-proconnect 2025-09-10 17:56:47 +02:00
Jonathan Perret c51c95e007 💚(ci) fix CI jobs post org move
- use the GitHub app on numerique-gouv only to access the secrets repo
- inline helmfile-lint action (it only works on repos in numerique-gouv
  currently)
- replace deprecated `git whatchanged` with `git log`
- publish to ghcr.io instead of Docker Hub
- rename workflows to match other proconnect-gouv repos
2025-09-10 17:40:32 +02:00
Jonathan Perret 2687868465 📝(repo) update remaining references to numerique-gouv
Also updating CHANGELOG.
2025-09-10 17:40:30 +02:00
Jonathan Perret 38707412b3 🔧(secrets) change secrets submodule path
Since the oidcfer repo moved to a different organization the relative
path to the secrets submodule needs to change.
2025-09-10 15:24:56 +02:00
Jonathan Perret 8cd89621b2 Deploy release v1.0.7 to production. 2025-05-07 17:08:42 +02:00
Jonathan Perret 425365d22a v1.0.7 release 2025-05-07 17:07:48 +02:00
Jonathan Perret 63806bde22 Merge pull request #30 from numerique-gouv/fix-cve
Remove unused APT dependencies that trigger a CVE warning
2025-05-07 13:46:13 +02:00
Jonathan Perret 96299e1386 ⬆️ (deps) Bump gunicorn to 23.0.0 2025-05-07 13:43:45 +02:00
Jonathan Perret bf015c9238 🔒️(docker) remove unused APT dependencies that trigger a CVE warning
Specifically CVE-2023-45853 was flagged in our Docker image, but
it is in libfreetype6 which we don't use, and is only pulled in
because of a recommended depdency of `gcc` — which we don't need
in any case.
2025-05-07 13:43:45 +02:00
Jacques ROUSSEL 589d447f19 🐛(ci) fix helmfile linter
Latest helmfile version breaks lots of thing.
2025-03-28 14:46:38 +01:00
Jacques ROUSSEL ddc09cca50 🐛(ci) use github action for argocd webhook notification
In order to refactor this notification between alls projetcs, we
chooseto use a custom github action
2025-03-28 14:46:38 +01:00
26 changed files with 363 additions and 175 deletions
+2 -2
View File
@@ -9,9 +9,9 @@ We primarily use GitHub as an issue tracker. If however you're encountering an i
---
Please make sure you have read our [main Readme](https://github.com/numerique-gouv/oidc2fer).
Please make sure you have read our [main Readme](https://github.com/proconnect-gouv/oidc2fer).
Also make sure it was not already answered in [an open or close issue](https://github.com/numerique-gouv/oidc2fer/issues).
Also make sure it was not already answered in [an open or close issue](https://github.com/proconnect-gouv/oidc2fer/issues).
If your question was not covered, and you feel like it should be, fire away! We'd love to improve our docs! 👌
+67
View File
@@ -0,0 +1,67 @@
name: 🐳 Build docker images
on:
push:
branches:
- 'main'
tags:
- 'v*'
pull_request:
branches:
- 'main'
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=sha,prefix=sha-
# set latest tag for default branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Login to Github Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
target: production
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
notify-argocd:
runs-on: ubuntu-latest
if: |
github.event_name != 'pull_request'
needs:
- build-and-push
steps:
- uses: numerique-gouv/action-argocd-webhook-notification@main
id: notify
with:
deployment_repo_path: "${{ github.repository }}"
argocd_webhook_secret: "${{ secrets.ARGOCD_PREPROD_WEBHOOK_SECRET }}"
argocd_url: "${{ vars.ARGOCD_PREPROD_WEBHOOK_URL }}"
@@ -1,4 +1,4 @@
name: OIDC2FER Workflow
name: 💚 CI Tests
on:
push:
@@ -23,7 +23,7 @@ jobs:
run: git log
- name: Enforce absence of print statements in code
run: |
! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude)**/oidc2fer.yml' | grep "print("
! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude).github/**' | grep "print("
- name: Check absence of fixup commits
run: |
! git log | grep 'fixup!'
@@ -43,7 +43,7 @@ jobs:
with:
fetch-depth: 0
- name: Check that the CHANGELOG has been modified in the current branch
run: git whatchanged --name-only --pretty="" origin/${{ github.event.pull_request.base.ref }}..HEAD | grep CHANGELOG
run: git log --name-only --pretty="" origin/${{ github.event.pull_request.base.ref }}..HEAD | grep CHANGELOG
lint-changelog:
runs-on: ubuntu-latest
@@ -101,3 +101,37 @@ jobs:
pip install --user .[dev]
- name: Run tests
run: ~/.local/bin/pytest
helmfile-lint:
runs-on: ubuntu-latest
# skip this job on forks since they won't have access to the required secrets
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
container:
image: ghcr.io/helmfile/helmfile:v1.2.0
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: numerique-gouv
repositories: secrets
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Helmfile lint
env:
SOPS_AGE_KEY: ${{ secrets.SOPS_PRIVATE }}
run: |
HELMFILE=src/helm/helmfile.yaml.gotmpl
environments=$(< $HELMFILE awk -F'[ :]+' '/^ [^ ]/ {print $2} /^---/ { exit }')
for env in $environments; do
echo "################### $env lint ###################"
helmfile -e $env -f "$HELMFILE" lint || exit 1
echo -e "\n"
done
-93
View File
@@ -1,93 +0,0 @@
name: Docker Hub Workflow
on:
workflow_dispatch:
push:
branches:
- 'main'
tags:
- 'v*'
pull_request:
branches:
- 'main'
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "oidc2fer,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: lasuite/oidc2fer
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/oidc2fer/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
-
name: Login to DockerHub
run: echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USER" --password-stdin
-
name: Build and push
uses: docker/build-push-action@v5
with:
context: .
target: production
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
notify-argocd:
runs-on: ubuntu-latest
if: |
github.event_name != 'pull_request'
needs:
- build-and-push
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "oidc2fer,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/oidc2fer/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
-
name: Call argocd github webhook
run: |
data='{"ref": "'$GITHUB_REF'","repository": {"html_url":"'$GITHUB_SERVER_URL'/'$GITHUB_REPOSITORY'"}}'
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_WEBHOOK_URL
-22
View File
@@ -1,22 +0,0 @@
name: Helmfile lint
run-name: Helmfile lint
on:
pull_request:
branches:
- 'main'
jobs:
helmfile-lint:
runs-on: ubuntu-latest
container:
image: ghcr.io/helmfile/helmfile:latest
steps:
-
uses: numerique-gouv/action-helmfile-lint@main
with:
app-id: ${{ secrets.APP_ID }}
age-key: ${{ secrets.SOPS_PRIVATE }}
private-key: ${{ secrets.PRIVATE_KEY }}
helmfile-src: "src/helm"
repositories: "oidc2fer,secrets"
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "secrets"]
path = secrets
url = ../secrets
url = ../../numerique-gouv/secrets
+19
View File
@@ -6,6 +6,25 @@ 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.11] - 2025-11-24
- remove setuptools, wheel and pip from production Docker image
## [1.0.10] - 2025-11-21
- rename helmfile.yaml for compatibility with helmfile 1.x
## [1.0.9] - 2025-10-03
- map SAML entity IDs to SIRET (#34)
- include ACR claim in ID token only if requested (#32)
## [1.0.8] - 2025-09-10
- fix secrets submodule path following move to `proconnect-gouv` organization
- update other references to `numerique-gouv` organization
- publish Docker images at ghcr.io/proconnect-gouv/oidc2fer
## [1.0.7] - 2025-05-07
- remove unused APT dependencies
- upgrade to gunicorn 23.0.0
## [1.0.6] - 2025-03-11
- upgrade to SATOSA 8.5.1
- allow faculty, staff, employee, researcher, teacher affiliations
+7 -12
View File
@@ -1,17 +1,11 @@
# ---- base image to inherit from ----
FROM python:3.11-slim-bookworm as common
FROM python:3.11.12-slim-bookworm AS common
# Install xmlsec1 dependencies required for xmlsec (for SAML)
# Needs to be kept before the `pip install`
RUN apt-get update && \
apt-get -y upgrade && \
apt-get install -y \
pkg-config \
gcc \
xmlsec1 \
libxml2-dev \
libxmlsec1-dev \
libxmlsec1-openssl && \
apt-get install -qy --no-install-recommends xmlsec1 && \
rm -rf /var/lib/apt/lists/*
# We want the most up-to-date stable pip release
@@ -19,7 +13,7 @@ RUN pip install --upgrade pip
ENV PYTHONUNBUFFERED=1
# Give the "root" group the same permissions as the "root" user on /etc/passwd
# Give the "root" group the same permissions AS the "root" user on /etc/passwd
# to allow a user belonging to the root group to add new users; typically the
# docker user (see entrypoint).
RUN chmod g=u /etc/passwd
@@ -41,7 +35,7 @@ COPY docker/files/usr/local/etc/gunicorn/satosa.py /usr/local/etc/gunicorn/satos
CMD ["gunicorn", "-c", "/usr/local/etc/gunicorn/satosa.py"]
# ---- Development image ----
FROM common as development
FROM common AS development
# Playwright browsers
ENV PLAYWRIGHT_BROWSERS_PATH=/pw-browsers
@@ -67,14 +61,15 @@ COPY ./src/satosa /app/
USER ${DOCKER_USER}
# ---- Production image (keep last so it is the default target) ----
FROM common as production
FROM common AS production
# Copy oidc2fer application (see .dockerignore)
COPY ./src/satosa /app/
WORKDIR /app
RUN pip install .
# Uninstall pip, setuptools and wheel after installation to reduce attack surface
RUN pip install . && pip uninstall -y setuptools wheel pip
# Switch to unprivileged user
USER ${DOCKER_USER}
+1 -1
View File
@@ -57,7 +57,7 @@ number and date.
## Deploying a release to production (DINUM instance)
1. Make sure the release you want to deploy has been built and appears on
https://hub.docker.com/r/lasuite/oidc2fer/tags .
https://github.com/proconnect-gouv/oidc2fer/pkgs/container/oidc2fer
2. Edit `image/tag` at the top of
`src/helm/env.d/outscale-production/values.oidc2fer.yaml.gotmpl`.
3. Commit and push to `main`.
+1 -1
View File
@@ -66,7 +66,7 @@ services:
#OIDC_PROVIDER: https://oidc2fer-staging.beta.numerique.gouv.fr
OIDC_CLIENT_ID: oidc-test-client
OIDC_CLIENT_SECRET: oidc-test-secret
OIDC_SCOPES: openid,uid,given_name,usual_name,email
OIDC_SCOPES: openid,uid,given_name,usual_name,email,siret
extra_hosts:
- "oidc2fer.127.0.0.1.nip.io:host-gateway"
+2 -4
View File
@@ -2,13 +2,10 @@ from flask import Flask, jsonify, request, session
from oic.oic import Client
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic import rndstr
from oic.oic.message import RegistrationResponse
from oic.oic.message import Claims, ClaimsRequest, RegistrationResponse
from oic.utils.http_util import Redirect
from oic.oic.message import AuthorizationResponse
import secrets
import webbrowser
import threading
import time
import logging
import os
@@ -52,6 +49,7 @@ def index():
"nonce": session["nonce"],
"redirect_uri": client.registration_response["redirect_uris"][0],
"state": session["state"],
"claims": ClaimsRequest(id_token=Claims(acr=None, amr=None)),
}
)
login_url = auth_req.request(client.authorization_endpoint)
+2 -2
View File
@@ -1,2 +1,2 @@
Flask==3.0.3
oic==1.6.1
Flask==3.1.3
oic==1.7.0
+1 -1
Submodule secrets updated: b0d485544d...5773ab2a69
@@ -36,6 +36,10 @@ satosa:
"token_endpoint_auth_method": "client_secret_post"
}
}
SIRET_MAP: |-
{
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
}
ingress:
enabled: true
@@ -1,7 +1,7 @@
image:
repository: lasuite/oidc2fer
repository: ghcr.io/proconnect-gouv/oidc2fer
pullPolicy: Always
tag: "v1.0.6"
tag: "v1.0.11"
satosa:
replicas: 2
@@ -24,6 +24,112 @@ satosa:
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
# As provided by RENATER
SIRET_MAP: |-
{
"http://idp.univ-poitiers.fr": "19860856400375",
"https://apps.univ-lr.fr/idp/shibboleth": "19170032700015",
"https://auth.sso.vet-alfort.fr/saml/metadata": "19940608300014",
"https://auth.uttop.fr/saml/metadata": "19650048200019",
"https://authentification.inrae.fr/saml/metadata/idp": "18007003901803",
"https://federation.ens.psl.eu/idp/shibboleth": "19753459700012",
"https://federation.umontpellier.fr/idp/shibboleth": "13002979600013",
"https://federation.unimes.fr/idp/shibboleth": "93249157400012",
"https://federation.upf.pf/idp/shibboleth": "19987001500013",
"https://federation.utbm.fr/idp/shibboleth": "19900356700013",
"https://federation3.univ-brest.fr/idp/shibboleth": "94129831700012",
"https://idauthproxy.insa-lyon.fr/Saml2IDP/metadata": "19690192000013",
"https://ident-shib.ensc-rennes.fr/idp/shibboleth": "19350077400016",
"https://identification.univ-toulouse.fr": "13002132200016",
"https://identites.ec-lyon.fr/idp/shibboleth": "19690187000010",
"https://identites.ensea.fr/idp/shibboleth": "19951376300011",
"https://identities.univ-jfc.fr/idp/prod": "19811201300018",
"https://idp-genci.renater.fr/idp/shibboleth": "49468697500041",
"https://idp-ng.univ-st-etienne.fr/idp/shibboleth": "93850168100010",
"https://idp-septa.onisep.fr/idp/shibboleth": "18004302800653",
"https://idp-v4.univ-montp3.fr/idp/shibboleth": "93249089900014",
"https://idp.bnu.fr/idp/shibboleth": "18004406700015",
"https://idp.cirad.fr/idp/shibboleth": "33159627000016",
"https://idp.crous-reims.fr/idp/shibboleth": "18510200100327",
"https://idp.ec-nantes.fr/idp/shibboleth": "19440100600011",
"https://idp.ehesp.fr/idp/shibboleth": "13000362700010",
"https://idp.ens-lyon.fr/idp/shibboleth": "13000812100019",
"https://idp.ensam.eu/idp/shibboleth": "19753472000010",
"https://idp.ensfea.fr/idp/shibboleth": "19310143300012",
"https://idp.ensma.fr/idp/shibboleth": "19860073600021",
"https://idp.ent.dauphine.fr/idp/shibboleth": "19754692200018",
"https://idp.imt-atlantique.fr/idp/shibboleth": "18009202500121",
"https://idp.inha.fr/idp/shibboleth": "19754688000018",
"https://idp.inp-toulouse.fr/idp/shibboleth": "19311381800127",
"https://idp.insa-rennes.fr/idp/shibboleth": "19350097200016",
"https://idp.institut-agro.fr/idp": "13002622200013",
"https://idp.isae.fr/idp/shibboleth": "13000427800011",
"https://idp.lyon.archi.fr/idp/shibboleth": "19690184700018",
"https://idp.renater.fr/idp/shibboleth": "18008947600055",
"https://idp.rennes.archi.fr/idp/shibboleth": "19350089900029",
"https://idp.sciencespo-lyon.fr/idp/shibboleth": "19690173000024",
"https://idp.sciencespobordeaux.fr/idp/shibboleth": "19330192600039",
"https://idp.uca.fr/idp/shibboleth": "13002806100013",
"https://idp.uha.fr/idp/shibboleth": "19681166500013",
"https://idp.unistra.fr/idp/shibboleth": "13000545700010",
"https://idp.univ-avignon.fr/idp/shibboleth": "19840685200204",
"https://idp.univ-cotedazur.fr/idp/shibboleth": "13002566100013",
"https://idp.univ-eiffel.fr/idp/shibboleth": "13002612300013",
"https://idp.univ-lemans.fr/idp/shibboleth": "19720916600010",
"https://idp.univ-lille.fr/idp/shibboleth": "13002975400012",
"https://idp.univ-lyon2.fr/idp/shibboleth": "19691775100014",
"https://idp.univ-lyon3.fr/idp/shibboleth": "19692437700282",
"https://idp.univ-orleans.fr/idp/shibboleth": "19450855200016",
"https://idp.univ-perp.fr/idp/shibboleth": "19660437500010",
"https://idp.univ-tln.fr/idp/shibboleth": "19830766200017",
"https://idp.univ-tlse3.fr/idp/shibboleth": "93827139200012",
"https://idp.univ-tours.fr/idp/shibboleth": "19370800500478",
"https://idp.universite-paris-saclay.fr/idp": "13002602400054",
"https://idp1.agroparistech.fr/idp/shibboleth": "13000285000134",
"https://idp1.ens-paris-saclay.fr/idp/shibboleth": "19940607500036",
"https://idp1.univ-fcomte.fr/idp/shibboleth": "93810656400017",
"https://idp2.amue.fr/idp/shibboleth": "18004312700091",
"https://idp2.brgm.fr/idp/shibboleth": "58205614900120",
"https://idp2.emse.fr/idp/shibboleth": "18009202500105",
"https://idp2.univ-paris8.fr/idp/shibboleth": "19931827000014",
"https://idp3.univ-lorraine.fr/idp/shibboleth": "13001550600012",
"https://idp3.ut-capitole.fr/idp/shibboleth": "13003061200019",
"https://idp4.unicaen.fr/idp/shibboleth": "19141408500016",
"https://idpv3.univ-amu.fr/idp/shibboleth": "13001533200013",
"https://janus.cnrs.fr/idp": "18008901303720",
"https://multipass.imt-nord-europe.fr/idp/shibboleth": "18009202500139",
"https://papangue.vetagro-sup.fr/idp/shibboleth": "13000858400018",
"https://prod-idp.inria.fr": "18008904700013",
"https://ruhnu.univ-tlse2.fr/idp/shibboleth": "19311383400017",
"https://shib.mines-albi.fr/idp/shibboleth": "18009202500097",
"https://shib.univ-lehavre.fr/idp/shibboleth": "19762762300097",
"https://identite.univ-reims.fr/idp/shibboleth": "19511296600799",
"https://shib2.unc.nc/idp/shibboleth": "13000322100012",
"https://shibboleth.ens2m.fr/idp/shibboleth": "19250082500026",
"https://shibboleth.grenoble-inp.fr/idp/shibboleth": "19381912500017",
"https://shibboleth.insa-rouen.fr/idp/shibboleth": "19760165100023",
"https://shibboleth.ube.fr/idp/shibboleth": "93823061200013",
"https://shibboleth.univ-corse.fr/idp/shibboleth": "19202664900264",
"https://shibboleth.univ-evry.fr/idp/shibboleth": "19911975100014",
"https://shibboleth.univ-grenoble-alpes.fr/idp/shibboleth": "13002608100013",
"https://shibboleth.univ-savoie.fr/idp/shibboleth": "19730858800015",
"https://shibboleth03.chartes.psl.eu/idp/shibboleth": "19753478700043",
"https://shibboleth3.utt.fr/idp/shibboleth": "19101060200032",
"https://srv-fii.insa-toulouse.fr/idp/shibboleth": "19310152400018",
"https://sso-ciation-saclay.centralesupelec.fr/idp/shibboleth": "13002076100016",
"https://sso.bordeaux-inp.fr/idp/shibboleth": "13000635600013",
"https://sso.ird.fr/idp/shibboleth": "18000602500159",
"https://upnidp2.parisnanterre.fr/idp/shibboleth": "19921204400010",
"https://vip.espci.fr/saml2/idp/metadata.php": "20000068500012",
"urn:mace:cru.fr:federation:uhb.fr": "19350937900015",
"urn:mace:cru.fr:federation:unilim.fr": "19870669900321",
"urn:mace:cru.fr:federation:univ-nantes.fr": "13002974700016",
"urn:mace:cru.fr:federation:univ-paris1.fr": "19751717000019",
"urn:mace:cru.fr:federation:univ-rennes1.fr": "13003051300019",
"urn:mace:cru.fr:federation:univ-rouen.fr": "19761904200017",
"urn:mace:cru.fr:federation:univ-ubs.fr": "19561718800600"
}
ingress:
enabled: true
host: renater.agentconnect.gouv.fr
@@ -1,7 +1,7 @@
image:
repository: lasuite/oidc2fer
repository: ghcr.io/proconnect-gouv/oidc2fer
pullPolicy: Always
tag: "main"
tag: "latest"
satosa:
replicas: 2
@@ -24,6 +24,11 @@ satosa:
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
SIRET_MAP: |-
{
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
}
ingress:
enabled: true
host: oidc2fer-staging.beta.numerique.gouv.fr
@@ -1,3 +1,20 @@
environments:
dev:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
staging:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
outscale-production:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
---
repositories:
- name: bitnami
url: registry-1.docker.io/bitnamicharts
@@ -29,21 +46,3 @@ releases:
- env.d/{{ .Environment.Name }}/values.oidc2fer.yaml.gotmpl
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
environments:
dev:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
staging:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
outscale-production:
values:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
+3
View File
@@ -31,3 +31,6 @@ attributes:
uid:
openid:
- uid
siret:
openid:
- siret
@@ -0,0 +1 @@
from .entity_id_to_siret_mapper import EntityIdToSiretMapper
@@ -0,0 +1,23 @@
import json
import logging
from satosa.micro_services.base import ResponseMicroService
logger = logging.getLogger(__name__)
class EntityIdToSiretMapper(ResponseMicroService):
def __init__(self, config, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attribute = config.get("attribute", "siret")
self.mapping = json.loads(config.get("mapping_json", "{}"))
def process(self, context, data):
entity_id = data.auth_info.issuer
if entity_id in self.mapping:
siret = self.mapping[entity_id]
logger.info("Mapping entity ID %s to SIRET %s", entity_id, siret)
data.attributes[self.attribute] = siret
else:
logger.warning("No SIRET mapping found for entity ID %s", entity_id)
return super().process(context, data)
@@ -43,6 +43,7 @@ config:
- uid
- given_name
- usual_name
- siret
# Set code/token lifetimes as short as possible
authorization_code_lifetime: 60
@@ -56,8 +57,5 @@ config:
- given_name
usual_name:
- usual_name
extra_id_token_claims:
oidc-test-client:
- acr
agent-connect:
- acr
siret:
- siret
@@ -0,0 +1,5 @@
module: oidc2fer.attribute_generators.EntityIdToSiretMapper
name: EntityIdToSiretMapper
config:
attribute: siret
mapping_json: !ENV SIRET_MAP
+1
View File
@@ -17,6 +17,7 @@ MICRO_SERVICES:
- plugins/microservices/primary_identifier.yaml
- plugins/microservices/static_attributes.yaml
- plugins/microservices/attribute_processor.yaml
- plugins/microservices/siret_mapping.yaml
LOGGING:
# All the logging configuration is done in the Gunicorn config, this is just
# here to avoid overwriting it with the default SATOSA config
+5 -5
View File
@@ -24,17 +24,17 @@ readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"SATOSA==8.5.1",
"gunicorn==22.0.0",
"gunicorn==23.0.0",
"redis==5.0.4",
"JSON-log-formatter==1.0",
"WhiteNoise==6.7.0",
]
[project.urls]
"Bug Tracker" = "https://github.com/numerique-gouv/oidc2fer/issues/new"
"Changelog" = "https://github.com/numerique-gouv/oidc2fer/blob/main/CHANGELOG.md"
"Homepage" = "https://github.com/numerique-gouv/oidc2fer"
"Repository" = "https://github.com/numerique-gouv/oidc2fer"
"Bug Tracker" = "https://github.com/proconnect-gouv/oidc2fer/issues/new"
"Changelog" = "https://github.com/proconnect-gouv/oidc2fer/blob/main/CHANGELOG.md"
"Homepage" = "https://github.com/proconnect-gouv/oidc2fer"
"Repository" = "https://github.com/proconnect-gouv/oidc2fer"
[project.optional-dependencies]
dev = [
@@ -0,0 +1,42 @@
import json
from satosa.context import Context
from satosa.internal import AuthenticationInformation, InternalData
from oidc2fer.attribute_generators import EntityIdToSiretMapper
class TestEntityIdToSiretMapper:
def create_mapper(self):
mapper = EntityIdToSiretMapper(
config={
"attribute": "siret",
"mapping_json": json.dumps(
{
"https://idp.example.fr": "12345678200010",
}
),
},
name="siret_mapper",
base_url="https://satosa.example.com",
)
mapper.next = lambda ctx, data: data
return mapper
def test_sets_siret_for_known_entityid(self):
mapper = self.create_mapper()
resp = InternalData(
auth_info=AuthenticationInformation(issuer="https://idp.example.fr")
)
ctx = Context()
mapper.process(ctx, resp)
assert resp.attributes["siret"] == "12345678200010"
def test_does_not_set_siret_for_unknown_entityid(self):
mapper = self.create_mapper()
resp = InternalData(
auth_info=AuthenticationInformation(issuer="https://unknown.example.fr")
)
ctx = Context()
mapper.process(ctx, resp)
assert "siret" not in resp.attributes
+4 -1
View File
@@ -20,6 +20,7 @@ def renater_test_idp(page, login):
def renater_wayf(page):
page.get_by_text("Veuillez sélectionner").click()
page.get_by_role("searchbox").fill("GIP RENATER - IdP de test")
page.get_by_role("option", name="GIP RENATER - IdP de test", exact=True).click()
page.get_by_role("button", name="Sélection").click()
@@ -48,6 +49,7 @@ def oidc_to_renater(
"email": expected_email,
"given_name": expected_given_name,
"usual_name": expected_usual_name,
"siret": "12345678200010",
}.items() <= userinfo.items()
return id_token
@@ -101,6 +103,7 @@ def pro_connect_to_renater(
"email": expected_email,
"given_name": expected_given_name,
"usual_name": expected_usual_name,
"siret": "12345678200010",
}.items() <= result.items()
return result
@@ -125,7 +128,7 @@ def test_pro_connect_to_renater_student_not_allowed(page: Page):
renater_wayf(page)
renater_test_idp(page, login="etudiant1")
expect(page.locator("body")).to_contain_text("Une erreur technique est survenue.")
expect(page.locator("body")).to_contain_text("access_denied")
@pytest.mark.skipif(