help: remove section about API accesses (now written online) (#75607)
This commit is contained in:
parent
00222aae84
commit
42c904394f
|
@ -1,317 +0,0 @@
|
|||
<page xmlns="http://projectmallard.org/1.0/"
|
||||
type="topic" id="api-auth" xml:lang="fr">
|
||||
|
||||
<info>
|
||||
<link type="guide" xref="index#api" />
|
||||
<revision docversion="0.1" date="2013-01-04" status="draft"/>
|
||||
<revision docversion="0.2" date="2015-12-18" status="draft"/>
|
||||
<credit type="author">
|
||||
<name>Frédéric Péters</name>
|
||||
<email>fpeters@entrouvert.com</email>
|
||||
</credit>
|
||||
<desc>Accès aux API, identifiants et clé d’utilisation, utilisateurs, signature, etc.</desc>
|
||||
|
||||
</info>
|
||||
|
||||
<title>Authentification</title>
|
||||
|
||||
<section>
|
||||
<title>Gestion des accès aux API</title>
|
||||
|
||||
<p>
|
||||
La création d’accès aux API se fait dans l’espace de paramétrage, dans la
|
||||
section « Sécurité », en suivant le lien « Accès aux API ». Le bouton « Nouvel
|
||||
accès aux API » permet d’ajouter un accès, et il faut indiquer :
|
||||
</p>
|
||||
|
||||
<list>
|
||||
|
||||
<item><p>Nom : le nom choisi pour l’accès, qui sera affiché dans la page des
|
||||
accès ;</p></item>
|
||||
|
||||
<item><p>Description : pour se rappeler de l’usage prévu pour cet
|
||||
accès ;</p></item>
|
||||
|
||||
<item><p>Identifiant d’accès : le nom de l’utilisateur à utiliser pour
|
||||
l’authentification HTTP Basic, ou le paramètre <code>orig</code> pour
|
||||
l’authentification par signature ;</p></item>
|
||||
|
||||
<item><p>Clé d’accès : le mot de passe pour l’authentification HTTP Basic de
|
||||
cet utilisateur, ou la clé partagée à utiliser pour l’authentification par
|
||||
signature ;</p></item>
|
||||
|
||||
<item><p>Rôles : liste des rôles automatiquement obtenus lorsque cet accès est
|
||||
utilisé. Par exemple, s’il s’agit de permettre de lister des demandes d’une
|
||||
certaine démarche, il faut indiquer un rôle qui permet de voir les demandes.
|
||||
Ce rôle est à déterminer selon le paramétrage du formulaire de la démarche
|
||||
et/ou de son workflow.</p></item>
|
||||
|
||||
</list>
|
||||
|
||||
<note><p>Il est conseillé de créer des «rôles techniques» dédiés aux API. Ces
|
||||
rôles ne sont jamais donnés à des utilisateurs de la plateforme, ils sont
|
||||
utilisés uniquement dans le paramétrage des accès. Typiquement une démarche est
|
||||
paramétrée pour qu’un certain rôle technique ait accès à ses demandes, et ce
|
||||
même rôle est indiqué dans l’accès aux API dédié.</p></note>
|
||||
|
||||
<section>
|
||||
<title>Définitions de l’usager concerné</title>
|
||||
|
||||
<p>
|
||||
Si l’authentification utilisée passe par un accès aux API qui ne donne pas de
|
||||
rôle spécifique, alors il faut indiquer dans la query-string un usager qui aura
|
||||
les rôles nécessaires.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
C'est aussi nécessaire pour les appels concernant un usager particulier, tel
|
||||
que la récupération de la liste de ses formulaires en cours.
|
||||
</p>
|
||||
|
||||
<p>L’usager est précisé en ajoutant dans la query string :</p>
|
||||
|
||||
<list>
|
||||
<item><p>soit un paramètre <code>email</code> pour trouver l’usager selon son
|
||||
adresse électronique</p></item>
|
||||
<item><p>soit un paramètre <code>NameID</code> pour trouver l’usager selon son
|
||||
NameID SAML.</p></item>
|
||||
</list>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Authentification simple HTTP Basic</title>
|
||||
|
||||
<p>
|
||||
Pour accéder aux API avec l’authentification HTTP Basic classique, il faut
|
||||
utiliser le nom d’utilisateur (identifiant d’accès) et le mot de passe (clé
|
||||
d’accès) de l’accès configuré ci-dessus.
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section>
|
||||
<title>Authentification par signature de l’URL</title>
|
||||
|
||||
<p>
|
||||
Un système d’authentification basé sur une signature ajoutée à la fin de l’URL
|
||||
est également disponible. Il peut être jugé plus sécurisé que
|
||||
l’authentification HTTP Basic, par ailleurs il assure une protection plus
|
||||
explicite contre le rejeu. Ce système est spécifique à Publik/w.c.s.
|
||||
</p>
|
||||
|
||||
<section id="req-security-shared-secret">
|
||||
<title>Signature des requêtes</title>
|
||||
|
||||
<p>
|
||||
La signature d’un appel aux API passe par une clé partagée à
|
||||
configurer des deux cotés de la liaison, la signature est du type HMAC;
|
||||
l’algorithme de hash à employer est passé en paramètre.
|
||||
</p>
|
||||
|
||||
<note><p>En ce qui concerne l’algorithme de hash, il est préconisé d’utiliser
|
||||
SHA-256 par respect du <link
|
||||
href="http://references.modernisation.gouv.fr/securite">Référentiel Général
|
||||
de Sécurité (RGS)</link>.</p></note>
|
||||
|
||||
<p>
|
||||
La signature est à calculer sur la query string encodée complète, en
|
||||
enlevant les paramètres terminaux <code>algo</code>, <code>timestamp</code>,
|
||||
<code>nonce</code>, <code>orig</code> et <code>signature</code> s’ils sont
|
||||
présents.</p>
|
||||
|
||||
<p>La formule de calcul de la signature est la suivante :</p>
|
||||
|
||||
<code>
|
||||
BASE64(HMAC-HASH(query_string+'algo=HASH&timestamp=' + timestamp + '&nonce=' + nonce '&orig=" + orig, clé))
|
||||
</code>
|
||||
|
||||
<list>
|
||||
|
||||
<item><p><code>timestamp</code> est la date dans la zone GMT au format ISO8601
|
||||
en se limitant à la précision des secondes (ex : 2012-04-04T12:34:00Z),
|
||||
</p></item>
|
||||
|
||||
<item><p><code>nonce</code> est un aléa, typiquement la réprésentation hexa
|
||||
d’un nombre pseudo-aléatoire de 128 bits,</p></item>
|
||||
|
||||
<item><p><code>orig</code> est une chaîne précisant l’émetteur de la
|
||||
requête,</p></item>
|
||||
|
||||
<item><p>algo est une chaîne représentant l’algorithme de hachage utilisé, sont
|
||||
définis : sha1, sha256, sha512 pour les trois algorithmes correspondant.
|
||||
L’utilisation d’une valeur différente n’est pas définie. L’algorithme sha256
|
||||
est préconisé.</p></item>
|
||||
|
||||
</list>
|
||||
|
||||
<p>
|
||||
La query string définitive est ainsi :
|
||||
</p>
|
||||
|
||||
<code>
|
||||
<var>qs_initial</var>&algo=<var>algo</var>&timestamp=<var>timestamp</var>&nonce=<var>nonce</var>&orig=<var>orig</var>&signature=<var>signature</var>
|
||||
</code>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Configuration des clés partagées</title>
|
||||
|
||||
<p>
|
||||
La définition des clés se fait lors de la création des accès aux API (voir
|
||||
plus haut). Lors de la création d'un nouvel accès, l’identifiant d'accès
|
||||
correspond au «orig» et la clé d'accès est la clé de signature. Les rôles sont
|
||||
ceux qui seront obtenus lors de l’usage de l’accès.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Les clés partagées peuvent aussi être définies dans le fichier
|
||||
<code>site-options.cfg</code>, dans une section <code>[api-secrets]</code>, par
|
||||
exemple :
|
||||
</p>
|
||||
|
||||
<code>
|
||||
[api-secrets]
|
||||
intranet = 12345
|
||||
</code>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Exemples d'implémentation de l’algorithme de signature</title>
|
||||
|
||||
<p>
|
||||
Voici des exemples de code pour créer des URLs signées selon l’algorithme
|
||||
expliqué ci-dessus.
|
||||
</p>
|
||||
|
||||
<listing>
|
||||
<title>Python</title>
|
||||
<code mime="text/x-python">
|
||||
#! /usr/bin/env python3
|
||||
|
||||
import base64
|
||||
import datetime
|
||||
import hashlib
|
||||
import hmac
|
||||
import random
|
||||
import urllib.parse
|
||||
|
||||
|
||||
def sign_url(url, key, algo='sha256', orig=None, timestamp=None, nonce=None):
|
||||
parsed = urllib.parse.urlparse(url)
|
||||
new_query = sign_query(parsed.query, key, algo, orig, timestamp, nonce)
|
||||
return urllib.parse.urlunparse(parsed[:4] + (new_query,) + parsed[5:])
|
||||
|
||||
|
||||
def sign_query(query, key, algo='sha256', orig=None, timestamp=None, nonce=None):
|
||||
if timestamp is None:
|
||||
timestamp = datetime.datetime.utcnow()
|
||||
timestamp = timestamp.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
if nonce is None:
|
||||
nonce = hex(random.getrandbits(128))[2:].rstrip('L')
|
||||
new_query = query
|
||||
if new_query:
|
||||
new_query += '&'
|
||||
new_query += urllib.parse.urlencode((('algo', algo), ('timestamp', timestamp), ('nonce', nonce)))
|
||||
if orig is not None:
|
||||
new_query += '&' + urllib.parse.urlencode({'orig': orig})
|
||||
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
|
||||
new_query += '&' + urllib.parse.urlencode({'signature': signature})
|
||||
return new_query
|
||||
|
||||
|
||||
def sign_string(s, key, algo='sha256', timedelta=30):
|
||||
if not isinstance(key, bytes):
|
||||
key = key.encode('utf-8')
|
||||
if not isinstance(s, bytes):
|
||||
s = s.encode('utf-8')
|
||||
digestmod = getattr(hashlib, algo)
|
||||
hash = hmac.HMAC(key, digestmod=digestmod, msg=s)
|
||||
return hash.digest()
|
||||
|
||||
|
||||
# usage:
|
||||
url = sign_url('https://www.example.net/uri/?arg=val&arg2=val2', 'user-key', orig='user')
|
||||
</code>
|
||||
</listing>
|
||||
|
||||
<listing>
|
||||
<title>PHP</title>
|
||||
<code mime="application/x-php">
|
||||
<?php
|
||||
|
||||
function sign_url(string $url, string $orig, string $key) {
|
||||
$parsed_url = parse_url($url);
|
||||
$timestamp = gmstrftime("%Y-%m-%dT%H:%M:%SZ");
|
||||
$nonce = bin2hex(random_bytes(16));
|
||||
$new_query = '';
|
||||
if (isset($parsed_url['query'])) {
|
||||
$new_query .= $parsed_url['query'] . '&';
|
||||
}
|
||||
$new_query .= http_build_query(array(
|
||||
'algo' => 'sha256',
|
||||
'timestamp' => $timestamp,
|
||||
'nonce' => $nonce,
|
||||
'orig' => $orig));
|
||||
$signature = base64_encode(hash_hmac('sha256', $new_query, $key, $raw_output = true));
|
||||
$new_query .= '&' . http_build_query(array('signature' => $signature));
|
||||
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
|
||||
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
||||
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
|
||||
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
|
||||
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
|
||||
$pass = ($user || $pass) ? "$pass@" : '';
|
||||
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
|
||||
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
|
||||
return "$scheme$user$pass$host$port$path?$new_query$fragment";
|
||||
}
|
||||
|
||||
# usage:
|
||||
url = sign_url("http://www.example.net/uri/?arg=val&arg2=val2", "user", "user-key");
|
||||
|
||||
?>
|
||||
</code>
|
||||
</listing>
|
||||
|
||||
<listing>
|
||||
<title>Shell (bash)</title>
|
||||
<code mime="application/x-shellscript">
|
||||
#!/bin/bash
|
||||
|
||||
url="http://www.example.net/uri/?arg=val&arg2=val2"
|
||||
orig="user"
|
||||
key="user-key"
|
||||
|
||||
function rawurlencode() {
|
||||
local string="${1}"
|
||||
local strlen=${#string}
|
||||
local encoded=""
|
||||
local pos c o
|
||||
for ((pos=0; pos<strlen; pos++)); do
|
||||
c=${string:$pos:1}
|
||||
case "$c" in
|
||||
[-_.~a-zA-Z0-9] ) o="${c}" ;;
|
||||
* ) printf -v o '%%%02x' "'$c"
|
||||
esac
|
||||
encoded+="${o}"
|
||||
done
|
||||
echo "${encoded}"
|
||||
}
|
||||
|
||||
now=$(date -u +%FT%TZ);
|
||||
nonce=$(od -N16 -txL /dev/urandom | cut -c8- | tr -d " ")
|
||||
qs="algo=sha256&timestamp=$now&nonce=$nonce&orig=$orig"
|
||||
sig=$(rawurlencode $(echo -n "$qs" | openssl dgst -binary -sha256 -hmac "$key" | base64))
|
||||
signed="${url}?$qs&signature=$sig"
|
||||
echo "$signed"
|
||||
</code>
|
||||
</listing>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</page>
|
|
@ -181,8 +181,7 @@ comme un commentaire ou une erreur lors de l’appel d’un <em>web service</em>
|
|||
<note>
|
||||
<p>
|
||||
Il est bien sûr nécessaire de disposer des autorisations nécessaires pour
|
||||
accéder ainsi aux données d’un formulaire. (cf <link
|
||||
xref="api-auth"/> pour les explications sur le sujet)
|
||||
accéder ainsi aux données d’un formulaire.
|
||||
</p>
|
||||
</note>
|
||||
|
||||
|
|
Loading…
Reference in New Issue