Thème de connexion Keycloak à l'identité Alliance Boréale

Thème login alliance-boreale (parent=keycloak + overlay CSS) reprenant
l'identité du site : ciel nocturne aurore, carte glassmorphism, logo étoile
(favicon du site), bouton dégradé aurore, police système (souveraineté).
Déployé dans themes/, appliqué au realm via kcadm loginTheme (idempotent).

Prouvé : page de login charge alliance.css (200) + logo.svg (200),
loginTheme=alliance-boreale actif.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-07-03 23:42:57 -04:00
parent 1f1b722a00
commit dd10ae8010
6 changed files with 218 additions and 0 deletions

View file

@ -3,6 +3,15 @@
## 2026-07-03
### Ajouté
- **Thème de connexion Keycloak à l'identité Alliance Boréale.** Thème de login `alliance-boreale`
(`roles/serveur_keycloak/files/themes/`, `parent=keycloak` + overlay CSS) reprenant l'identité du
site de l'Alliance (extraite de `site-alliance-boreale`) : **ciel nocturne aurore** (`#05060f`/
`#0a0d24` + dégradés), **carte glassmorphism**, **logo étoile aurore** (le `favicon.svg` du site),
**bouton dégradé aurore** (teal→cyan, pilule), liens cyan, **police système** (souveraineté, zéro
dépendance externe). Déployé dans `{{ keycloak_home }}/themes/`, appliqué au realm via
`kcadm ... -s loginTheme` (var `serveur_keycloak_login_theme`, idempotent), Keycloak rechargé
(`flush_handlers` avant la config realm). **Prouvé** : la page de login charge `alliance.css`
(HTTP 200) + le `logo.svg` (200), `loginTheme=alliance-boreale` actif sur `chezlepro`.
- **Soumission courriel `:587` interne (authentifiée) — la boucle souveraine est bouclée.**
Postfix (`edge-mta`) sert la **soumission `:587`** (bloc `master.cf` : STARTTLS requis, `SMTP AUTH`,
seuls les authentifiés relaient) ; l'auth SASL est **déléguée à Dovecot** (`infra-mail`, passdb LDAP

View file

@ -25,6 +25,8 @@ serveur_keycloak_admin_password: "{{ vault_keycloak_admin | default('') }}" # r
# Requiert client_pki sur ce nœud (racine step_ca dans le bundle système pour LDAPS).
serveur_keycloak_ldap_federation: true
serveur_keycloak_realm: "chezlepro"
# Thème de login du realm (déployé depuis files/themes/). Vide = thème Keycloak par défaut.
serveur_keycloak_login_theme: ""
serveur_keycloak_ldap_nom: "openldap"
# Connexion à l'annuaire (url, users_dn, bind_dn, bind_password) : fournie par le rôle
# partagé resoudre_annuaire (voir tasks/main.yml « Adopter la connexion annuaire »).

View file

@ -0,0 +1,121 @@
/* =========================================================================
Alliance Boréale thème de connexion Keycloak
Identité : aurore boréale · étoiles · constellation · ciel nocturne souverain.
Police système (souveraineté, aucune dépendance externe).
========================================================================= */
:root {
--bg: #05060f;
--bg-2: #0a0d24;
--ink: #e9ecff;
--ink-dim: #99a1c9;
--border: rgba(255, 255, 255, 0.10);
--panel: rgba(255, 255, 255, 0.05);
--aurora-teal: #4fe3c1;
--aurora-cyan: #56c2ff;
--aurora-violet: #a98bff;
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Noto Sans", "Helvetica Neue", Arial, sans-serif;
}
/* ---------- Ciel nocturne : aurore en fond ---------- */
html { height: 100%; }
body.login-pf,
body {
height: 100%;
font-family: var(--font);
color: var(--ink);
background:
radial-gradient(1200px 700px at 80% -10%, #131a44 0%, transparent 60%),
radial-gradient(900px 600px at 10% 0%, #0e1640 0%, transparent 55%),
linear-gradient(180deg, var(--bg-2) 0%, var(--bg) 70%) fixed;
}
.login-pf-page { padding-top: 40px; }
/* ---------- En-tête + logo étoile aurore ---------- */
#kc-header,
#kc-header-wrapper {
color: var(--ink);
font-size: 1.6rem;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: none;
}
.login-pf-page .login-pf-header {
text-align: center;
}
.login-pf-page .login-pf-header::before {
content: "";
display: block;
width: 84px;
height: 84px;
margin: 0 auto 18px;
background: url("../img/logo.svg") center / contain no-repeat;
filter: drop-shadow(0 0 22px rgba(86, 194, 255, 0.5));
}
/* ---------- Carte de connexion (glassmorphism) ---------- */
.card-pf {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 16px;
box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
padding: 2rem 2.2rem 2.4rem;
}
/* ---------- Titres, libellés, texte ---------- */
#kc-page-title,
.login-pf-page .login-pf-signup a,
label,
.control-label,
#kc-form-options,
.login-pf-page label { color: var(--ink); }
.login-pf-page .login-pf-header h1 { color: var(--ink); }
p, .instruction, #kc-info-message { color: var(--ink-dim); }
/* ---------- Champs ---------- */
input.form-control,
.pf-c-form-control,
.form-control {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.14);
color: var(--ink);
border-radius: 10px;
}
input.form-control:focus,
.form-control:focus {
border-color: var(--aurora-cyan);
box-shadow: 0 0 0 3px rgba(86, 194, 255, 0.25);
background: rgba(255, 255, 255, 0.09);
}
input.form-control::placeholder { color: var(--ink-dim); }
/* ---------- Bouton primaire : ruban d'aurore ---------- */
.btn-primary,
input.btn-primary,
.pf-c-button.pf-m-primary,
#kc-login {
background: linear-gradient(100deg, var(--aurora-teal), var(--aurora-cyan)) !important;
color: #04121a !important;
border: none !important;
border-radius: 999px !important;
font-weight: 600 !important;
box-shadow: 0 10px 30px rgba(79, 227, 193, 0.28);
transition: transform 0.15s ease, box-shadow 0.2s ease;
}
.btn-primary:hover,
#kc-login:hover {
transform: translateY(-2px);
box-shadow: 0 14px 38px rgba(86, 194, 255, 0.4);
}
/* ---------- Liens ---------- */
a, a:visited { color: var(--aurora-cyan); }
a:hover { color: var(--aurora-violet); }
/* ---------- Alertes ---------- */
.alert { border-radius: 12px; border: 1px solid var(--border); }
/* ---------- Bas de page ---------- */
#kc-info, #kc-info-wrapper { color: var(--ink-dim); }

View file

@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="Alliance Boréale">
<defs>
<radialGradient id="sky" cx="50%" cy="36%" r="75%">
<stop offset="0%" stop-color="#10184a"/>
<stop offset="100%" stop-color="#05060f"/>
</radialGradient>
<linearGradient id="aurora" x1="0" y1="1" x2="1" y2="0">
<stop offset="0%" stop-color="#2ec18f"/>
<stop offset="45%" stop-color="#56c2ff"/>
<stop offset="100%" stop-color="#a98bff"/>
</linearGradient>
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#bfe9ff"/>
<stop offset="100%" stop-color="#bfe9ff" stop-opacity="0"/>
</radialGradient>
<radialGradient id="star" cx="50%" cy="45%" r="60%">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="100%" stop-color="#d6ecff"/>
</radialGradient>
</defs>
<!-- ciel nocturne -->
<circle cx="16" cy="16" r="16" fill="url(#sky)"/>
<!-- ruban d'aurore -->
<path d="M3 21 C 9 16, 13 23, 18 18 C 22 14, 26 17, 30 13"
fill="none" stroke="url(#aurora)" stroke-width="2.6"
stroke-linecap="round" opacity="0.85"/>
<!-- petites étoiles (constellation) -->
<circle cx="7" cy="9" r="0.9" fill="#cfe6ff"/>
<circle cx="24" cy="8" r="1.1" fill="#ffffff"/>
<circle cx="26" cy="22" r="0.8" fill="#bfe9ff"/>
<circle cx="9" cy="25" r="0.7" fill="#cfe6ff"/>
<!-- halo de l'étoile centrale -->
<circle cx="16" cy="15" r="9" fill="url(#glow)" opacity="0.55"/>
<!-- étoile centrale à quatre branches -->
<path d="M16 5
C 16.9 12.4, 17.6 13.1, 25 14
C 17.6 14.9, 16.9 15.6, 16 23
C 15.1 15.6, 14.4 14.9, 7 14
C 14.4 13.1, 15.1 12.4, 16 5 Z"
fill="url(#star)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,3 @@
parent=keycloak
import=common/keycloak
styles=css/login.css css/alliance.css

View file

@ -117,6 +117,16 @@
mode: "0644"
notify: Redemarrer keycloak
- name: Deployer les themes Set-OPS (identite Alliance Boreale)
ansible.builtin.copy:
src: themes/
dest: "{{ serveur_keycloak_home }}/themes/"
owner: "{{ serveur_keycloak_utilisateur }}"
group: "{{ serveur_keycloak_utilisateur }}"
mode: "0644"
directory_mode: "0755"
notify: Redemarrer keycloak
- name: Activer et demarrer keycloak
when: not ansible_check_mode
ansible.builtin.systemd:
@ -125,6 +135,9 @@
state: started
daemon_reload: true
- name: Appliquer le theme (recharger Keycloak avant la config du realm)
ansible.builtin.meta: flush_handlers
- name: Configurer la federation LDAP (realm + provider OpenLDAP)
ansible.builtin.include_tasks: federation-ldap.yml
when: serveur_keycloak_ldap_federation | bool
@ -132,3 +145,27 @@
- name: Enregistrer les clients OIDC applicatifs
ansible.builtin.include_tasks: clients-oidc.yml
when: serveur_keycloak_clients | length > 0
- name: Definir le theme de login du realm (identite Alliance Boreale)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -euo pipefail
KC={{ serveur_keycloak_home }}/bin/kcadm.sh
"$KC" config credentials --server http://localhost:8080 --realm master \
--user {{ serveur_keycloak_admin_user }} --password "$KC_ADMIN_PW" >/dev/null
if "$KC" get realms/{{ serveur_keycloak_realm }} --fields loginTheme 2>/dev/null \
| grep -q '"{{ serveur_keycloak_login_theme }}"'; then
echo SETOPS_OK
else
"$KC" update realms/{{ serveur_keycloak_realm }} \
-s loginTheme={{ serveur_keycloak_login_theme }} >/dev/null
echo SETOPS_CHANGED
fi
environment:
KC_ADMIN_PW: "{{ serveur_keycloak_admin_password }}"
register: serveur_keycloak_theme_res
changed_when: "'SETOPS_CHANGED' in serveur_keycloak_theme_res.stdout"
when:
- serveur_keycloak_login_theme | length > 0
- not ansible_check_mode