Aller au contenu principal

IAMApplication

Disponible

Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.

apiVersioniam.stackngo.io/v1alpha1
kindIAMApplication
Appliqué parsng apply
Commandes liéessng 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​

billing-api.yml
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é​

portal.yml
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
clientIdidentifiant client OAuth2
clientSecretsecret client
issuerURL 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 pour http://127.0.0.1 et http://localhost (applications natives et CLI), y compris avec un port joker http://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 quand spec.token est présent.
  • token.refreshExpireInHours: 0 est interdit quand grantTypes contient refresh_token.
  • assignableRoles n'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​

ChampDescriptionDéfautValidation
apiVersion stringiam.stackngo.io/v1alpha1
kind stringIAMApplication
metadata ObjectMetaSeul metadata.name est à renseigner (nom de la ressource dans votre tenant).
spec IAMApplicationSpec
status IAMApplicationStatus

IAMApplicationSpec​

ChampDescriptionDéfautValidation
displayName stringNom affiché sur l'écran de connexion de l'application (256 caractères au plus).MaxLength: 256
homeURL stringAdresse d'accueil de l'application, en HTTPS. Les adresses locales et privées sont refusées.MaxLength: 2048
redirectURLs string arrayAdresses 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 arrayAdresses 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 arrayFlux OAuth2 autorisés (16 au plus), par exemple authorization_code, refresh_token ou client_credentials.MaxItems: 16
scopes string arrayPérimètres de données que l'application peut demander (32 au plus), par exemple openid, profile, email.MaxItems: 32
assignableRoles string arrayPas encore pris en charge : une liste non vide est refusée. Laissez ce champ vide.MaxItems: 64
credentialsSecret CredentialsSecretSpecOù déposer les identifiants de l'application (clientId, clientSecret, issuer) pour les injecter dans une App.Optional: {}
token TokenPolicyDurées de vie des jetons émis. Facultatif : sans ce bloc, les jetons d'accès
durent 168 heures (7 jours).
Optional: {}
public booleanClient public (CLI, application native) : PKCE obligatoire, aucun secret utilisé,
redirections loopback admises.
Optional: {}
clientID stringIdentifiant 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 stringUtilisateurs 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.platformEnum: [platform tenant]
Optional: {}
deletionPolicy DeletionPolicySort de l'application quand le manifeste est supprimé : Block (défaut), Orphan ou Delete.BlockEnum: [Block Orphan Delete]

IAMApplicationStatus​

ChampDescriptionDéfautValidation
observedGeneration integerDernière version du manifeste (metadata.generation) prise en compte par la plateforme.
provider ProviderStatusIdentité de la ressource dans le service d'authentification.
lastSyncedAt TimeDate de la dernière prise en compte réussie du manifeste.Optional: {}
conditions Condition arrayConditions décrivant l'état actuel de la ressource (Ready…).
credentials CredentialsStatusÉtat du secret des identifiants OIDC, sans les valeurs secrètes.
oauthSecretRef SecretReferenceDeprecated: use status.credentials.secretName.
machineOrigin stringTenant 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.

ChampDescriptionDéfautValidation
name stringNom 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.
trueOptional: {}

TokenPolicy​

TokenPolicy fixe la durée de vie des jetons émis pour l'application.

ChampDescriptionDéfautValidation
expireInHours integerDurée de vie du jeton d'accès, en heures. 0 est refusé. Défaut : 168.168Maximum: 8760
Minimum: 1
Optional: {}
refreshExpireInHours integerDuré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]
ValeurDescription
BlockBloque la suppression tant que la ressource est encore utilisée par une autre.
OrphanSupprime le manifeste mais conserve la ressource créée.
DeleteSupprime la ressource avec le manifeste, sans vérifier son usage.

ProviderStatus​

ProviderStatus identifie la ressource dans le service d'authentification.

ChampDescriptionDéfautValidation
owner stringOrganisation propriétaire de l'objet dans l'annuaire d'identité. Renseigné par la plateforme.
name stringNom de l'objet dans l'annuaire d'identité. Renseigné par la plateforme.
resourceID stringIdentifiant 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.

ChampDescriptionDéfautValidation
secretName stringNom du Secret qui contient les identifiants.
ready booleanVrai quand le Secret d'identifiants est écrit et complet.
lastRotatedAt TimeDate du dernier renouvellement des identifiants.
observedRotationRequest stringDernière demande de renouvellement prise en compte.

SecretReference​

SecretReference désigne un secret de votre tenant.

ChampDescriptionDéfautValidation
name stringNom 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])?)*$
Champs hors d'atteinte depuis un tenant

Statut et conditions​

ConditionTrue quand
Readyl'application existe dans le SSO et correspond au manifeste
CredentialsReadyle 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.

RaisonConditionSignificationAction corrective
ReconciledReady=True, CredentialsReady=Trueà jour—
SecretUpdatedCredentialsReady=Trueles identifiants viennent d'être renouvelésredémarrer les applications qui lisent le Secret
WaitingForTenantReady=Falsel'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
NamespaceNotManagedReady=Falsele tenant n'est pas encore activé côté plateformecontacter le support
UnsupportedConfigurationReady=Falseune règle de validation est enfreinte (URL, nom de Secret, durée de jeton, assignableRoles renseigné)corriger le manifeste, sng apply
SecretOwnershipConflictCredentialsReady=Falseun Secret du même nom existe et n'appartient pas à cette applicationchanger credentialsSecret.name ou supprimer l'autre Secret
CredentialsMissingCredentialsReady=Falsele Secret n'a pas pu être écrit ou est incompletattendre la prochaine tentative ; si cela dure, contacter le support
CredentialsUnavailableCredentialsReady=Falsel'application existe dans le SSO mais son Secret a disparu, et le secret client ne peut pas être relusupprimer puis recréer l'application avec deletionPolicy: Delete, ou contacter le support
InsufficientRBACCredentialsReady=Falseincident côté plateforme : le Secret ne peut pas être écritcontacter le support
ProviderConflictReady=Falseune application du même nom existe dans le SSO et n'appartient pas à cet objetchoisir un autre metadata.name (voir Erreurs fréquentes)
ProviderUnavailable, ScopeUnresolvedReady=Falseenregistrement d'une application machine impossible pour l'instantréessai automatique
DependencyInUseReady=Falsesuppression 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 :

deletionPolicyApplication dans l'annuaireSecret <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é
Orphanconservéeconservé
Deletesupprimée, sans vérifier l'usagesupprimé

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ômeCauseCorrection
sng apply refuse : metadata : seul name est permis (…)label, annotation ou autre clé que name dans metadatala retirer
Ready: False, UnsupportedConfiguration : assignableRoles: field not supported yet…assignableRoles renseignéretirer le champ
Ready: False, WaitingForTenantannuaire du tenant pas encore prêtpatienter quelques minutes ; sinon contacter le support
sng apply refuse directorydirectory modifié après la création, ou tenant combiné à multiTenant ou au scope urn:stackngo:introspectcréer une autre application
Ready: False, UnsupportedConfiguration : redirectURLs: …URL de retour en http:// vers un hôte public, ou adresse privéeHTTPS, ou http://127.0.0.1 pour une application native
sng apply refuse token.expireInHoursvaleur 01 au minimum, ou retirer spec.token (168 h)
CredentialsReady: False, SecretOwnershipConflictun 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 nomune 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, DependencyInUseapplication liée à un fournisseur d'identité externecontacter le support
sng tenant policy attach --app billing-api sans effet--app attend le nom SSO, pas le nom du manifestelire status.provider.name (sng kind get IAMApplication billing-api --json) et le passer à --app

Voir aussi​