LDAP et Active Directory

Les connecteurs LDAP et Active Directory utilisent les services des répertoires LDAP et Active Directory (respectivement) de l’entreprise pour fournir l’authentification et les attributs utilisés pour :

  • la migration des informations de profil d’utilisateur des systèmes d’accès existants vers les systèmes d’accès hébergés sur le cloud,
  • l’ajout d’en-têtes HTTP utilisés par les applications sur site, ou
  • le maintien de l’état des sessions utilisateur lorsqu’elles passent d’un système d’identité à l’autre et d’une application à l’autre.

Options de configuration

Les valeurs suivantes peuvent être fournies au connecteur LDAP via le fichier de configuration de Maverics.

URL

Les adresses url du serveur LDAP avec lequel Maverics se connecte. Les URL uniques et les listes d’URL sont prises en charge. Lorsque plusieurs URL sont fournies, un système d’équilibrage circulaire de la charge sera utilisé pour répartir le trafic.

Service Account Username

serviceAccountUsername correspond au nom d’utilisateur utilisé pour se connecter au serveur LDAP pour les requêtes.

Service Account Password

serviceAccountPassword correspond au mot de passe utilisé pour se connecter au serveur LDAP pour les requêtes.

Base DN

baseDN spécifie l’emplacement dans lequel la recherche LDAP doit être effectuée.

Username Search Key

La clé usernameSearchKey à filtrer lors des requêtes et des liaisons.

Attribute delimiter

attributeDelimiter correspond au délimiteur utilisé pour séparer les attributs à valeurs multiples. Il s’agit d’un champ facultatif qui n’est nécessaire que pour les attributs à valeurs multiples. Si aucune valeur n’est fournie, la valeur par défaut « , » sera utilisée en tant que délimiteur.

Enable Authentication

Définissez enableAuthentication sur true afin d’utiliser le protocole LDAP en tant que fournisseur d’identité.

connectors:
  - type: ldap
    enableAuthentication: true
    # ...

Authentication Search Scope

La configuration authenticationSearchScope est une configuration facultative qui doit être utilisée avec serviceAccountUsername, serviceAccountPassword, usernameSearchKey et enableAuthentication pour prendre en charge l’authentification des utilisateurs contenus dans des
unités organisationnelles imbriquées à l’intérieur du nom de domaine baseDN spécifié. Si vous souhaitez vous authentifier auprès d’utilisateurs qui se trouvent dans des unités organisationnelles imbriquées, le paramètre authenticationSearchScope doit être défini de manière à prendre en charge leur authentification.

connectors:
  - type: ldap
    enableAuthentication: true
    usernameSearchKey: uid
    baseDN: ou=Engineering,ou=People,dc=example,dc=com
    authenticationSearchScope: singleLevel
    serviceAccountUsername: cn=exampleUsername,dc=example,dc=com
    serviceAccountPassword: <examplePassword>
    # ...

Les configurations suivantes sont prises en charge :

Base Object

baseObject correspond au champ d’application qui limite la recherche au nom de domaine de base baseDN.

Single Level

singleLevel correspond au champ d’application qui limite la recherche aux subordonnés immédiats de l’entrée nommée par baseDN.

Whole Subtree

wholeSubtree correspond au champ d’application qui limite la recherche au nom de domaine de base baseDN et à tous ses subordonnés.

Login URL

Lors de l’utilisation du connecteur LDAP en tant que fournisseur d’identité, le paramètre loginURL (facultatif) peut être utilisé pour définir un terminal personnalisé pour l’affichage des informations d’identification de l’utilisateur. Si ce paramètre n’est pas défini, le formulaire est envoyé à l’emplacement par défaut /.ldap-login. Ce terminal est hébergé par l’orchestrateur, le domaine spécifié doit donc correspondre à un domaine hébergé par l’orchestrateur ou être défini comme un simple chemin d’accès. Dans les deux cas, il ne doit pas entrer en conflit avec d’autres chemins d’accès aux applications protégées.

ℹ️

Au moment de spécifier un loginURL, utilisez une URL absolue (complète) comprenant le schéma, le nom de l’hôte et le chemin d’accès afin de garantir que les requêtes de statut sont acheminées correctement. Spécifiez toujours une valeur loginURL personnalisée si routePattern inclut un nom d’hôte.

Par exemple, si routePattern est défini comme suit :

routePatterns:
  - api.example.com

la valeur loginURL peut être :

loginURL: https://api.example.com/login

connectors:
  - type: ldap
    enableAuthentication: true
    loginURL: "https://example.com/ldap-login"
    # ...

Custom Login HTML

Lors de l’utilisation du connecteur LDAP en tant que fournisseur d’identité, la configuration customLoginHTML (optionnelle) peut présenter une page personnalisée invitant l’utilisateur à s’authentifier. Elle doit contenir l’emplacement d’une page HTML dans le système de fichiers. Si la valeur n’est pas définie, une page de connexion par défaut sera utilisée.

connectors:
  - type: ldap
    enableAuthentication: true
    loginURL: "https://example.com/ldap-login"
    # Using a static HTML page.
    customLoginHTML: /var/www/html/ldap-login.html
    # ...

En définissant customLoginHTML, l’orchestrateur peut fournir une page HTML personnalisée stockée dans le système de fichiers, comme indiqué ci-dessus. L’orchestrateur utilise Go Templates pour fournir les éléments pertinents à restituer.

Cette page doit POSTER le contenu du nom d’utilisateur et le mot de passe vers l’URL de connexion, qui sera fournie dans la valeur du modèle LoginURL. La page initialement demandée se trouve dans la valeur du modèle RedirectURL et doit être transmise à l’URL de connexion en même temps que le nom d’utilisateur et le mot de passe.

<html>
    <body>
        <form action={{.LoginURL}} method=POST>
            <label for="username">Username</label>
            <input type="text" id="username" name="username" />
            <br>
            <label for="password">Password</label>
            <input type="password" id="password" name="password" />
            <br>
            <input type="hidden" name="redirectURL" value="{{.RedirectURL}}" />
            <br>
            <input type="submit" name="submit" value="Submit" />
        </form>
    </body>
</html>

Health Check

healthCheck définit une vérification d’état facultative du connecteur. Cette option est requise lors de l’utilisation du connecteur en situation de maintien de la pérennité du fournisseur d’identité. Pour plus d’informations sur la façon de définir la vérification d’état, veuillez consulter la documentation.

Exemples

Chargement d’attributs à partir du protocole LDAP (LDAP en tant que fournisseur d’attributs)

connectors:
  - name: ldap-example
    type: ldap
    url:
      - "ldap://node1.ldap.com"
      - "ldap://node2.ldap.com"
    baseDN: ou=People,o=Example,c=US
    serviceAccountUsername: uid=admin,ou=Admins,o=Example,c=US
    serviceAccountPassword: <examplePassword>
    usernameSearchKey: uid
    attributeDelimiter: ^

Exemple de configuration du connecteur Active Directory

connectors:
  - name: ad-example
    type: activedirectory
    url:
      - "ldap://node1.ldap.com"
      - "ldap://node2.ldap.com"
    baseDN: ou=People,o=Example,c=US
    serviceAccountUsername: uid=admin,ou=Admins,o=Example,c=US
    serviceAccountPassword: password
    usernameSearchKey: uid
    attributeDelimiter: ^

Authentification avec le connecteur LDAP (LDAP en tant que fournisseur d’identité)

Lorsque le protocole LDAP est utilisé en tant que fournisseur d’identité, l’orchestrateur présente un formulaire permettant à l’utilisateur de saisir son nom d’utilisateur et son mot de passe. Pour utiliser Active Directory en tant que fournisseur d’identité, remplacez le type de connecteur par activedirectory

tls:
  maverics:
    certFile: certs/maverics.sonarsystems.co.crt
    keyFile: certs/maverics.sonarsystems.co.key

http:
  address: :443
  tls: maverics

apps:
  - name: Sonar
    type: proxy
    routePatterns:
      - /
    tls: sonar-app
    upstream: https://app.sonarsystems.com:8443
    policies:
      - location: /
        authentication:
          idps:
            - ldap
        authorization:
          allowAll: true

connectors:
  - name: ldap
    type: ldap
    url: "ldap://ldap.example.com:389"
    serviceAccountPassword: <examplePassword>
    serviceAccountUsername: cn=exampleUsername,dc=example,dc=com
    baseDN: ou=People,dc=example,dc=com
    usernameSearchKey: uid
    enableAuthentication: true
    authenticationSearchScope: wholeSubtree
    loginURL: https://example.com/ldap-login
    customLoginHTML: /var/www/html/ldap-login.html

Utilisation des attributs LDAP dans une extension de services

Les attributs d’un connecteur LDAP ne sont chargés que s’ils sont utilisés dans une évaluation de politique ou définis directement dans les en-têtes.

Ainsi, dans l’exemple de configuration ci-dessous, ldap.groupMembership est utilisé dans une politique d’autorisation.

apps:
  - name: exampleApp
    type: proxy
    routePatterns:
      - /

    # ...

    policies:
      - location: /
        authentication:
          idps:
            - azure
        authorization:
          rules:
            - and:
              - equals: [ "{{azure.authenticated}}", "true" ]
              - contains: [ "{{ldap.groupMembership}}", "cn=Joe Smith,ou=East,dc=MyDomain" ]

    headers:
      - createHeaderSE:
          funcName: CreateHeader
          file: "/etc/maverics/extensions/createHeader.go"

L’attribut ldap.groupMembership peut alors être référencé dans l’extension de services createHeader.go.

/etc/maverics/extensions/createHeader.go

package main

import (
	"net/http"
	"strings"

	"github.com/strata-io/service-extension/orchestrator"
)

// CreateHeader adds a prefix to each group claim.
func CreateHeader(
	api orchestrator.Orchestrator,
	_ http.ResponseWriter,
	_ *http.Request,
) (http.Header, error) {
	logger := api.Logger()
	logger.Debug("se", "building custom header")
	
	sess, err := api.Session()
	if err != nil {
		logger.Error("se", "unable to retrieve session", "error", err.Error())
		return nil, err
	}
	
	groupclaims, err := sess.GetString("ldap.groupMembership")
	if err != nil {
            logger.Error("se", "unable to retrieve string", "error", err.Error())
            return nil, err
	}
	
	splitHeaders := strings.Split(groupclaims, "^")

	var outHeaders []string
	for _, h := range splitHeaders {
		outHeaders = append(outHeaders, "myPrefix-"+h)
	}
	headers := make(http.Header)
	headers["GROUPS"] = []string{strings.Join(outHeaders, "^")}
	return headers, nil
}

Si ldap.groupMembership n’était pas utilisé dans une politique ou un en-tête, il serait vide lorsqu’il est référencé dans l’extension de services.