Sécurité du connecteur
En bref
Le connecteur héberge des données comptables : il s'expose en HTTPS, authentifie chaque appel par un jeton, applique lui-même les droits de l'utilisateur, et conserve ses secrets dans un fichier chiffré lié à la machine. Cette page décrit l'état réel des protections livrées et les réglages qui restent à votre main.
HTTPS et certificat
Le connecteur écoute en HTTPS, sur le réseau privé EasyConnect ou sur un port ouvert. Le certificat se paramètre dans l'écran Serveur Web :
- Certificat local
.pfx: l'outil sait en générer un auto-signé, avec un mot de passe et une durée de validité en années (10 ans par défaut). Il est écrit dans le dossier de configuration du connecteur, sous le nomsensaas.pfx, et l'assistant le crée s'il manque. - Let's Encrypt : mode alternatif, sans certificat local à gérer.
Un certificat auto-signé chiffre la liaison mais n'est reconnu par aucun client sans installation préalable de l'autorité : réservez-le aux usages internes, et utilisez un certificat reconnu pour une exposition directe sur Internet. Le portail SenSaaS, lui, ne vérifie pas ce certificat quand il rappelle le connecteur pour tester son accessibilité.
L'option Rediriger automatiquement HTTP vers HTTPS n'a d'effet que si le port HTTP est ouvert.
Certificat manquant
Si vous activez HTTPS sans que le fichier .pfx existe, l'outil de configuration vous en
avertit au moment d'appliquer la configuration. Le service ne pourra pas démarrer son écoute
HTTPS tant que le certificat est absent.
Authentification et jetons
Toute route protégée attend un en-tête Authorization: Bearer <jeton>. Le connecteur accepte deux
jetons en parallèle, toujours actifs : aucun réglage ne permet d'en désactiver un. Il les aiguille
d'après leur émetteur, puis applique dans les deux cas les droits, dossiers et filtres de
l'utilisateur du connecteur.
| Mécanisme | État livré |
|---|---|
| Obtention | POST /auth/login ou POST /v2/auth/login, avec identifiant et mot de passe d'un utilisateur du connecteur |
| Mots de passe des utilisateurs | Hachés (BCrypt), jamais stockés en clair |
| Politique de mot de passe | 10 à 72 caractères, au moins une lettre et un chiffre |
| Jeton d'accès | JWT signé (HMAC-SHA512) avec une clé propre à l'installation, générée aléatoirement puis conservée chiffrée |
| Durée du jeton d'accès | 20 minutes |
| Jeton de rafraîchissement | Valeur aléatoire, 7 jours, déposée dans un cookie HttpOnly, Secure, SameSite=Strict |
| Stockage du jeton de rafraîchissement | Seule une empreinte est conservée en base ; la valeur en clair ne vit que côté client |
| Réponse d'authentification | Indifférenciée : elle ne révèle pas si un compte existe |
| Limitation de débit | 30 requêtes par minute et par adresse IP sur les routes d'authentification |
La clé de signature étant propre à chaque installation, un jeton émis par un connecteur n'est valable sur aucun autre.
| Contrôle | Exigence |
|---|---|
| Émetteur | Serveur d'identité SenSaaS (Keycloak), realm sensaas |
| Signature | RS256 uniquement |
| Audience | connector-api |
| Type de jeton | Jeton d'accès (typ = Bearer) : jetons d'identité et de rafraîchissement refusés |
Client émetteur (azp) |
Une application SenSaaS autorisée (webapp, webapp bêta, application, portail) |
| Rôle | app-access |
| Identité | Email présent et vérifié (email_verified) |
Le connecteur ne délivre ni ne renouvelle jamais ce jeton : le client le renouvelle auprès du serveur d'identité. Le jeton est associé à l'utilisateur actif du connecteur qui porte la même adresse email (casse et espaces ignorés). Si plusieurs comptes actifs partagent cet email, le premier compte non B2B est retenu. L'association est gardée en mémoire deux minutes : un compte désactivé perd l'accès au plus tard deux minutes après.
La validation ne fait aucun appel réseau par requête : la clé publique du serveur d'identité est
téléchargée seulement quand une clé inconnue se présente (au plus une fois toutes les cinq
minutes), puis conservée dans C:\ProgramData\Sage\SenSaaS\keycloak-jwks.json. Un connecteur
redémarré sans Internet valide donc toujours les jetons. Le connecteur doit pouvoir joindre le
serveur d'identité en HTTPS sortant au premier jeton et à chaque changement de clé.
Réponses en cas de refus
| Situation | Réponse | Ce que fait le client |
|---|---|---|
| Aucun jeton, ou jeton mal signé, d'un autre émetteur, d'une autre audience, sans le rôle ou sans email vérifié | 401 AUTH.INVALID_TOKEN, en-tête WWW-Authenticate: Bearer |
Se reconnecter ; le detail donne le motif |
| Jeton expiré | 401 AUTH.TOKEN_EXPIRED |
Renouveler le jeton, puis rejouer l'appel |
| Jeton Keycloak valide, mais aucun utilisateur actif du connecteur pour cet email | 403 AUTH.UTILISATEUR_INCONNU |
Ne pas renouveler le jeton : l'administrateur crée ou active l'utilisateur dans Utilisateurs |
Pas de politique CORS, volontairement
Aucune politique de partage entre origines n'est déclarée. L'API vise des clients natifs et des services, pas des pages web tierces : sans en-têtes CORS, les navigateurs refusent d'eux-mêmes les appels depuis un autre domaine. C'est le comportement le plus sûr par défaut.
Droits appliqués par le connecteur
Une fois l'utilisateur identifié, le connecteur contrôle lui-même chaque appel. Les règles se règlent dans l'outil de configuration, par dossier, par profil ou par utilisateur.
| Règle | Où la régler | Effet côté API |
|---|---|---|
| Dossiers autorisés | Utilisateurs | Un dossier non autorisé est écarté ; une écriture qui ne vise que des dossiers non autorisés reçoit 403 DOSSIER.NOT_AUTHORIZED |
| Filtres de données | Filtres et accès, onglet Filtres | Lignes et colonnes visibles restreintes, sur les lectures comme sur les requêtes |
| Valeurs forcées | Même onglet, option Forcer d'un filtre | Valeur d'une colonne imposée à l'enregistrement (voir ci-dessous) |
| Droits sur l'API | Même écran, onglet API | Un appel dont le droit est retiré reçoit 403 AUTH.FORBIDDEN |
| Droits sur les documents | Même écran, onglet Documents | Impression et écritures de documents refusées en 403 AUTH.FORBIDDEN |
Droits sur l'API
Tout est permis par défaut : l'onglet API n'enregistre que les droits retirés, opération par opération ou pour toute une route. Chaque opération relève d'une nature :
- Lecture :
GET,HEAD, et lesPOSTqui ne font que lire (recherches, comptages,/v2/query,/v2/search, balances, tableau de bord, indicateurs, PDF) ; - Écriture : les autres
POST,PUTetPATCH; - Suppression :
DELETE.
Les règles de l'utilisateur, des dossiers visés et de ses profils sur ces dossiers se cumulent. Le message du refus nomme le droit et la route concernés. Les opérations anonymes (connexion, sondes) ne sont jamais concernées. Un changement est pris en compte en 30 secondes au plus, sans redémarrer le service. Le catalogue des opérations présenté par l'onglet est écrit par le service à chaque démarrage.
Droits sur les documents
Les droits par domaine (ventes, achats, stock, documents internes), par type et par statut de document, ainsi que le droit Imprimer, sont cumulés entre dossier, profil et utilisateur, puis appliqués par le connecteur :
| Opération | Droit exigé |
|---|---|
| Impression PDF | Voir et Imprimer, au type et au statut du document |
| Création d'un document | Ajouter, au type et au statut demandés |
| Modification ou suppression | Modifier ou Supprimer, au type et au statut actuels du document ; passer à un statut restreint exige Modifier à ce statut |
| Lignes d'un document | Les droits du document parent |
| Échéancier d'un document | Modifier le document |
La consultation des listes et des fiches (hors PDF), la transformation, la valorisation et l'export restent contrôlés par la webapp et l'application SenSaaS.
Les écritures comptables obéissent au droit des profils sur les écritures comptables ("EcritureC") : consulter, ajouter, modifier, supprimer.
Valeurs forcées
Un filtre peut forcer la valeur d'une colonne Sage à l'enregistrement, indépendamment de son filtre de lecture. Le niveau le plus précis l'emporte (utilisateur, puis profil, puis dossier).
- Création : la valeur forcée est écrite, quelle que soit la valeur envoyée.
- Modification : la valeur forcée est écrite si la colonne est vide en base ou porte déjà cette valeur ; si la base porte une autre valeur, elle est conservée et la valeur envoyée pour cette colonne est ignorée.
- Jamais en suppression, et seulement sur l'objet principal (pas sur les lignes d'un document).
Requêtes SQL brutes
L'option Autoriser les requêtes SQL brutes (écran Serveur Web, partie Options) est activée par défaut. Elle permet à un client d'envoyer sa propre requête SQL en lecture, mais le connecteur ne l'exécute jamais telle quelle :
- la requête est analysée puis réécrite avec les filtres de données de l'appelant ; si elle ne peut pas l'être, elle est refusée (403, avec le motif et la position fautive) ;
- une requête qui nomme une colonne masquée pour l'utilisateur est refusée, et une colonne masquée
qui remonte d'un
SELECT *est retirée du résultat ; - la liste d'exceptions aux filtres fournie par le client est ignorée ;
- les refus sont détaillés dans les journaux.
Ce que l'option ne borne pas
Les droits par module ne s'appliquent pas aux requêtes SQL brutes : un appelant peut lire une table qu'aucun de ses écrans ne lui ouvre. Désactivez l'option si ce point compte pour vos dossiers. Une installation mise à jour qui n'avait jamais touché à ce réglage passe sur le nouveau défaut, donc option activée. Le changement exige un redémarrage du service.
Hôtes autorisés
Le champ Hôtes autorisés de l'écran Serveur Web liste les noms
d'hôte acceptés dans l'en-tête Host des requêtes, séparés par des points-virgules. Il protège
contre l'usurpation d'hôte.
La valeur par défaut est * (tous les hôtes). Restreignez-la dès que vous connaissez le nom par
lequel vos clients joignent le connecteur, par exemple sensaas.monentreprise.fr;localhost.
Proxys de confiance
Par défaut, le connecteur ignore les en-têtes X-Forwarded-* : n'importe quel client peut les
forger, et s'y fier fausserait l'adresse réelle du client et la limitation de débit.
Si un proxy inverse est placé devant le connecteur, déclarez-le dans le champ Proxys de confiance (écran Serveur Web), une entrée par ligne, sous forme d'adresse IP ou de réseau CIDR :
Conséquences lorsque ce champ est renseigné :
- l'adresse réelle du client transmise par ces proxys fait foi, notamment pour la limitation de débit ;
- le schéma d'origine transmis par le proxy est honoré (redirection HTTPS et cookies corrects derrière un proxy TLS) ;
- un seul saut de proxy est honoré ;
- une entrée mal formée est refusée à la saisie par l'outil de configuration.
Laissez ce champ vide en exposition directe ou via EasyConnect. Le paramètre n'est pris en compte qu'au redémarrage du service.
Le fichier de configuration chiffré
Tous les secrets du connecteur (identifiants SQL et Sage, mot de passe du certificat, clé de signature des jetons, jeton serveur de la licence, mot de passe administrateur de l'outil) résident dans un seul fichier :
- Il est chiffré avec une clé aléatoire propre à l'installation, elle-même protégée par le mécanisme de protection de données de Windows, à portée machine.
- Il est relu à chaud par le service : une modification faite depuis l'outil de configuration est prise en compte sans redémarrage, sauf pour les paramètres signalés comme nécessitant un redémarrage (ports, proxys de confiance, écritures v2, requêtes SQL brutes).
- L'outil de configuration en est la seule autorité d'écriture. Ne l'éditez jamais à la main.
Le fichier n'est pas transférable d'une machine à l'autre
Puisque la clé de chiffrement est liée à la machine, copier SenSaaS.config sur un autre
serveur ne permet pas de le relire. C'est voulu. Pour reprendre une configuration, passez par
l'export et l'import de l'outil (ci-dessous), ou resaisissez-la via l'assistant.
Exporter et importer la configuration
L'écran Configuration, section Sauvegarde de la configuration, exporte la configuration en JSON lisible et sait l'importer :
- à l'export, les secrets (mots de passe SQL et Sage, clé de signature, jeton serveur, mot de passe du certificat) sont masqués, même vides ;
- à l'import, un secret masqué garde la valeur actuelle du serveur qui importe : les secrets sont donc à ressaisir sur une nouvelle machine ;
- le code machine et la licence restent toujours ceux du serveur qui importe ;
- l'import est validé puis confirmé, et le service est redémarré.
Durcissements recommandés
L'audit de sécurité du connecteur relève deux points qui restent à la charge de l'administrateur :
- Restreindre les droits du dossier
C:\ProgramData\Sage\SenSaaS\au compte du service et aux administrateurs de la machine. - Exclure la copie de secours
sensaas.crtdes sauvegardes externalisées : contrairement au fichier principal, elle n'est pas protégée par une clé propre à la machine. Son retrait est prévu une fois la synchronisation de configuration vers le portail généralisée.
Mot de passe administrateur de l'outil
Le mot de passe demandé à l'ouverture de l'outil de configuration est haché (BCrypt) dans le fichier de configuration. Il protège l'interface d'administration, pas les données : l'oublier ne fait perdre aucune donnée, seule la réouverture de l'outil est bloquée. La procédure de récupération est décrite dans Se connecter à l'outil.
Changez-le depuis l'écran Configuration.
Autres protections en place
- Erreurs normalisées : toute erreur est renvoyée au format
ProblemDetails. Aucune pile d'appels n'est exposée, et le détail est masqué sur les erreurs serveur. - En-tête
Serverneutralisé : la version du serveur n'est pas publiée. - Interrupteur des écritures v2 : les routes d'écriture de l'API v2 sont ouvertes par défaut aux utilisateurs autorisés, dans la limite de leurs droits. Désactiver l'option Autoriser les écritures API v2 de l'écran Serveur Web les ferme toutes : elles répondent alors "service indisponible".
- Routes historiques signalées : les routes hors
/v2portent les en-têtesDeprecationetSunset; leur retrait est prévu au 1er janvier 2027. - Corps encodés bornés : le décodage des corps de requête encodés est plafonné à 10 Mo.
- Endpoint réseau interne restreint : les routes de gestion du réseau privé ne répondent qu'en local.
Bonnes pratiques
- N'ouvrez le port HTTP que si un proxy inverse assure le chiffrement, ou sur un réseau de confiance.
- N'activez l'outil de test de l'API que le temps d'un diagnostic : il expose la documentation et permet d'exécuter des requêtes.
- Désactivez les requêtes SQL brutes si les droits par module comptent pour vos dossiers.
- Ne laissez la journalisation détaillée active que ponctuellement, et traitez les journaux comme confidentiels : voir Journalisation.
- Créez un compte par utilisateur réel, avec son adresse email exacte s'il se connecte par la webapp et désactivez les comptes inutilisés plutôt que de partager un compte.
Dans l'API v2
Les objets de cet écran sont exposés par l'API du connecteur. Chaque groupe détaille ses opérations, leurs paramètres et un exemple d'appel ; le point de départ est Démarrer avec l'API.
- Auth.Auth : 7 opérations