IAMApplication
Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.
apiVersion | iam.stackngo.io/v1alpha1 |
kind | IAMApplication |
| Appliqué par | sng apply |
| Commandes liées | sng template gen IAMApplication, sng kind get IAMApplication, sng kind delete IAMApplication, sng iam app list · describe · credentials, sng tenant policy attach --app |
À quoi ça sert
Une IAMApplication déclare un client OAuth2 / OIDC pour l'une de vos applications : ses URL de retour, ses flux (authorization_code, refresh_token, client_credentials…), ses scopes et la durée de ses jetons. La plateforme crée l'application et dépose clientId, clientSecret et issuer dans un secret <nom>-oidc de votre tenant, prêt à être injecté dans une App. Avec directory: tenant, les utilisateurs de vos applications (annuaire du tenant) se connectent sur l'émetteur de votre tenant (https://auth.dev.stackngo.fr/t/acme), sans mot de passe.
Exemple minimal
apiVersion: iam.stackngo.io/v1alpha1
kind: IAMApplication
metadata:
name: billing-api
spec:
directory: tenant # utilisateurs de vos applications (défaut : platform)
displayName: Billing API
redirectURLs:
- https://billing-api.acme.dev.stackngo.app/auth/callback
grantTypes: [authorization_code, refresh_token]
scopes: [openid, profile, email]
sng apply billing-api.yml
sng kind get IAMApplication billing-api --json # status.credentials.secretName = billing-api-oidc
Il n'existe pas de commande impérative équivalente : sng iam app liste et décrit les applications de l'annuaire, mais ne les crée pas ; la console propose un formulaire équivalent.
Exemple complet commenté
apiVersion: iam.stackngo.io/v1alpha1
kind: IAMApplication
metadata:
name: portal # nom de l'objet ; le nom dans le SSO en dérive (sng-…-app-portal)
spec:
displayName: Portail client # affiché sur l'écran de connexion, 256 caractères max
homeURL: https://portal-web.acme.dev.stackngo.app # HTTPS, pas d'adresse locale ou privée
redirectURLs: # 32 max ; HTTPS, sauf http://127.0.0.1 et http://localhost
- https://portal-web.acme.dev.stackngo.app/auth/callback
- http://127.0.0.1:*/callback # application native ou CLI (port quelconque)
grantTypes: # 16 max
- authorization_code
- refresh_token
scopes: [openid, profile, email] # 32 max
credentialsSecret:
name: portal-oidc # défaut : <nom>-oidc
create: true # false : aucun Secret, identifiants dans le SSO seulement
token:
expireInHours: 1 # jeton d'accès : 1 à 8760 h ; 168 si spec.token est omis
refreshExpireInHours: 720 # jeton de rafraîchissement : 168 par défaut avec refresh_token
deletionPolicy: Delete # Block (défaut), Orphan ou Delete : voir « Ce qui se passe quand vous supprimez »
Le Secret produit :
| Clé | Contenu |
|---|---|
clientId | identifiant client OAuth2 |
clientSecret | secret client |
issuer | URL de l'émetteur OIDC (https://auth.dev.stackngo.fr/t/acme pour directory: tenant) ; découverte sous <issuer>/.well-known/openid-configuration |
Champs
Règles de validation croisées
Le schéma ne porte pas de règle CEL. sng apply vérifie les types, longueurs et bornes du tableau ci-dessous (par exemple token.expireInHours: 0 est refusé, minimum 1). Les règles suivantes sont vérifiées par la plateforme après sng apply, au moment d'appliquer le manifeste :
redirectURLs: chaque URL en HTTPS, ni adresse locale, ni adresse privée, ni adresse de métadonnées ; exception pourhttp://127.0.0.1ethttp://localhost(applications natives et CLI), y compris avec un port jokerhttp://127.0.0.1:*/callback.homeURL: HTTPS, mêmes interdits, sans l'exception locale.credentialsSecret.name: nom DNS (minuscules, chiffres,-,.) ou vide.token.expireInHours: 1 au moins quandspec.tokenest présent.token.refreshExpireInHours: 0est interdit quandgrantTypescontientrefresh_token.assignableRolesn'est pas encore pris en charge : une liste non vide est refusée (assignableRoles: field not supported yet, it would have no effect; remove it). Retirez le champ, ou laissez-le vide.
Une application refusée à ce stade reste Ready: False avec la raison UnsupportedConfiguration et le message de la règle.
IAMApplication
| Champ | Description | Défaut | Validation |
|---|---|---|---|
apiVersion string | iam.stackngo.io/v1alpha1 | ||
kind string | IAMApplication | ||
metadata ObjectMeta | Seul metadata.name est à renseigner (nom de la ressource dans votre tenant). | ||
spec IAMApplicationSpec | |||
status IAMApplicationStatus |
IAMApplicationSpec
| Champ | Description | Défaut | Validation |
|---|---|---|---|
displayName string | Nom affiché sur l'écran de connexion de l'application (256 caractères au plus). | MaxLength: 256 | |
homeURL string | Adresse d'accueil de l'application, en HTTPS. Les adresses locales et privées sont refusées. | MaxLength: 2048 | |
redirectURLs string array | Adresses vers lesquelles l'utilisateur est renvoyé après connexion (32 au plus). HTTPS obligatoire, sauf http://127.0.0.1 et http://localhost pour les applications natives et les CLI. | MaxItems: 32 | |
postLogoutRedirectURLs string array | Adresses de retour admises après une déconnexion (post_logout_redirect_uri d'OIDC RP-Initiated Logout), mêmes règles que redirectURLs. Backend auth seulement : sans elles, /end_session refuse la redirection et la session du navigateur reste ouverte. | MaxItems: 32 Optional: {} | |
grantTypes string array | Flux OAuth2 autorisés (16 au plus), par exemple authorization_code, refresh_token ou client_credentials. | MaxItems: 16 | |
scopes string array | Périmètres de données que l'application peut demander (32 au plus), par exemple openid, profile, email. | MaxItems: 32 | |
assignableRoles string array | Pas encore pris en charge : une liste non vide est refusée. Laissez ce champ vide. | MaxItems: 64 | |
credentialsSecret CredentialsSecretSpec | Où déposer les identifiants de l'application (clientId, clientSecret, issuer) pour les injecter dans une App. | Optional: {} | |
token TokenPolicy | Durées de vie des jetons émis. Facultatif : sans ce bloc, les jetons d'accès durent 168 heures (7 jours). | Optional: {} | |
public boolean | Client public (CLI, application native) : PKCE obligatoire, aucun secret utilisé, redirections loopback admises. | Optional: {} | |
clientID string | Identifiant OAuth fixé (ex. compilé dans un binaire) au lieu d'un identifiant généré. Jamais au format UUID. | Pattern: ^[A-Za-z0-9._-]\{8,128\}$ Optional: {} | |
directory string | Utilisateurs que l'application connecte : platform (défaut, membres de votre tenant sur StackNGO) ou tenant (utilisateurs de vos applications, émetteur propre à votre tenant). Ne change plus après la création : en créer une autre. Incompatible avec le scope urn:stackngo:introspect. | platform | Enum: [platform tenant] Optional: {} |
deletionPolicy DeletionPolicy | Sort de l'application quand le manifeste est supprimé : Block (défaut), Orphan ou Delete. | Block | Enum: [Block Orphan Delete] |
IAMApplicationStatus
| Champ | Description | Défaut | Validation |
|---|---|---|---|
observedGeneration integer | Dernière version du manifeste (metadata.generation) prise en compte par la plateforme. | ||
provider ProviderStatus | Identité de la ressource dans le service d'authentification. | ||
lastSyncedAt Time | Date de la dernière prise en compte réussie du manifeste. | Optional: {} | |
conditions Condition array | Conditions décrivant l'état actuel de la ressource (Ready…). | ||
credentials CredentialsStatus | État du secret des identifiants OIDC, sans les valeurs secrètes. | ||
oauthSecretRef SecretReference | Deprecated: use status.credentials.secretName. | ||
machineOrigin string | Tenant auquel sont rattachées les sessions ouvertes avec les identifiants de cette application, quand c'est une application machine. Vide sinon. |
CredentialsSecretSpec
CredentialsSecretSpec configure le secret qui reçoit les identifiants OIDC de l'application.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom du secret qui reçoit les identifiants (clientId, clientSecret, issuer). Défaut : <nom-de-l-application>-oidc. Ignoré quand create vaut false. | MaxLength: 253 Pattern: ^(|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)$ Optional: {} | |
create boolean | À false, aucun secret n'est créé dans votre tenant : les identifiants ne sont conservés que par le service d'authentification (cas typique d'une application machine à machine). Défaut : true. | true | Optional: {} |
TokenPolicy
TokenPolicy fixe la durée de vie des jetons émis pour l'application.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
expireInHours integer | Durée de vie du jeton d'accès, en heures. 0 est refusé. Défaut : 168. | 168 | Maximum: 8760 Minimum: 1 Optional: {} |
refreshExpireInHours integer | Durée de vie du jeton de rafraîchissement, en heures. Non renseigné : 168 si grantTypes contient refresh_token, 0 sinon. La valeur 0 n'est acceptée que sans le grant refresh_token. | Maximum: 8760 Minimum: 0 Optional: {} |
DeletionPolicy
Type sous-jacent : string
DeletionPolicy indique ce que devient la ressource quand vous supprimez son manifeste : Block bloque la suppression tant que la ressource est encore utilisée, Orphan la conserve, Delete la supprime.
Règles de validation :
Enum: [Block Orphan Delete]
| Valeur | Description |
|---|---|
Block | Bloque la suppression tant que la ressource est encore utilisée par une autre. |
Orphan | Supprime le manifeste mais conserve la ressource créée. |
Delete | Supprime la ressource avec le manifeste, sans vérifier son usage. |
ProviderStatus
ProviderStatus identifie la ressource dans le service d'authentification.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
owner string | Organisation propriétaire de l'objet dans l'annuaire d'identité. Renseigné par la plateforme. | ||
name string | Nom de l'objet dans l'annuaire d'identité. Renseigné par la plateforme. | ||
resourceID string | Identifiant de l'objet dans l'annuaire d'identité. Renseigné par la plateforme. |
CredentialsStatus
CredentialsStatus indique si le secret des identifiants OIDC est prêt, sans en exposer les valeurs.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
secretName string | Nom du Secret qui contient les identifiants. | ||
ready boolean | Vrai quand le Secret d'identifiants est écrit et complet. | ||
lastRotatedAt Time | Date du dernier renouvellement des identifiants. | ||
observedRotationRequest string | Dernière demande de renouvellement prise en compte. |
SecretReference
SecretReference désigne un secret de votre tenant.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom du secret. | MaxLength: 253 MinLength: 1 Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ |
status.machineOriginn'est renseigné que pour les applications machine créées par la plateforme (voir Machines et comptes de service).
Statut et conditions
| Condition | True quand |
|---|---|
Ready | l'application existe dans le SSO et correspond au manifeste |
CredentialsReady | le Secret d'identifiants est écrit (ou les identifiants sont conservés dans le SSO avec create: false) |
Champs utiles : status.provider.name (nom de l'application dans le SSO, à passer à sng tenant policy attach --app), status.credentials.secretName, status.credentials.lastRotatedAt, status.lastSyncedAt.
| Raison | Condition | Signification | Action corrective |
|---|---|---|---|
Reconciled | Ready=True, CredentialsReady=True | à jour | — |
SecretUpdated | CredentialsReady=True | les identifiants viennent d'être renouvelés | redémarrer les applications qui lisent le Secret |
WaitingForTenant | Ready=False | l'annuaire d'identité du tenant n'est pas encore prêt (la ressource converge d'elle-même) | patienter ; si cela dure, contacter le support |
NamespaceNotManaged | Ready=False | le tenant n'est pas encore activé côté plateforme | contacter le support |
UnsupportedConfiguration | Ready=False | une règle de validation est enfreinte (URL, nom de Secret, durée de jeton, assignableRoles renseigné) | corriger le manifeste, sng apply |
SecretOwnershipConflict | CredentialsReady=False | un Secret du même nom existe et n'appartient pas à cette application | changer credentialsSecret.name ou supprimer l'autre Secret |
CredentialsMissing | CredentialsReady=False | le Secret n'a pas pu être écrit ou est incomplet | attendre la prochaine tentative ; si cela dure, contacter le support |
CredentialsUnavailable | CredentialsReady=False | l'application existe dans le SSO mais son Secret a disparu, et le secret client ne peut pas être relu | supprimer puis recréer l'application avec deletionPolicy: Delete, ou contacter le support |
InsufficientRBAC | CredentialsReady=False | incident côté plateforme : le Secret ne peut pas être écrit | contacter le support |
ProviderConflict | Ready=False | une application du même nom existe dans le SSO et n'appartient pas à cet objet | choisir un autre metadata.name (voir Erreurs fréquentes) |
ProviderUnavailable, ScopeUnresolved | Ready=False | enregistrement d'une application machine impossible pour l'instant | réessai automatique |
DependencyInUse | Ready=False | suppression bloquée (deletionPolicy: Block) : suppression bloquée : l'application est encore liée à 1 fournisseur d'identité | contacter le support ; ou supprimer avec deletionPolicy: Delete |
Ce qui se passe à l'application
Création. L'application est créée dans l'annuaire de vos utilisateurs sous un nom stable dérivé du manifeste (sng-<empreinte>-app-<nom>, visible dans status.provider.name), avec un clientId et un clientSecret, rangés dans le Secret <nom>-oidc de votre tenant (sauf credentialsSecret.create: false).
Mise à jour. Un nouveau sng apply met l'application à jour en place ; clientId et clientSecret ne changent pas. Renommer le manifeste (metadata.name) crée une autre application.
Ce qui se passe quand vous supprimez
sng kind delete IAMApplication <nom>. L'effet dépend de deletionPolicy :
deletionPolicy | Application dans l'annuaire | Secret <nom>-oidc |
|---|---|---|
Block (défaut) | supprimée, sauf tant qu'elle est utilisée : liée à un fournisseur d'identité externe (DependencyInUse, avec un message qui dit quoi) | supprimé |
Orphan | conservée | conservé |
Delete | supprimée, sans vérifier l'usage | supprimé |
Une fois l'application supprimée de l'annuaire, vos utilisateurs ne peuvent plus s'y connecter. Une suppression bloquée est réexaminée chaque minute et aboutit d'elle-même dès que l'application n'est plus utilisée.
Recréer sous le même nom. Après une suppression aboutie (Block ou Delete), un nouveau
sng apply du même manifeste crée une nouvelle application, avec un nouveau clientId et un
nouveau clientSecret dans <nom>-oidc. Après un Orphan, le manifeste réappliqué reprend
l'application restée dans l'annuaire.
Aucun utilisateur de l'annuaire n'est jamais supprimé avec une application.
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
sng apply refuse : metadata : seul name est permis (…) | label, annotation ou autre clé que name dans metadata | la retirer |
Ready: False, UnsupportedConfiguration : assignableRoles: field not supported yet… | assignableRoles renseigné | retirer le champ |
Ready: False, WaitingForTenant | annuaire du tenant pas encore prêt | patienter quelques minutes ; sinon contacter le support |
sng apply refuse directory | directory modifié après la création, ou tenant combiné à multiTenant ou au scope urn:stackngo:introspect | créer une autre application |
Ready: False, UnsupportedConfiguration : redirectURLs: … | URL de retour en http:// vers un hôte public, ou adresse privée | HTTPS, ou http://127.0.0.1 pour une application native |
sng apply refuse token.expireInHours | valeur 0 | 1 au minimum, ou retirer spec.token (168 h) |
CredentialsReady: False, SecretOwnershipConflict | un Secret <nom>-oidc existe déjà (créé à la main, ou par une autre application) | credentialsSecret.name: autre-nom |
Ready: False, ProviderConflict : une ressource du même nom existe déjà et appartient à un autre objet : choisissez un autre nom | une application de ce nom existe dans l'annuaire sans appartenir à votre tenant ni à un manifeste supprimé | choisir un autre metadata.name |
Suppression qui ne se termine pas, DependencyInUse | application liée à un fournisseur d'identité externe | contacter le support |
sng tenant policy attach --app billing-api sans effet | --app attend le nom SSO, pas le nom du manifeste | lire status.provider.name (sng kind get IAMApplication billing-api --json) et le passer à --app |
Voir aussi
- Guides : Authentification de vos applications, Machines et comptes de service, Utilisateurs, rôles et groupes
- CLI :
sng iam,sng apply,sng tenant policy attach - Autres kinds : IAMRole, IAMGroup, IAMPolicyBinding