🧑‍💻(demo) configure people as an IdP

This configures local environment to test login through people:
- Keycloak configuration of the IdP (people)
- Add Keycloak Application in people

The only user who can login for now is "admin".
This commit is contained in:
Quentin BEY
2025-01-14 11:48:55 +01:00
committed by BEY Quentin
parent db6cdadd72
commit 68550f6f7e
5 changed files with 187 additions and 7 deletions

View File

@@ -59,6 +59,35 @@ cmd_button('Migrate db',
text='Run database migration',
)
# Command to reset DB
reset_db = '''
set -eu
# get k8s pod name from tilt resource name
POD_NAME="$(tilt get kubernetesdiscovery desk-backend -ojsonpath='{.status.pods[0].name}')"
kubectl -n desk exec "$POD_NAME" -- python manage.py flush --no-input
kubectl -n desk exec "$POD_NAME" -- python manage.py createsuperuser --username admin@example.com --password admin
'''
cmd_button('Reset DB',
argv=['sh', '-c', reset_db],
resource='desk-backend',
icon_name='developer_board',
text='Reset DB',
)
# Command to create demo data
populate_people_with_demo_data = '''
set -eu
# get k8s pod name from tilt resource name
POD_NAME="$(tilt get kubernetesdiscovery desk-backend -ojsonpath='{.status.pods[0].name}')"
kubectl -n desk exec "$POD_NAME" -- python manage.py create_demo --force
'''
cmd_button('Populate with demo data',
argv=['sh', '-c', populate_people_with_demo_data],
resource='desk-backend',
icon_name='developer_board',
text='Populate with demo data',
)
# Command to created domain/users/access from people to dimail
populate_dimail_from_people = '''
set -eu

View File

@@ -129,6 +129,8 @@ services:
image: quay.io/keycloak/keycloak:20.0.1
volumes:
- ./docker/auth/realm.json:/opt/keycloak/data/import/realm.json
extra_hosts:
- "host.docker.internal:host-gateway"
command:
- start-dev
- --features=preview

View File

@@ -1652,8 +1652,130 @@
"enabledEventTypes": [],
"adminEventsEnabled": false,
"adminEventsDetailsEnabled": false,
"identityProviders": [],
"identityProviderMappers": [],
"identityProviders": [
{
"alias": "oidc-people-local",
"displayName": "People OIDC (local)",
"internalId": "47aa6d7c-8ac5-4178-934e-66f78e510ee4",
"providerId": "oidc",
"enabled": true,
"updateProfileFirstLoginMode": "on",
"trustEmail": false,
"storeToken": false,
"addReadTokenRoleOnCreate": false,
"authenticateByDefault": false,
"linkOnly": false,
"firstBrokerLoginFlowAlias": "first broker login",
"config": {
"hideOnLoginPage": "false",
"userInfoUrl": "http://app-dev:8000/o/userinfo/",
"validateSignature": "true",
"acceptsPromptNoneForwardFromClient": "false",
"clientId": "people-idp",
"tokenUrl": "http://app-dev:8000/o/token/",
"uiLocales": "false",
"jwksUrl": "http://app-dev:8000/o/.well-known/jwks.json",
"backchannelSupported": "false",
"issuer": "http://app-dev:8000/o",
"useJwksUrl": "true",
"loginHint": "true",
"pkceEnabled": "true",
"pkceMethod": "S256",
"authorizationUrl": "http://localhost:8071/o/authorize/",
"clientAuthMethod": "client_secret_post",
"disableUserInfo": "false",
"syncMode": "IMPORT",
"clientSecret": "local-tests-only",
"passMaxAge": "false",
"defaultScope": "openid given_name usual_name email siret",
"allowedClockSkew": "0"
}
}
],
"identityProviderMappers": [
{
"id": "e55dc88c-7bb5-46fb-95ad-1df701a96282",
"name": "Sub",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "oidc-username-idp-mapper",
"config": {
"template": "${CLAIM.sub}",
"are.claim.values.regex": "false",
"claims": "[{\"key\":\"\",\"value\":\"\"}]",
"syncMode": "FORCE",
"attributes": "[]",
"target": "BROKER_ID"
}
},
{
"id": "7e489676-8cba-49e4-aa1e-dcd1462d33f7",
"name": "given_name",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "hardcoded-attribute-idp-mapper",
"config": {
"claims": "[{\"key\":\"\",\"value\":\"\"}]",
"syncMode": "FORCE",
"are.claim.values.regex": "false",
"attributes": "[]",
"attribute": "firstName"
}
},
{
"id": "30b6b3bc-5738-4936-bf88-c540b8805998",
"name": "usual_name",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "oidc-user-attribute-idp-mapper",
"config": {
"template": "${ALIAS}.${CLAIM.preferred_username}",
"are.claim.values.regex": "false",
"claims": "[{\"key\":\"profile\",\"value\":\"lastName\"}]",
"syncMode": "FORCE",
"claim": "profile",
"user.attribute": "lastName",
"attributes": "[]",
"target": "LOCAL"
}
},
{
"id": "b67caa26-4571-4cfe-9c15-68e022645fc5",
"name": "Username",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "oidc-username-idp-mapper",
"config": {
"template": "${CLAIM.email | lowercase}",
"are.claim.values.regex": "false",
"claims": "[{\"key\":\"\",\"value\":\"\"}]",
"syncMode": "FORCE",
"attributes": "[]",
"target": "BROKER_USERNAME"
}
},
{
"id": "4eef21ce-b5f7-4753-bd58-4e50eb2b5f31",
"name": "Email",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "oidc-user-attribute-idp-mapper",
"config": {
"are.claim.values.regex": "false",
"claims": "[{\"key\":\"\",\"value\":\"\"}]",
"syncMode": "FORCE",
"claim": "email",
"user.attribute": "email",
"attributes": "[]"
}
},
{
"id": "084cdd0e-0794-4388-8474-84c9a7c1b9c8",
"name": "siret",
"identityProviderAlias": "oidc-people-local",
"identityProviderMapper": "oidc-user-attribute-idp-mapper",
"config": {
"syncMode": "FORCE",
"claim": "siret",
"user.attribute": "siret"
}
}
],
"components": {
"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
{
@@ -2195,7 +2317,7 @@
"authenticatorConfig": "review profile config",
"authenticator": "idp-review-profile",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"requirement": "DISABLED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false

View File

@@ -13,6 +13,7 @@ from django.core.management.base import BaseCommand, CommandError
from django.utils.text import slugify
from faker import Faker
from oauth2_provider.models import Application
from treebeard.mp_tree import MP_Node
from core import models
@@ -133,6 +134,25 @@ class Timeit:
return elapsed_time
def create_oidc_people_idp_client():
"""Configure the OIDC client for the People Identity Provider if missing."""
try:
Application.objects.get(client_id="people-idp")
except Application.DoesNotExist:
application = Application(
client_id="people-idp",
client_secret="local-tests-only",
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
name="People Identity Provider",
algorithm=Application.RS256_ALGORITHM,
redirect_uris="http://localhost:8083/realms/people/broker/oidc-people-local/endpoint",
skip_authorization=True,
)
application.clean()
application.save()
def create_demo(stdout): # pylint: disable=too-many-locals
"""
Create a database with demo data for developers to work in a realistic environment.
@@ -315,6 +335,10 @@ def create_demo(stdout): # pylint: disable=too-many-locals
queue.flush()
# OIDC configuration
if settings.OAUTH2_PROVIDER.get("OIDC_ENABLED", False):
create_oidc_people_idp_client()
class Command(BaseCommand):
"""A management command to create a demo database."""

View File

@@ -3,7 +3,6 @@
from unittest import mock
from django.core.management import call_command
from django.test import override_settings
import pytest
@@ -11,6 +10,7 @@ from core import models
from demo import defaults
from mailbox_manager import models as mailbox_models
from people.settings import Base
pytestmark = pytest.mark.django_db
@@ -23,10 +23,13 @@ TEST_NB_OBJECTS = {
}
@override_settings(DEBUG=True)
@mock.patch.dict(defaults.NB_OBJECTS, TEST_NB_OBJECTS)
def test_commands_create_demo():
def test_commands_create_demo(settings):
"""The create_demo management command should create objects as expected."""
settings.DEBUG = True
settings.OAUTH2_PROVIDER["OIDC_ENABLED"] = True
settings.OAUTH2_PROVIDER["OIDC_RSA_PRIVATE_KEY"] = Base.generate_temporary_rsa_key()
call_command("create_demo")
# Monique Test, Jeanne Test and Jean Something (quick fix for e2e)
@@ -37,7 +40,7 @@ def test_commands_create_demo():
assert models.Team.objects.count() == TEST_NB_OBJECTS["teams"]
assert models.TeamAccess.objects.count() >= TEST_NB_OBJECTS["teams"]
assert mailbox_models.MailDomain.objects.count() == TEST_NB_OBJECTS["domains"]
assert mailbox_models.MailDomain.objects.count() == TEST_NB_OBJECTS["domains"] + 1
# 3 domain access for each user with domain rights
# 3 x 3 domain access for each user with both rights