Asserteur d’identité WebLogic

Le module Maverics Identity Asserter est un module personnalisé d’assertion d’identité WebLogic. Ce module valide le fait qu’une requête provient d’un proxy d’authentification tiers fiable, analyse l’identité de l’utilisateur à partir de l’en-tête de la requête et renvoie un nom distinctif (DN, Distinguished Name) ou un nom court que WebLogic utilisera pour construire son contexte d’identité.

Exigences relatives au serveur

  • Oracle WebLogic 12c
  • Java 8

Installation

Pour installer l’asserteur d’identité, copiez-le dans le répertoire $WL_HOME/server/lib/mbeantypes ($WL_HOME correspond au répertoire d’origine du serveur WebLogic).

  1. Sous le domaine cible, sélectionnez « Security Realms ».
  2. Sélectionnez le domaine cible, par exemple « myrealm », puis sélectionnez « Providers » -> « Authentication ».
  3. Créez un nouveau fournisseur d’authentification de type « MavericsIdentityAsserter ».
  4. Une fois le fournisseur créé, réorganisez les modules de sécurité en déplaçant l’asserteur qui vient d’être créé au début de la liste.
  5. Sélectionnez la valeur SUFFICIENT pour l’indicateur Strata Identity Asserter.
  6. Générez la clé de vérification de la signature encodée au format base64, comme indiqué dans l’exemple ci-dessous.
  7. Sélectionnez l’onglet « Provider Specific » et ajoutez la clé encodée au format base64 que vous avez créée. Clé de vérification de signature
  8. Pour tous les autres modules de sécurité, sélectionnez la valeur SUFFICIENT pour l’indicateur.
  9. Redémarrez le serveur WebLogic.
  10. Testez la fonctionnalité en accédant à l’URL.

Mise à niveau

Pour mettre l’asserteur d’identité à niveau, remplacez la version existante de Maverics Identity Asserter dans le répertoire $WL_HOME/server/lib/mbeantypes par une nouvelle version. Après avoir remplacé le JAR, redémarrez le serveur WebLogic.

Exemple

Cet exemple illustre la manière dont l’orchestrateur peut être utilisé pour authentifier un utilisateur et acheminer le trafic à travers un proxy vers WebLogic. Une fois la requête reçue par WebLogic, l’asserteur d’identité validera la valeur de l’en-tête MAVERICS_USERNAME et construira le contexte d’identité.

La commande suivante peut être exécutée afin de générer une clé privée qui sera utilisée pour signer les jetons JWT. Dans cet exemple, la clé privée générée est stockée dans une base de données secrète dont le nom est webLogicPrivateKey.

openssl genrsa -out wl-private-key.pem 2048

Une fois la clé privée générée, la clé publique utilisée pour vérifier la signature peut être extraite à l’aide de la commande suivante.

openssl rsa -in wl-private-key.pem -outform PEM -pubout -out wl-public-key.pem

Une fois la clé publique extraite, il faut l’encoder en base64 avant de l’ajouter en tant que propriété dans WebLogic. L’encodage Base64 de la clé est nécessaire car WebLogic n’autorise pas les propriétés multi-lignes.

openssl base64 -A -in wl-public-key.pem

Maintenant que la paire de clés a été générée et que les propriétés nécessaires ont été ajoutées à WebLogic, le fichier de configuration Maverics ci-dessous peut être utilisé comme référence pour transmettre une valeur d’en-tête JWT à WebLogic.

apps:
  - name: exampleWebLogic
    type: proxy
    routePatterns:
      - /
    upstream: https://app-internal.example.com
    headers:
      - createHeaderSE:
          funcName: CreateHeader
          file: /etc/maverics/webLogic-createHeader.go
          metadata:
            # userLookupKey is the key that will be used to look up the user's
            # username from the session store. The corresponding value will be passed
            # as the 'sub' claim in the JWT.
            userLookupKey: azure.name
            # privateKeyLookupKey is the key that will be used to retrieve the
            # signing key from the secret store.
            privateKeyLookupKey: webLogicPrivateKey
            # jwtLifetime is the lifetime of the JWT in hours. The value should be
            # set to match the lifetime of a user's session.
            jwtLifetime: 24

    policies:
      - location: /
        authentication:
          idps:
            - azure
        authorization:
          allowAll: true

/etc/maverics/webLogic-createHeader.go

package main

import (
	"errors"
	"fmt"
	"net/http"
	"time"

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

// CreateHeader creates an HTTP header that will be consumed and validated by
// the WebLogic Identity Asserter. The header has a name of 'MAVERICS_USERNAME' and
// a signed JWT as the value.
func CreateHeader(
	api orchestrator.Orchestrator,
	_ http.ResponseWriter,
	_ *http.Request,
) (http.Header, error) {
	logger := api.Logger()
	logger.Debug("se", "creating header for WebLogic")

	metadata := api.Metadata()
	userLookupKey, _ := metadata["userLookupKey"].(string)
	privateKeyLookupKey, _ := metadata["privateKeyLookupKey"].(string)
	jwtLifetime, _ := metadata["jwtLifetime"].(int)

	session, err := api.Session()
	if err != nil {
		return nil, fmt.Errorf("failed to get session: %w", err)
	}
	name, err := session.GetString(userLookupKey)
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve username from session: %w", err)
	}

	secretProvider, err := api.SecretProvider()
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve secret provider: %w", err)
	}
	privateKey := secretProvider.GetString(privateKeyLookupKey)
	if len(privateKey) == 0 {
		return nil, errors.New("private key not found in secret provider")
	}

	jwt, err := api.WebLogic().NewSignedJWT(weblogic.Config{
		RSAPrivateKeyPEM: privateKey,
		Subject:          name,
		Lifetime:         time.Duration(jwtLifetime) * time.Hour,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to construct JWT: %w", err)
	}

	header := make(http.Header)
	header["MAVERICS_USERNAME"] = []string{jwt}
	return header, nil
}