WebLogic Identity Asserter
The Maverics Identity Asserter is a custom WebLogic identity asserter module. This module validates that a request comes from a legitimate third-party authentication proxy, reads in a users’ identity from the request header, and returns either a distinguished name (DN) or a short name which WebLogic will use to build its identity context.
Server requirements
- Oracle WebLogic 12c
- Java 8
Install
To install the identity asserter, copy it to the $WL_HOME/server/lib/mbeantypes
directory ($WL_HOME
is the home directory of the WebLogic server). After copying the
JAR, restart the WebLogic server.
Upgrade
To upgrade the identity asserter, replace the existing Maverics Identity Asserter in
the $WL_HOME/server/lib/mbeantypes
directory with a new version. After replacing the
JAR, restart the WebLogic server.
Configuration options
After installing the JAR, complete the following steps in the WebLogic admin console:
- Under the target domain, select “Security Realms”.
- Select the target realm, e.g. “myrealm”, and then select “Providers” -> “Authentication”.
- Create a new Authentication Provider of type “MavericsIdentityAsserter”.
- Once created, re-order the security modules by moving the newly created asserter to the beginning of the list.
- Configure the flag as
REQUIRED
for Strata Identity Asserter. - Configure the flag for all other security modules as
SUFFICIENT
. - Restart the WebLogic server.
- Test the functionality by accessing the URL.
Example
This example demonstrates how the Orchestrator can be used to authenticate a user and
proxy traffic to WebLogic. Once a request is received by WebLogic, the identity
asserter will validate the MAVERICS_USERNAME
header value and build the identity
context.
In order to generate a private key that will be used to sign JWTs, the following
command can be run. This example stores the generated private key in a secret store
with a name of webLogicPrivateKey
.
openssl genrsa -out wl-private-key.pem 2048
After a private key has been generated, the public key used for verifying the signature can be extracted with the following command.
openssl rsa -in wl-private-key.pem -outform PEM -pubout -out wl-public-key.pem
After the public key has been extracted, base64 encode it before adding it as a property in WebLogic. Base64 encoding the key is a requirement since WebLogic does not permit multi-line properties.
openssl base64 -A -in wl-public-key.pem
Now that the key pair has been generated and the necessary properties have been added to WebLogic, the below Maverics config file can be used as a reference for how to pass a JWT header value to 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
}