Configuration des extensions de services

Configuration des extensions de services

Maverics peut être enrichi à l’aide d’extensions de services, sous la forme de codes Golang personnalisés qui prennent en charge des fonctionnalités diverses telles que l’extraction et la construction d’attributs complexes ou la définition et l’évaluation de politiques d’accés/d’authentification et d’autorisation dont la logique ne fait pas déjà partie intégrante d’un orchestrateur. Les extensions de services donnent aux administrateurs la possibilité de personnaliser le comportement de l’orchestrateur Maverics en fonction des besoins spécifiques de leur intégration.

Les choix d’extension de services sont basés sur le type d’application comme suit :

Extensions de services SAML

  • Authentication : les extensions de services isAuthenticatedSE et authenticateSE sont disponibles et permettent de déterminer si un utilisateur est déjà authentifié et afin de contrôler le comportement d’authentification.
  • Authorization : isAuthorizedSE est une extension de services optionnelle qui peut être utilisée pour remplacer le comportement par défaut qui détermine si un utilisateur est autorisé.
  • Custom Claims : buildClaimsSE permet de personnaliser les attributs qui seront ajoutés à l’élément AttributeStatement SAML 2.0.
  • Relay State : buildRelayStateSE peut être utilisée pour construire le paramètre RelayState dans un flux de connexion initié par le fournisseur d’identité. Cette extension peut être utilisée lorsque l’état du relais est dynamique et ne peut donc pas être défini avec une adresse relayStateURL statique.

Extensions de services OIDC

  • Authentication : les extensions de services isAuthenticatedSE et authenticateSE sont disponibles et permettent de déterminer si un utilisateur est déjà authentifié et afin de contrôler le comportement d’authentification.
  • Access Token : accessToken définit la configuration du jeton d’accès OAuth.
  • ID Token : l’extension de services facultative buildIDTokenClaimsSE permet de personnaliser la manière dont les réclamations dans le jeton d’identification sont construites. buildAccessTokenClaimsSE permet de personnaliser la manière dont les réclamations dans le jeton d’accès sont construites.

Extensions de services Proxy app

  • Authentication : les extensions de services isAuthenticatedSE et authenticateSE sont disponibles et permettent de déterminer si un utilisateur est déjà authentifié et afin de contrôler le comportement d’authentification.
  • Upstream Login : upstreamLogin est une configuration facultative utilisée pour déterminer si une requête adressée à une application en amont est authentifiée et pour pouvoir se connecter à une application en amont. De telles situations sont courantes lorsqu’une application gère ses propres sessions ou s’authentifie directement auprès d’un magasin de données comme LDAP ou une base de données relationnelle.
  • Load Attributes : loadAttrsSE est une extension de services optionnelle utilisée pour personnaliser la manière dont le chargement des attributs est effectué. Cette extension est souvent utilisée pour charger des attributs à partir de sources de données propriétaires telles que les API d’entreprise.
  • Header Creation : createHeaderSE est une extension de services optionnelle utilisée pour créer un en-tête HTTP personnalisé. Cette extension est souvent utilisée lorsqu’un attribut doit être enrichi ou concaténé avec des données supplémentaires.
  • Authorization : isAuthorizedSE est une extension de services optionnelle qui peut être utilisée pour remplacer le comportement par défaut qui détermine si un utilisateur est autorisé.
  • Handle Unauthorized : handleUnauthorizedSE est une extension de services optionnelle qui peut être utilisée pour remplacer le comportement par défaut lorsqu’une évaluation de la politique refuse l’accès à l’application.
  • Modify Request : modifyRequestSE est une extension de services optionnelle qui peut être utilisée pour modifier chaque requête passant par l’application.
  • Modify Response : modifyResponseSE est une extension de services optionnelle qui peut être utilisée pour modifier chaque réponse passant par l’application.

Paramètres et configurations supplémentaires

Après avoir créé une extension de services, vous pouvez utiliser les champs suivants pour effectuer des sélections supplémentaires concernant celle-ci :

Paramètres des extensions de services

  • Assets : vous permet de télécharger des fichiers supplémentaires à référencer dans votre extension de services. Maverics prend également en charge les paquets protégés autorisés.
  • Providers : vous permet de sélectionner un ou plusieurs fournisseurs à utiliser dans l’extension de service. Ces configurations de fournisseurs seront utilisées dans le flux utilisateur lorsque l’extension de service est appelée.
  • Claims : vous permet d’inclure une ou plusieurs réclamations à utiliser dans la section des en-têtes (disponible uniquement pour les extensions de services Authentication et Load Attributes).
  • Metadata : les métadonnées sont un ensemble de paires clé-valeur diverses qui peuvent être mises à la disposition d’une extension donnée. Les valeurs peuvent être référencées à partir du code Go, ce qui rend les extensions de services plus flexibles et la configuration plus claire.

Utilisez l’éditeur de code d’extension de services pour configurer une extension de services personnalisée. Notre éditeur de code génère des erreurs lorsqu’il tente de compiler un code malformé.

Pour plus d’informations sur la configuration d’une extension de services personnalisée et des exemples de code, consultez le Référentiel des extensions de services. Par ailleurs, la Documentation de l’orchestrateur sur site relative aux extensions de services peut constituer une référence utile.

Utilisation des extensions de services dans un flux utilisateur

Les extensions de services peuvent être référencées dans les flux utilisateurs de différentes manières. Par exemple, l’extension de services Authentication peut être sélectionnée partout où vous définissez une politique d’authentification dans un flux utilisateur ou lorsque vous avez besoin de réclamations d’une session pour des attributs, des en-têtes ou des politiques d’autorisation.

Utilisation d’une extension de services

Utilisation d’une extension de services

Chaque flux utilisateur peut disposer de plusieurs emplacements pour référencer différents types d’extensions de service en fonction du contexte.

Utilisation d’une extension de services

Déploiement d’extensions de services

Lorsqu’une extension de service est mise à jour, tous les flux utilisateurs qui font référence à l’extension de service affichent un statut Uncommitted Changes sur la page des flux utilisateurs. Pour déployer vos flux utilisateurs avec les dernières mises à jour, ouvrez un flux utilisateur affecté, cliquez sur Commit, puis sur Deploy.

L’étape de prévisualisation du déploiement affiche une vue différentielle des modifications apportées aux extensions de services et aux actifs non binaires (txt, html, .js, etc.) entre les déploiements.

Prévisualisation du déploiement

Si vous avez déployé plusieurs flux utilisateurs qui font référence à la même extension de services dans le même environnement, tous les flux utilisateurs utiliseront l’extension de services mise à jour.

Si vous déployez une version précédente d’un flux utilisateur avec une extension de services, il reviendra à un instantané de l’extension de services à partir du déploiement précédent.

Exemples

Pour plus d’informations sur la configuration d’une extension de services personnalisée et des exemples de code, consultez le Référentiel des extensions de services. Par ailleurs, la Documentation de l’orchestrateur sur site relative aux extensions de services peut constituer une référence utile.

Actifs de référence dans l’extension de services

Il existe deux façons de référencer les fichiers d’actifs téléchargés avec l’extension de services.

  • ReadFile renvoie le contenu du fichier sous la forme []byte. Le chemin d’accès au fichier est relatif à la façon dont il a été téléchargé. Actuellement, l’interface utilisateur de Maverics ne permet que de télécharger des fichiers sans spécifier de sous-répertoire.
  • FS renvoie un objet de système de fichiers qui contient tous les fichiers d’actifs téléchargés avec l’extension de services associée. Cela signifie qu’il ne contient pas tous les actifs de toutes les extensions de service déployées sur l’orchestrateur.

Lire un seul fichier à partir des ressources téléchargées

Dans l’exemple ci-dessous, le contenu d’un fichier unique téléchargé en tant qu’extension de services est lu.

func Authenticate(api orchestrator.Orchestrator, rw http.ResponseWriter, req *http.Request) {
    logger := api.Logger()
    logger.Debug("se", "authenticating user")

    if req.Method == http.MethodGet {
        // ServiceExtensionAssets exposes any assets that may have been bundled with the
        // service extension.
        assets := api.ServiceExtensionAssets()
        // ReadFile returns the file contents as a []byte.
        idpForm, err := assets.ReadFile("idpForm.html")
        if err != nil {
            logger.Error("se", "failed to read service extension asset file", "error", err.Error())
            http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }

        logger.Info("se", "received GET request, rendering IDP selector form")
        _, _ = rw.Write(idpForm)
        return
    }

    if req.Method != http.MethodPost {
        logger.Error("se", fmt.Sprintf("received unexpected request method '%s', expected POST", req.Method))
        http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
        return
    }

    logger.Debug("se", "parsing form from request")
    err := req.ParseForm()
    if err != nil {
        logger.Error("se", "failed to parse form from request", "error", err.Error())
        http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        return
    }

    selectedIDP := req.Form.Get("idp")
    logger.Info("se", fmt.Sprintf("user selected '%s' IDP for authentication", selectedIDP))

    idp, err := api.IdentityProvider(selectedIDP)
    if err != nil {
        logger.Error("se", "unable to lookup idp", "error", err.Error())
        http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        return
    }

	idp.Login(rw, req)
}

Lire tous les actifs téléchargés en tant que système de fichiers

Dans l’exemple ci-dessous, tous les actifs de l’extension de services téléchargés sont lus en tant que système de fichiers.

func ServeWebAssets(api orchestrator.Orchestrator) error {
    router := api.Router()
    router.HandleFunc("/assets/idpform.html", func(rw http.ResponseWriter, req *http.Request) {
        logger := api.Logger()
        logger.Info("se", "serving idp picker form")

        session, err := api.Session(session.WithRequest(req))
        if err != nil {
            logger.Error("se", "unable to retrieve session", "error", err.Error())
            http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return false
        }
        username, _ := session.GetString("idp.username")

        seAssets := api.ServiceExtensionAssets()
        // FS returns a filesystem of type (fs.FS) containing the assets associated
        // with the service extension.
        sefs, err := seAssets.FS()
        if err != nil {
            logger.Error("se", "failed to get service extension filesystem", "error", err.Error())
            http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
        tmpl, err := template.ParseFS(sefs, "idp-form.html")
        if err != nil {
            logger.Error("se", "unable to parse template", "error", err.Error())
            http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }

        data := struct {
            Title string
        }{
            Title: fmt.Sprintf("Pick your IDP %s", username),
        }
        err = tmpl.Execute(rw, data)
        if err != nil {
            logger.Error("se", "unable to execute template", "error", err.Error())
            http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }
    })
    return nil
}