Compare commits

...

64 Commits

Author SHA1 Message Date
Jonathan Perret cfec0eead1 🔐(secrets) update secrets to current main 2026-03-26 16:25:19 +01:00
Jonathan Perret 5932135ec5 🔐(secrets) update secrets to current main 2026-03-26 15:26:17 +01:00
Jonathan Perret 0a43908ac3 Deploy release v1.0.13 to production 2026-03-26 15:10:43 +01:00
Jonathan Perret 435e2e20a9 v1.0.13 release 2026-03-26 14:54:48 +01:00
Jonathan Perret 5dcfcf213d Merge pull request #40 from proconnect-gouv/stateless-oidc
Utiliser le mode stateless de SATOSA pour ne plus avoir besoin de Redis
2026-03-26 14:53:06 +01:00
Jonathan Perret 00b048d94d 🗃️(redis) remove Redis support
We switched to stateless OIDC.
2026-03-26 14:34:58 +01:00
Jonathan Perret bda7a44bc8 🔧(helm) use stateless OIDC in production
Getting rid of Redis should help with performance.
2026-03-26 13:41:53 +01:00
Jonathan Perret 9db60451aa 🔧(helm) use stateless OIDC in dev and staging
Getting rid of Redis should help with performance.
2026-03-25 10:37:00 +01:00
Jonathan Perret 018b9e8726 🔧(helm) use lists for env vars
Moving back to the Kubernetes-native syntax of lists makes it possible
to use dependent environment variables.
2026-03-25 10:04:28 +01:00
Jonathan Perret ea4199de91 Merge pull request #39 from proconnect-gouv/tilt-oidc-test-client
🔨 Configuration Tilt pour le client test OIDC
2026-03-20 15:44:31 +01:00
Jonathan Perret 4d1a9c56d2 🔨(e2e) add benchmark e2e test
This can help diagnose performance issues.
2026-03-20 15:32:09 +01:00
Jonathan Perret 14f9d42889 ⬆️ (oidc-test-client) create Helm chart for test client
This helps running tests with the app running in a
Kubernetes cluster.
2026-03-20 15:32:08 +01:00
Jonathan Perret 3a0a0564d7 🔧(siret) fix SIRET for univ-angers.fr
As provided by RENATER.
2026-03-06 17:24:28 +01:00
Jonathan Perret 9a82204f69 🔧(siret) add new entities to SIRET map
As provided by RENATER.
2026-03-05 15:22:10 +01:00
Jonathan Perret fd4a2b665f 🔧(siret) add new entities to SIRET map
As provided by RENATER.
2026-03-05 14:11:14 +01:00
Jonathan Perret 645bbaca74 Deploy release v1.0.12 to production 2026-03-02 19:43:36 +01:00
Jonathan Perret 1ef50896ec v1.0.12 release 2026-03-02 19:41:37 +01:00
Jonathan Perret f8661c76d5 Merge pull request #38 from proconnect-gouv/deps-update
Update dependencies
2026-03-02 19:38:16 +01:00
Jonathan Perret ecfa38f11e ⬆️ (actions) upgrade and pin GitHub actions
To latest stable versions.
2026-02-27 19:08:46 +01:00
Jonathan Perret 159d992783 🔧(config) add healthcheck to docker-compose
This makes docker-compose up --wait work.
2026-02-27 19:05:31 +01:00
Jonathan Perret 2efaaa8281 🔨(kind) improve local cluster start script
Taking some cues from what's done in other projects.
2026-02-27 19:05:30 +01:00
Jonathan Perret f0b1c4cbc3 ⬆️ (python) upgrade Python dependencies
To latest stable versions.
2026-02-27 19:05:29 +01:00
Jonathan Perret 2e9dd01907 🔨(redis) fix bitnami image reference
Bitnami images have moved.
2026-02-27 19:05:28 +01:00
Jonathan Perret 5f7b7ab8a8 🔥(pyproject) remove setup.py
This file is not needed with a modern project structure, and since
`setuptools` is no longer included in recent Python versions it causes a
`pylint` failure.
2026-02-27 19:05:19 +01:00
Jonathan Perret 9994eb84b0 ⬆️ (python) upgrade to Python 3.14.3
Bumping base image to avoid reported vulnerabilities.
2026-02-27 19:04:37 +01:00
Jonathan Perret f9efafd574 🔧 (metadata) update Renater metadata URL
The old URLs were decommissionned on feb. 26.
2026-02-27 14:45:11 +01: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
44 changed files with 904 additions and 368 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Docker meta
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # 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@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # 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@cac2ee67896eb13e84e804f60c4271370424eaa8 # 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:
@@ -16,14 +16,14 @@ jobs:
if: github.event_name == 'pull_request' # Makes sense only for pull requests
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: show
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!'
@@ -39,17 +39,17 @@ jobs:
github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
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
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check CHANGELOG max line length
run: |
max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L)
@@ -65,11 +65,11 @@ jobs:
working-directory: src/satosa
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Python
uses: actions/setup-python@v3
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.11'
python-version: '3.14'
- name: Install development dependencies
run: |
# Python's xmlsec requirement
@@ -89,11 +89,11 @@ jobs:
working-directory: src/satosa
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Python
uses: actions/setup-python@v3
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.11'
python-version: '3.14'
- name: Install development dependencies
run: |
# Python's xmlsec requirement
@@ -101,3 +101,45 @@ 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@29824e69f54612133e76f7eaac726eef6c875baf # v2
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Install mkcert
run: |
apt-get update -y -q && apt-get install -y -q libnss3-tools
curl -Ss -L -o mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64
chmod +x mkcert
mv mkcert /usr/local/bin/
TRUST_STORES=none mkcert -install
-
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
+25
View File
@@ -6,6 +6,31 @@ 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.13] - 2026-03-26
- switch to stateless OIDC and remove Redis
## [1.0.12] - 2026-03-02
- upgrade dependencies: Python 3.14.3, gunicorn 25.1.0…
## [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
+16 -13
View File
@@ -1,25 +1,23 @@
# ---- base image to inherit from ----
FROM python:3.11-slim-bookworm as common
FROM python:3.14.3-slim-trixie AS common
# Install xmlsec1 dependencies required for xmlsec (for SAML)
# Needs to be kept before the `pip install`
RUN apt-get update && \
RUN export DEBIAN_FRONTEND=noninteractive && \
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/*
# Silence pip warnings about running as root in a container
ENV PIP_ROOT_USER_ACTION=ignore
# We want the most up-to-date stable pip release
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 +39,11 @@ 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
# Install curl (for healthchecks)
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && apt-get install -qy curl
# Playwright browsers
ENV PLAYWRIGHT_BROWSERS_PATH=/pw-browsers
@@ -67,14 +69,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`.
+5
View File
@@ -13,6 +13,11 @@ docker_build(
]
)
docker_build(
'localhost:5001/oidc-test-client:latest',
context='docker/oidc-test-client'
)
watch_file('src/helm')
k8s_yaml(local('cd src/helm && helmfile -n oidc2fer -e dev template .'))
+10 -8
View File
@@ -14,7 +14,7 @@ services:
GUNICORN_CMD_ARGS: --workers=2
TEST_E2E: 1
#TEST_E2E_PC: 1
OIDC_DB_URI: redis://redis/0
OIDC_DB_URI: stateless://:STATE-ENCRYPTION-KEY@localhost
CLIENT_DB_JSON: |
{
"oidc-test-client": {
@@ -30,7 +30,7 @@ services:
}
}
SAML2_DISCOVERY_URL: https://discovery.renater.fr/test/
SAML2_METADATA_URL: https://pub.federation.renater.fr/metadata/test/preview/preview-idps-test-metadata.xml
SAML2_METADATA_URL: https://pub.federation.renater.fr/metadata/test/idps.xml
SAML2_ENTITY_ID: https://satosa.traefik.me/Saml2/proxy_saml2_backend.xml
env_file:
- env.d/development/common
@@ -38,8 +38,13 @@ services:
volumes:
- ./src/satosa:/app
- ./docker/files/usr/local/etc/gunicorn/satosa.py:/usr/local/etc/gunicorn/satosa.py
depends_on:
- redis
healthcheck:
test: ["CMD", "curl", "--fail", "http://localhost:8000/ping"]
interval: 60s
timeout: 5s
retries: 3
start_period: 30s
start_interval: 1s
oidc-test-client:
build: docker/oidc-test-client
@@ -66,13 +71,10 @@ 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"
redis:
image: redis:7.2.4
nginx:
image: nginx:1.25
ports:
-6
View File
@@ -39,11 +39,5 @@ printenv SAML2_BACKEND_KEY > /tmp/backend.key
printenv OIDC_FRONTEND_KEY > /tmp/frontend.key
printenv CLIENT_DB_JSON > /tmp/client_db.json
# Redis database number must be specified
if [[ ! $OIDC_DB_URI =~ /[0-9]+$ ]]; then
echo "🐳(entrypoint) adding db id to OIDC_DB_URI"
export OIDC_DB_URI=$OIDC_DB_URI/0
fi
echo "🐳(entrypoint) running your command: ${*}"
exec "$@"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.11
FROM python:3.14.3-slim-trixie
COPY . /app
+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)
+1 -1
View File
@@ -1,2 +1,2 @@
Flask==3.0.3
oic==1.6.1
oic==1.7.0
+1 -1
Submodule secrets updated: b0d485544d...aa2de36cd8
@@ -0,0 +1,22 @@
image:
repository: localhost:5001/oidc-test-client
pullPolicy: Always
tag: "latest"
ingress:
enabled: true
host: oidc-test-client.127.0.0.1.nip.io
env:
- name: OIDC_ROOT_URL
value: https://oidc-test-client.127.0.0.1.nip.io
- name: OIDC_PROVIDER
value: https://oidc2fer.127.0.0.1.nip.io
- name: OIDC_CLIENT_ID
value: oidc-test-client
- name: OIDC_CLIENT_SECRET
value: oidc-test-secret
- name: OIDC_SCOPES
value: openid,uid,given_name,usual_name,email,siret
- name: EXTRA_ROOT_CA
value: {{ exec "mkcert" (list "-CAROOT") | trim | printf "%s/rootCA.pem" | readFile | quote }}
+46 -26
View File
@@ -5,37 +5,57 @@ image:
satosa:
replicas: 1
envVars:
BASE_URL: https://oidc2fer.127.0.0.1.nip.io
GUNICORN_CMD_ARGS: --workers=3
env:
- name: BASE_URL
value: https://oidc2fer.127.0.0.1.nip.io
- name: GUNICORN_CMD_ARGS
value: --workers=3
LOG_LEVEL: debug
- name: LOG_LEVEL
value: 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
SAML2_ENTITY_ID: https://oidc2fer.127.0.0.1.nip.io/Saml2/proxy_saml2_backend.xml
- name: SAML2_DISCOVERY_URL
value: https://discovery.renater.fr/test/
- name: SAML2_METADATA_URL
value: https://pub.federation.renater.fr/metadata/test/idps.xml
- name: SAML2_ENTITY_ID
value: https://oidc2fer.127.0.0.1.nip.io/Saml2/proxy_saml2_backend.xml
STATE_ENCRYPTION_KEY: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
SAML2_BACKEND_CERT: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
SAML2_BACKEND_KEY: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
OIDC_FRONTEND_KEY: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
- name: STATE_ENCRYPTION_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
- name: SAML2_BACKEND_CERT
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
- name: SAML2_BACKEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
- name: OIDC_FRONTEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
OIDC_DB_URI: "redis://:pass@redis-master:6379"
CLIENT_DB_JSON: |-
{
"oidc-test-client": {
"response_types": [
"id_token",
"code"
],
"redirect_uris": [
"https://oidc-test-client.traefik.me/redirect_uri",
"https://oidc-test-client.traefik.me:8443/redirect_uri"
],
"client_secret": "oidc-test-secret",
"token_endpoint_auth_method": "client_secret_post"
- name: OIDC_DB_URI
value: "stateless://:$(STATE_ENCRYPTION_KEY)@localhost"
- name: CLIENT_DB_JSON
value: |-
{
"oidc-test-client": {
"response_types": [
"id_token",
"code"
],
"redirect_uris": [
"https://oidc-test-client.traefik.me/redirect_uri",
"https://oidc-test-client.traefik.me:8443/redirect_uri",
"https://oidc-test-client.127.0.0.1.nip.io/redirect_uri"
],
"client_secret": "oidc-test-secret",
"token_endpoint_auth_method": "client_secret_post"
}
}
- name: SIRET_MAP
value: |-
{
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
}
}
ingress:
enabled: true
@@ -1,28 +1,172 @@
image:
repository: lasuite/oidc2fer
repository: ghcr.io/proconnect-gouv/oidc2fer
pullPolicy: Always
tag: "v1.0.6"
tag: "v1.0.13"
satosa:
replicas: 2
envVars:
BASE_URL: https://renater.agentconnect.gouv.fr
GUNICORN_CMD_ARGS: --workers=3
env:
- name: BASE_URL
value: https://renater.agentconnect.gouv.fr
- name: GUNICORN_CMD_ARGS
value: --workers=3
LOG_LEVEL: INFO
LOG_LEVELS: '{ "satosa.backends.saml2": "DEBUG" }'
- name: LOG_LEVEL
value: INFO
- name: LOG_LEVELS
value: '{ "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
SAML2_ENTITY_ID: https://renater.agentconnect.gouv.fr/Saml2/proxy_saml2_backend.xml
- name: SAML2_DISCOVERY_URL
value: https://discovery.renater.fr/agentconnect/
- name: SAML2_METADATA_URL
value: https://pub.federation.renater.fr/metadata/fer/idps.xml
- name: SAML2_ENTITY_ID
value: https://renater.agentconnect.gouv.fr/Saml2/proxy_saml2_backend.xml
STATE_ENCRYPTION_KEY: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
SAML2_BACKEND_CERT: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
SAML2_BACKEND_KEY: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
OIDC_FRONTEND_KEY: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
CLIENT_DB_JSON: { secretKeyRef: { name: oidc2fer, key: CLIENT_DB_JSON } }
- name: STATE_ENCRYPTION_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
- name: SAML2_BACKEND_CERT
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
- name: SAML2_BACKEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
- name: OIDC_FRONTEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
- name: CLIENT_DB_JSON
valueFrom: { secretKeyRef: { name: oidc2fer, key: CLIENT_DB_JSON } }
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
- name: OIDC_DB_URI
value: "stateless://:$(STATE_ENCRYPTION_KEY)@localhost"
# As provided by RENATER
- name: SIRET_MAP
value: |-
{
"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",
"https://idp.marseille.archi.fr/idp/shibboleth": "19130236300020",
"https://idp.inalco.fr/idp/shibboleth": "19753488600092",
"https://idp.sigma-clermont.fr/idp/shibboleth": "13002191800011",
"https://idp.univ-artois.fr/idp/shibboleth": "19624401600016",
"https://idp2.ensai.fr/idp/shibboleth": "13001422800055",
"urn:mace:cru.fr:federation:univ-lyon1.fr": "19691774400019",
"https://idp.enitab.fr/idp/shibboleth": "19330203100011",
"https://idp.oca.eu/idp/shibboleth": "19061563300012",
"https://idp.univ-paris13.fr/idp/shibboleth": "19931238000017",
"https://idp.ens-rennes.fr/idp/shibboleth": "13001848400019",
"https://idp.uphf.fr/idp/shibboleth": "13002574500014",
"https://idp.college-de-france.fr/idp/shibboleth": "19753480300014",
"https://shibboleth.csi.uvsq.fr/idp/shibboleth": "19781944400013",
"https://idp.esaip.org/idp/shibboleth": "37920438100014",
"https://idp.eskn.fr/idp/shibboleth": "13002617200010",
"https://auth.centrale-marseille.fr/idp/shibboleth": "19133340000015",
"https://idp-insa-cvl.renater.fr/idp/shibboleth": "13001833600011",
"https://shibboleth3.obspm.fr/idp/shibboleth": "19753496900013",
"https://idp-ecole-air.renater.fr/idp/shibboleth": "13002454000010",
"https://idp.enpc.fr/saml/metadata": "19753501600020",
"https://idp.paris-malaquais.archi.fr/idp/shibboleth": "18009221500011",
"https://idp.univ-pau.fr/idp/shibboleth": "19640251500270",
"https://idp4.cereq.fr/idp/shibboleth": "18004303600037",
"urn:mace:cru.fr:federation:univ-angers.fr": "19490970100303"
}
ingress:
enabled: true
@@ -1,28 +1,47 @@
image:
repository: lasuite/oidc2fer
repository: ghcr.io/proconnect-gouv/oidc2fer
pullPolicy: Always
tag: "main"
tag: "latest"
satosa:
replicas: 2
envVars:
BASE_URL: https://oidc2fer-staging.beta.numerique.gouv.fr
GUNICORN_CMD_ARGS: --workers=3
env:
- name: BASE_URL
value: https://oidc2fer-staging.beta.numerique.gouv.fr
- name: GUNICORN_CMD_ARGS
value: --workers=3
LOG_LEVEL: DEBUG
LOG_LEVELS: '{ "satosa.backends.saml2": "DEBUG" }'
- name: LOG_LEVEL
value: DEBUG
- name: LOG_LEVELS
value: '{ "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
SAML2_ENTITY_ID: https://oidc2fer-staging.beta.numerique.gouv.fr/Saml2/proxy_saml2_backend.xml-test
- name: SAML2_DISCOVERY_URL
value: https://discovery.renater.fr/test/
- name: SAML2_METADATA_URL
value: https://pub.federation.renater.fr/metadata/test/idps.xml
- name: SAML2_ENTITY_ID
value: https://oidc2fer-staging.beta.numerique.gouv.fr/Saml2/proxy_saml2_backend.xml-test
STATE_ENCRYPTION_KEY: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
SAML2_BACKEND_CERT: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
SAML2_BACKEND_KEY: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
OIDC_FRONTEND_KEY: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
CLIENT_DB_JSON: { secretKeyRef: { name: oidc2fer, key: CLIENT_DB_JSON } }
- name: STATE_ENCRYPTION_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: STATE_ENCRYPTION_KEY } }
- name: SAML2_BACKEND_CERT
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_CERT } }
- name: SAML2_BACKEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: SAML2_BACKEND_KEY } }
- name: OIDC_FRONTEND_KEY
valueFrom: { secretKeyRef: { name: oidc2fer, key: OIDC_FRONTEND_KEY } }
- name: CLIENT_DB_JSON
valueFrom: { secretKeyRef: { name: oidc2fer, key: CLIENT_DB_JSON } }
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
- name: OIDC_DB_URI
value: "stateless://:$(STATE_ENCRYPTION_KEY)@localhost"
- name: SIRET_MAP
value: |-
{
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
}
ingress:
enabled: true
-5
View File
@@ -1,5 +0,0 @@
apiVersion: v2
name: extra
description: A Helm chart to add some manifests to oidc2fer
type: application
version: 0.1.0
-7
View File
@@ -1,7 +0,0 @@
apiVersion: core.libre.sh/v1alpha1
kind: Redis
metadata:
name: redis
namespace: {{ .Release.Namespace | quote }}
spec:
disableAuth: false
@@ -1,35 +1,3 @@
repositories:
- name: bitnami
url: registry-1.docker.io/bitnamicharts
oci: true
releases:
- name: redis
installed: {{ eq .Environment.Name "dev" | toYaml }}
namespace: {{ .Namespace }}
chart: bitnami/redis
version: 18.19.2
values:
- auth:
password: pass
architecture: standalone
- name: extra
installed: {{ ne .Environment.Name "dev" | toYaml }}
namespace: {{ .Namespace }}
chart: ./extra
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
- name: oidc2fer
version: {{ .Values.version }}
namespace: {{ .Namespace }}
chart: ./oidc2fer
values:
- env.d/{{ .Environment.Name }}/values.oidc2fer.yaml.gotmpl
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
environments:
dev:
values:
@@ -46,4 +14,26 @@ environments:
- version: 0.0.1
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
---
repositories:
- name: bitnami
url: registry-1.docker.io/bitnamicharts
oci: true
releases:
- name: oidc2fer
version: {{ .Values.version }}
namespace: {{ .Namespace }}
chart: ./oidc2fer
values:
- env.d/{{ .Environment.Name }}/values.oidc2fer.yaml.gotmpl
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
- name: oidc-test-client
installed: {{ eq .Environment.Name "dev" }}
version: {{ .Values.version }}
namespace: {{ .Namespace }}
chart: ./oidc-test-client
values:
- env.d/{{ .Environment.Name }}/values.oidc-test-client.yaml.gotmpl
+24
View File
@@ -0,0 +1,24 @@
apiVersion: v2
name: oidc-test-client
description: Test OIDC client
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.0.0"
@@ -0,0 +1,51 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "oidc-test-client.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "oidc-test-client.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "oidc-test-client.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "oidc-test-client.labels" -}}
helm.sh/chart: {{ include "oidc-test-client.chart" . }}
{{ include "oidc-test-client.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "oidc-test-client.selectorLabels" -}}
app.kubernetes.io/name: {{ include "oidc-test-client.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
@@ -0,0 +1,71 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "oidc-test-client.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "oidc-test-client.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "oidc-test-client.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oidc-test-client.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{ with .Values.livenessProbe }}
livenessProbe: {{ toJson . }}
{{- end }}
{{ with .Values.readinessProbe }}
readinessProbe: {{ toJson . }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
command:
- sh
- -ec
- |-
printenv EXTRA_ROOT_CA >> $(python -m certifi)
exec python app.py
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
@@ -0,0 +1,38 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "oidc-test-client.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "oidc-test-client.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className }}
{{- if .Values.ingress.tls.enabled }}
tls:
{{- if .Values.ingress.host }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingress.host | quote }}
{{- end }}
{{- end }}
rules:
{{- if .Values.ingress.host }}
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "oidc-test-client.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "oidc-test-client.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "oidc-test-client.selectorLabels" . | nindent 4 }}
+71
View File
@@ -0,0 +1,71 @@
# Default values for oidc-test-client.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: oidc-test-client
pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 5000
ingress:
enabled: true
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts: []
tls:
enabled: true
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
livenessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 30
readinessProbe: null
nodeSelector: {}
tolerations: []
affinity: {}
env: []
-40
View File
@@ -50,46 +50,6 @@ app.kubernetes.io/name: {{ include "oidc2fer.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
transform dictionnary of environment variables
Usage : {{ include "oidc2fer.env.transformDict" .Values.envVars }}
Example:
envVars:
# Using simple strings as env vars
ENV_VAR_NAME: "envVar value"
# Using a value from a configMap
ENV_VAR_FROM_CM:
configMapKeyRef:
name: cm-name
key: "key_in_cm"
# Using a value from a secret
ENV_VAR_FROM_SECRET:
secretKeyRef:
name: secret-name
key: "key_in_secret"
*/}}
{{- define "oidc2fer.env.transformDict" -}}
{{- range $key, $value := . }}
- name: {{ $key | quote }}
{{- if $value | kindIs "map" }}
valueFrom: {{ $value | toYaml | nindent 4 }}
{{- else }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
{{- end }}
{{/*
oidc2fer env vars
*/}}
{{- define "oidc2fer.common.env" -}}
{{- $topLevelScope := index . 0 -}}
{{- $workerScope := index . 1 -}}
{{- include "oidc2fer.env.transformDict" $workerScope.envVars -}}
{{- end }}
{{/*
Common labels
@@ -1,4 +1,3 @@
{{- $envVars := include "oidc2fer.common.env" (list . .Values.satosa) -}}
{{- $fullName := include "oidc2fer.satosa.fullname" . -}}
{{- $component := "satosa" -}}
apiVersion: apps/v1
@@ -42,10 +41,9 @@ spec:
args:
{{- toYaml . | nindent 12 }}
{{- end }}
env:
{{- if $envVars}}
{{- $envVars | indent 12 }}
{{- end }}
{{- with .Values.satosa.env }}
env: {{ toJson . }}
{{- end }}
{{- with .Values.satosa.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
@@ -1,4 +1,3 @@
{{- $envVars := include "oidc2fer.common.env" (list . .Values.satosa) -}}
{{- $fullName := include "oidc2fer.satosa.fullname" . -}}
{{- $component := "satosa" -}}
apiVersion: v1
+2 -13
View File
@@ -21,10 +21,6 @@ image:
nameOverride: ""
fullnameOverride: ""
## @skip commonEnvVars
commonEnvVars: &commonEnvVars
<<: []
## @param ingress.enabled whether to enable the Ingress or not
## @param ingress.className IngressClass to use for the Ingress
## @param ingress.host Host for the Ingress
@@ -79,15 +75,8 @@ satosa:
## @param satosa.securityContext Configure satosa Pod security context
securityContext: null
## @param satosa.envVars Configure satosa container environment variables
## @extra satosa.envVars.BY_VALUE Example environment variable by setting value directly
## @extra satosa.envVars.FROM_CONFIGMAP.configMapKeyRef.name Name of a ConfigMap when configuring env vars from a ConfigMap
## @extra satosa.envVars.FROM_CONFIGMAP.configMapKeyRef.key Key within a ConfigMap when configuring env vars from a ConfigMap
## @extra satosa.envVars.FROM_SECRET.secretKeyRef.name Name of a Secret when configuring env vars from a Secret
## @extra satosa.envVars.FROM_SECRET.secretKeyRef.key Key within a Secret when configuring env vars from a Secret
## @skip satosa.envVars
envVars:
<<: *commonEnvVars
## @param satosa.env Configure satosa container environment variables
env: []
## @param satosa.podAnnotations Annotations to add to the satosa Pod
podAnnotations: {}
+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
+15 -18
View File
@@ -11,47 +11,44 @@ version = "0.1.0"
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.14",
]
description = "An application to handle contacts and teams."
description = "A gateway from RENATER's FER to ProConnect's OIDC provider, built on top of SATOSA."
keywords = ["OIDC", "SAML", "Shibboleth", "FER", "RENATER"]
license = { file = "LICENSE" }
readme = "README.md"
requires-python = ">=3.11"
requires-python = ">=3.14"
dependencies = [
"SATOSA==8.5.1",
"gunicorn==22.0.0",
"redis==5.0.4",
"JSON-log-formatter==1.0",
"WhiteNoise==6.7.0",
"gunicorn==25.1.0",
"JSON-log-formatter==1.1.1",
"WhiteNoise==6.12.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 = [
"pylint==3.1.0",
"pytest-cov==4.1.0",
"pytest==8.0.2",
"ruff==0.2.2",
"pytest-playwright==0.4.4",
"pytest==9.0.2",
"ruff==0.15.4",
"pytest-playwright==0.7.2",
]
[tool.setuptools]
packages = { find = { where = ["."], exclude = ["tests"] } }
zip-safe = true
[tool.distutils.bdist_wheel]
universal = true
[tool.ruff]
exclude = [
".git",
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env python
"""Setup file for the oidc2fer module. All configuration stands in the setup.cfg file."""
# coding: utf-8
from setuptools import setup
setup()
@@ -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
+50 -7
View File
@@ -1,5 +1,9 @@
import concurrent.futures
import json
import logging
import os
import time
import urllib.request
import pytest
from playwright.sync_api import Browser, Page, expect
@@ -20,6 +24,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()
@@ -31,7 +36,7 @@ def oidc_to_renater(
expected_given_name="Georges",
expected_usual_name="Grospieds",
):
page.goto("https://oidc-test-client.traefik.me")
page.goto("https://oidc-test-client.127.0.0.1.nip.io")
renater_wayf(page)
renater_test_idp(page, login=login)
@@ -40,6 +45,7 @@ def oidc_to_renater(
result = json.loads(text)
id_token = result["access_token_response"]["id_token"]
access_token = result["access_token_response"]["access_token"]
assert {"acr": "eidas1"}.items() <= id_token.items()
userinfo = result["userinfo"]
assert {
@@ -48,8 +54,9 @@ 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
return id_token, access_token
@pytest.mark.skipif(
@@ -57,18 +64,53 @@ def oidc_to_renater(
)
def test_oidc_to_renater_keeps_sub(browser: Browser):
with browser.new_context().new_page() as page:
id_token1 = oidc_to_renater(page)
id_token1, _ = oidc_to_renater(page)
with browser.new_context().new_page() as page:
id_token2 = oidc_to_renater(page)
id_token2, _ = oidc_to_renater(page)
assert id_token1["sub"] == id_token2["sub"]
@pytest.mark.skipif(
"BENCH_E2E" not in os.environ, reason="Benchmark runs only if requested"
)
def test_benchmark_userinfo(browser: Browser):
with browser.new_context().new_page() as page:
_, access_token = oidc_to_renater(page)
request_count = int(os.environ.get("BENCH_E2E_N", "100"))
client_count = int(os.environ.get("BENCH_E2E_P", "2"))
start = time.time()
def make_request():
return urllib.request.urlopen(
urllib.request.Request(
"https://oidc2fer.127.0.0.1.nip.io/OIDC/userinfo",
headers={"Authorization": f"Bearer {access_token}"},
)
)
with concurrent.futures.ThreadPoolExecutor(max_workers=client_count) as executor:
futures = []
for _ in range(request_count):
futures.append(executor.submit(make_request))
for future in concurrent.futures.as_completed(futures):
with future.result() as resp:
assert resp.status == 200
end = time.time()
logging.info(
"Average userinfo request time with %d parallel requests: \
%.2f seconds",
client_count,
(end - start) / request_count,
)
@pytest.mark.skipif(
"TEST_E2E" not in os.environ, reason="Depends on app running locally"
)
def test_oidc_to_renater_student_not_allowed(page: Page):
page.goto("https://oidc-test-client.traefik.me")
page.goto("https://oidc-test-client.127.0.0.1.nip.io")
renater_wayf(page)
renater_test_idp(page, login="etudiant1")
@@ -101,6 +143,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,12 +168,12 @@ 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(
"TEST_E2E" not in os.environ, reason="Depends on app running locally"
)
def test_serve_static_assets(page: Page):
page.goto("https://satosa.traefik.me/images/logo.svg")
page.goto("https://oidc2fer.127.0.0.1.nip.io/images/logo.svg")
expect(page.locator("svg")).to_be_visible()
+14 -5
View File
@@ -26,7 +26,8 @@ fi
# https://github.com/kubernetes-sigs/kind/issues/2875
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
cat <<EOF | kind create cluster --config=-
kind --name=oidc2fer delete cluster || true
cat <<EOF | kind --name=oidc2fer create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
@@ -35,7 +36,6 @@ containerdConfigPatches:
config_path = "/etc/containerd/certs.d"
nodes:
- role: control-plane
image: kindest/node:v1.27.3
kubeadmConfigPatches:
- |
kind: InitConfiguration
@@ -50,9 +50,7 @@ nodes:
hostPort: 443
protocol: TCP
- role: worker
image: kindest/node:v1.27.3
- role: worker
image: kindest/node:v1.27.3
EOF
# 3. Add the registry config to the nodes
@@ -64,7 +62,7 @@ EOF
# We want a consistent name that works from both ends, so we tell containerd to
# alias localhost:${reg_port} to the registry container when pulling images
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
for node in $(kind get nodes); do
for node in $(kind --name=oidc2fer get nodes); do
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
@@ -91,6 +89,17 @@ data:
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
# Patch the CoreDNS configmap to rewrite requests for *.127.0.0.1.nip.io to the Ingress Controller service
kubectl -n kube-system get configmap coredns -o yaml |
yq '.data.Corefile |= (
trim
| split("\n")
| .[-1] = " rewrite name regex .*\\.127\\.0\\.0\\.1\\.nip\\.io ingress-nginx-controller.ingress-nginx.svc.cluster.local answer auto\n"
+ .[-1]
| join("\n")
)' |
kubectl replace -f -
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl -n ingress-nginx create secret tls mkcert --key /tmp/127.0.0.1.nip.io+1-key.pem --cert /tmp/127.0.0.1.nip.io+1.pem
kubectl -n ingress-nginx patch deployments.apps ingress-nginx-controller --type 'json' -p '[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value":"--default-ssl-certificate=ingress-nginx/mkcert"}]'