Section3 pages

Configuration déclarative

La configuration déclarative décrit la configuration des royaumes dans des fichiers, un objet par fichier, que l’on range dans git, relit en revue et promeut d’un environnement à l’autre. Le cycle est celui des outils d’infrastructure :

  1. export : les objets d’un royaume sont écrits en fichiers ;
  2. plan : les fichiers sont comparés au serveur, sans rien écrire ;
  3. apply : les écarts sont appliqués au serveur.

Un même moteur sert trois points d’entrée :

Faites défiler le tableau
Point d’entréeUsage
La commande tosiam-configPoste d’un exploitant, intégration continue
L’import au démarrageImage TOSIAM et chart Helm : la configuration est appliquée quand le serveur démarre
L’écran « Export / import » de la consoleExporter, prévisualiser et appliquer depuis un navigateur

Le moteur ne passe que par l’API REST d’administration (/api) : les écritures subissent les mêmes contrôles que celles de la console (droits, validation, masquage des secrets).

Objets pris en charge#

Faites défiler le tableau
Type (kind)RépertoireFichiers
DataStoredatastores/<nom>.yaml
Scriptscripts/<nom>.yaml et le code, <nom>.js ou <nom>.groovy
SubGraphsubgraphs/<nom>.json
AuthGraphauthgraphs/<nom>.json
RealmServiceservices/<service>.yaml
OAuth2Clientagents/OAuth2Client/<id>.yaml
WebAgentagents/WebAgent/<id>.yaml
ResourceTyperesourcetypes/<nom>.yaml
PolicySetpolicysets/<nom>.yaml
Policypolicies/<ensemble de politiques>/<nom>.yaml

Le royaume lui-même est décrit par son fichier realm.yaml : voir Le royaume.

Ne sont pas encore pris en charge : les services globaux, la fédération SAML, le STS et la configuration des serveurs. Ils restent du ressort de la console et de ssoadm.

Le répertoire de configuration#

texte
tosiam-config/
├── tosiam.yaml                 # version du format, périmètre géré
└── realms/
    ├── _root/                  # le royaume racine
    │   ├── realm.yaml          # chemin, statut et alias DNS du royaume
    │   ├── scripts/
    │   │   ├── decision.yaml
    │   │   └── decision.js
    │   ├── authgraphs/login.json
    │   └── agents/OAuth2Client/app1.yaml
    └── clients__mobile/        # le royaume /clients/mobile
        └── ...
  • Un répertoire par royaume sous realms/, à plat : _root pour le royaume racine, sinon le chemin du royaume dont les / sont remplacés par __. Le chemin écrit dans realm.yaml (path: /clients/mobile) l’emporte sur le nom du répertoire, qui peut donc être renommé.
  • tosiam.yaml porte la version du format (formatVersion: 1) et, au besoin, le périmètre géré.

Le royaume#

realm.yaml décrit le royaume lui-même :

yaml
path: /clients/mobile
active: true
aliases:
- mobile.example.com
  • Un royaume absent du serveur est créé par l’application, avant ses objets : actif et sans alias, sauf si realm.yaml dit autre chose. Son royaume parent doit exister, ou être appliqué avant lui (--all-realms applique les parents d’abord). La création d’un royaume demande un administrateur global.
  • Un royaume présent est mis à jour quand active ou aliases diffère de ce que déclare realm.yaml.
  • Une clé absente de realm.yaml n’est pas gérée : le serveur garde sa valeur. Un realm.yaml qui n’a que path ne change ni le statut ni les alias.
  • Un royaume n’est jamais supprimé, même avec --prune=managed.

Un objet par fichier#

Les fichiers sont écrits en YAML et peuvent être lus en YAML ou en JSON. Chacun porte kind, apiVersion et metadata.name ; le contenu est sous spec, avec les noms d’attributs de l’API REST :

yaml
apiVersion: config.tosiam.io/v1
kind: OAuth2Client
metadata:
  name: app1
spec:
  coreOAuth2ClientConfig:
    com.forgerock.openam.oauth2provider.clientType:
      inherited: false
      value: Confidential
    com.forgerock.openam.oauth2provider.redirectionURIs:
      inherited: false
      value:
      - ${env:APP1_REDIRECT_URI}
    userpassword: ${file:/run/secrets/tosiam-config/app1-secret}

Particularités :

  • Royaume : il n’est pas écrit dans les fichiers d’objets. C’est le répertoire qui le donne : copier realms/_root en realms/recette promeut la configuration du royaume racine vers le royaume /recette.
  • Identité : un objet est identifié par son nom, sauf les scripts et les types de ressource, identifiés par leur identifiant (metadata.id). À la création, cet identifiant est repris : un même script a le même identifiant sur tous les serveurs. Un objet à créer dont le nom est déjà pris sur le serveur sous un autre identifiant est un conflit, signalé avant toute écriture.
  • Graphes : un graphe est écrit dans l’enveloppe JSON d’export de la console, un graphe par fichier. Un fichier exporté par la CLI s’importe dans l’éditeur de graphes de la console, et inversement, à une exception près : l’éditeur refuse encore un sous-graphe dont un paramètre a une valeur par défaut.
  • Scripts : le code est dans un fichier à part, nommé par l’attribut source du .yaml.
  • Sortie stable : clés triées, listes sans ordre triées, aucun horodatage. Deux exports d’une même configuration donnent les mêmes fichiers, et un diff git ne montre que les vrais changements.
  • Scripts globaux : ceux du produit et ceux créés en global sont listés dans chaque royaume, mais ne sont ni exportés, ni comparés, ni supprimés.

Secrets et valeurs propres à un environnement#

L’API ne renvoie jamais un secret. À l’export, chaque secret est remplacé par une référence ${secret:…} qui indique où il se trouvait :

yaml
    userpassword: ${secret:realms/_root/agents/OAuth2Client/app1/coreOAuth2ClientConfig/userpassword}

Avant l’application, remplacez-la par une référence qui fournit la valeur. Deux sortes de références sont résolues, dans toute valeur, pas seulement dans les secrets :

Faites défiler le tableau
RéférenceValeur
${env:NOM}La variable d’environnement NOM
${file:/chemin}Le contenu du fichier, sans ses fins de ligne finales (un Secret Kubernetes monté, un fichier de la CI)

Une valeur peut contenir plusieurs références au milieu d’un texte : https://${env:HOST}/callback. Seuls les préfixes env:, file: et secret: font une référence : ${org}, par exemple un paramètre de sous-graphe, est laissé tel quel. Dans le code d’un script, rien n’est remplacé.

Quand une référence ne peut pas être résolue (${secret:…}, variable absente, fichier absent) :

  • sur un objet modifié, un secret non fourni est conservé par le serveur ; toute autre valeur est un problème qui empêche l’application ;
  • sur un objet créé, un secret déclaré obligatoire par le schéma du serveur (le mot de passe d’un client confidentiel, celui de la connexion d’un data store) doit être fourni ; un secret facultatif non fourni est omis.

Le serveur ne renvoyant pas les secrets, le plan ne sait pas si un secret fourni diffère de la valeur en place : un secret fourni est toujours réécrit, et annoncé comme tel (secret rewritten).

Suppressions et périmètre géré#

Par défaut, rien n’est supprimé : un objet présent sur le serveur et absent des fichiers est seulement signalé (!, « sur le serveur seulement »).

Pour que les fichiers fassent foi, déclarez dans tosiam.yaml le périmètre géré, puis appliquez avec --prune=managed :

yaml
formatVersion: 1
managed:
  - realm: /
    kinds: [OAuth2Client, AuthGraph, Script]
    exclude:
      - kind: Script
        name: "Legacy *"
  - realm: /clients
    kinds: ["*"]

Un objet est supprimé s’il est dans le périmètre (royaume et type déclarés, nom non exclu ; * est un joker) et n’a pas de fichier. Le périmètre est versionné avec le reste : il n’y a ni fichier d’état local, ni marqueur sur les objets du serveur.

Certains objets ne sont jamais supprimés, même dans le périmètre : le royaume lui-même, les services de royaume, les scripts globaux, le type de ressource URL et l’ensemble de politiques iPlanetAMWebAgentService.

Ordre d’application et reprise#

Les objets sont créés et modifiés dans l’ordre de leurs dépendances : le royaume, les data stores, scripts, sous-graphes, graphes, services, clients OAuth2, agents web, types de ressource, ensembles de politiques, politiques. Les suppressions suivent l’ordre inverse.

Il n’y a pas de transaction : à la première erreur, l’application s’arrête, et ce qui a été appliqué le reste. Comme le plan est recalculé à chaque fois, une nouvelle application reprend là où l’autre s’est arrêtée.

Compatibilité des versions#

Une CLI de version X.Y accepte un serveur X.Y ou X.(Y-1), pour couvrir la promotion pendant une montée de version, et refuse les autres. Un fichier tosiam.yaml d’un format plus récent que celui de la CLI est refusé.