1 <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <html xmlns
="http://www.w3.org/1999/xhtml" xml
:lang
="fr" lang
="fr">
4 <title
>ImmaeEu Account
</title
>
5 <meta http
-equiv
="Content-Type" content
="text/html; charset=utf-8"/>
6 <meta name
="viewport" content
="width=device-width, initial-scale=1" />
7 <link rel
="stylesheet" href
="https://assets.immae.eu/skeleton/2.0.4/skeleton.min.css" integrity
="sha256-2YQRJMXD7pIAPHiXr0s+vlRWA7GYJEK0ARns7k2sbHY=" crossorigin
="anonymous" />
8 <style type
="text/css">
10 font
-family
: Verdana
,Arial
,Courier
New;
13 table
#ssh_keys_list textarea {
17 table
#ssh_keys_list tbody tr.sshkeyrow {
20 table
#ssh_keys_list tbody tr.headrow th {
21 border
-bottom
: 0px
!important
;
22 padding
-bottom
: 0px
!important
;
24 table
#ssh_keys_list tbody tr.mainrow td:not(.delete-button) {
25 border
-bottom
: 0px
!important
;
26 padding
-bottom
: 0px
!important
;
28 table
#ssh_keys_list td.sshkey {
31 padding
-top
: 0px
!important
;
34 table
#ssh_keys_list td.comment {
41 <div
class="container">
42 <h1
>Gestion des clés SSH
</h1
>
49 // Liste des applications gérées
58 function checkSshKey($sshKey)
60 $exploded = explode(' ', $sshKey);
61 if (count($exploded) != 2) {
64 if (!in_array($exploded[0], array('ssh-rsa', 'ssh-ed25519'))) {
67 $decoded = base64_decode($exploded[1], true);
68 if ($decoded === FALSE) {
71 $decoded = preg_replace("/[^\w\-]/","", (string) $decoded);
72 if (substr($decoded, 0, strlen($exploded[0])) !== $exploded[0]) {
79 function isUserLogged()
81 return (isset($_SESSION["login"]));
84 function checkLogin($user, $password)
86 $server = "ldaps://ldap.immae.eu";
87 $con = ldap_connect($server);
88 ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION
, 3);
90 $user_dn = "uid=$user,ou=users,dc=immae,dc=eu";
92 if (ldap_bind($con, $user_dn, $password) === false) {
95 $_SESSION["user_dn"] = $user_dn;
97 $user_search = ldap_search($con,"dc=immae,dc=eu","(uid=$user)");
98 $auth_entry = ldap_first_entry($con, $user_search);
103 function connectPg() {
104 foreach(["PGUSER", "PGPASSWORD", "PGDATABASE", "PGHOST"] as $k) {
105 if (isset($_SERVER[$k]) && !isset($_ENV[$k])) {
106 putenv("${k}=" . $_SERVER[$k]);
109 $con = pg_connect("");
111 die("database access error");
119 if (!isset($_SESSION["login"]))
122 $result = pg_query_params($pg, "SELECT id,key,array_to_json(usage) as usage,comment FROM ldap_users_ssh_keys WHERE realm = 'immae' AND login = $1 ORDER BY id", array($_SESSION["login"]));
124 die("database access error");
127 while ($row = pg_fetch_assoc($result)) {
130 'apps' => json_decode($row["usage"]),
131 'public_key' => $row["key"],
132 'comment' => $row["comment"],
140 function saveKeys($keys)
142 if (!isset($_SESSION["login"])) {
146 $existingIds = pg_fetch_all_columns(pg_query_params($pg, "SELECT id FROM ldap_users_ssh_keys WHERE realm = 'immae' AND login = $1", array($_SESSION["login
"])));
147 foreach ($keys as $key) {
148 if (isset($key["id
"])) {
149 unset($existingIds[array_search($key["id
"],$existingIds)]);
150 pg_query_params($pg, "UPDATE ldap_users_ssh_keys SET key
= $2, usage
= ARRAY(SELECT
* FROM
json_array_elements_text($3))::ldap_users_ssh_key_usage
[], comment
= $4 WHERE id
= $5 AND login
= $1 AND realm
= 'immae'", array($_SESSION["login
"], $key["public_key
"], json_encode($key["apps
"]), $key["comment
"], $key["id
"]));
152 pg_query_params($pg, "INSERT INTO
ldap_users_ssh_keys (login
,realm
,key
,usage
,comment
) values ($1,'immae',$2,ARRAY(SELECT
* FROM
json_array_elements_text($3))::ldap_users_ssh_key_usage
[],$4)", array($_SESSION["login
"], $key["public_key
"], json_encode($key["apps
"]), $key["comment
"]));
155 foreach ($existingIds as $removedKeyId) {
156 pg_query_params($pg, "DELETE FROM ldap_users_ssh_keys WHERE login
= $1 AND realm
= 'immae' AND id
= $2", array($_SESSION["login"], $removedKeyId));
162 if (isset($_POST['deconnexion'])) {
166 if (isset($_POST['sauvegarder'])) {
170 foreach($_POST['keys'] as $id => $key) {
171 $editedKeys[$id] = $key;
172 if (!checkSshKey($key['public_key'])) {
173 $editedKeys[$id]['error'] = true;
177 if (!isset($key['apps'])) {
178 $editedKeys[$id]['apps'] = $key['apps'] = [];
181 foreach ($key['apps'] as $app) {
182 if (!in_array($app, apps
)) {
187 if (!isset($editedKeys[$id]['error']) || $editedKeys[$id]['error'] !== true) {
188 $keysToSave[] = $key;
193 $successSave = saveKeys($keysToSave);
198 if (isset($_POST['login'])) {
199 if (empty($_POST['username']) || empty($_POST['password'])) {
200 $loginErrors = "Le nom d'utilisateur et le mot de passe sont requis.";
201 } elseif (!checkLogin($_POST['username'], $_POST['password'])) {
202 $loginErrors = "Identifiants incorrects.";
204 $_SESSION['login'] = $_POST['username'];
208 if (isUserLogged()) :
209 $keys = isset($editedKeys) ? $editedKeys : getKeys();
211 <p
>Connecté en tant que
<b
><?= $_SESSION['login']; ?></b
></p
>
214 <input type
="submit" name
="deconnexion" value
="Déconnexion">
217 <?php
if (isset($successSave) && $successSave === true) : ?>
218 <p style
="color: green;">Clés enregistrées avec succès
.</p
>
222 <table id
="ssh_keys_list">
225 foreach ($keys as $id => $sshKey) :
229 <?php
foreach (apps
as $app) : ?>
235 <td
class="comment"><textarea name
="keys[<?= $id ?>][comment]"><?= $sshKey['comment'] ?></textarea
></td
>
237 foreach (apps
as $app) :
238 $checked = in_array($app, $sshKey['apps']);
240 <td
><input type
="checkbox" name
="keys[<?= $id ?>][apps][]" value
="<?= $app ?>"<?= $checked ? ' checked' : '' ?>></td
>
242 <td
class="delete-button" rowspan
="2"><input type
="hidden" name
="keys[<?= $id ?>][id]" value
="<?= $sshKey["id
"] ?>"><button
class="delete">Suppr
.</button
></td
>
244 <tr
class="sshkeyrow">
245 <td colspan
="<?php echo 1+count(apps); ?>" class="sshkey"><textarea name
="keys[<?= $id ?>][public_key]" <?php
if (isset($sshKey['error']) && $sshKey['error'] === true) :?>style
="color: red"<?php
endif; ?>><?= $sshKey['public_key'] ?></textarea
></td
>
253 <button id
="add">Ajouter
</button
>
257 <input type
="submit" value
="Sauvegarder" name
="sauvegarder">
260 function deleteLine(element
) {
261 element
.addEventListener('click', function(e
) {
263 e
.target
.closest('tr').nextElementSibling
.remove();
264 e
.target
.closest('tr').previousElementSibling
.remove();
265 e
.target
.closest('tr').remove();
269 var suppr
= document
.getElementsByClassName('delete');
270 var add
= document
.getElementById('add');
271 var list = document
.querySelector('#ssh_keys_list > tbody');
273 for (var i
= 0; i
< suppr
.length
; i++
) {
274 deleteLine(suppr
[i
]);
277 add
.addEventListener('click', function (e
) {
284 <?php
foreach (apps
as $app) : ?>
290 <td
class="comment"><textarea name
="keys[${i}][comment]"></textarea
></td
>
295 foreach (apps
as $app) :
297 newLine +
= `
<td
><input type
="checkbox" name
="keys[${i}][apps][]" value
="<?= $app ?>"></td
>`
;
300 newLine +
= `
<td
class="delete-button" rowspan
="2"><button
class="delete" id
="delete-${i}">Suppr
.</button
></td
>
303 newLine +
= `
<tr
class="sshkeyrow">
304 <td colspan
="<?php echo 1+count(apps); ?>" class="sshkey"><textarea name
="keys[${i}][public_key]"></textarea
></td
>
308 list.insertAdjacentHTML('beforeend', newLine
);
310 deleteLine(document
.getElementById("delete-" + i
));
317 <form action
="" method
="post">
321 if (!empty($loginErrors)):
323 <p style
="color: red;"><?= $loginErrors; ?></p
>
328 <label
for="username">Utilisateur
:</label
>
329 <input type
="text" id
="username" name
="username"/>
331 <label
for="password">Mot de passe
:</label
>
332 <input type
="password" id
="password" name
="password"/>
334 <input type
="submit" value
="OK" name
="login" />