Agent de liaison JavaScript Plugins
Création de plugins JavaScript pour Bridge Agent
Cette documentation détaille le développement de plugins JavaScript pour l'agent IBM Security Verify Bridge. Les plugins JavaScript sont utilisés pour mettre en œuvre une logique personnalisée d'authentification des utilisateurs et de récupération des attributs pour des sources d'attributs autres que le LDAP principal.
Procédure de haut niveau
Assurez-vous d'avoir accès à un locataire IBM Security Verify (ISV) et suivez les étapes décrites dans les sections suivantes :
Architecture de haut niveau

À partir de la version 1.0.14
, l'agent de pont prend en charge deux types différents de sources d'attributs :
- LDAP primaire
- LDAP non primaire
Par défaut, l'agent de pont effectue l'authentification de l'utilisateur à l'aide de l'adresse primary LDAP
. L'authentification et la récupération des attributs sont intégrées et ne nécessitent pas de plugin JavaScript.
Pour les cas d'utilisation avancés, il peut être souhaitable d'utiliser les sources d'attributs non-primary LDAP
. Elles permettent de mettre en œuvre une logique personnalisée de recherche d'attributs et d'authentification à l'aide du site JavaScript plugin
. L'agent bridge prend en charge les sources d'attributs LDAP non primaires suivantes :
- LDAP
- Oracle Database
- PostgreSQL
- IBM Db2
Les liaisons avec ces sources d'attributs sont créées au moyen d'une configuration JavaScript ( jsconfig
). La logique de gestion de la récupération des attributs et de l'authentification des utilisateurs doit être mise en œuvre au moyen d'un plugin JavaScript ( jsplugin
).
Ce guide détaille le site création d'un jsconfig
pour configurer une connexion à votre source d'attributs et le site l'élaboration d'un jsplugin
pour mettre en œuvre la logique d'extraction d'attributs et d'authentification de l'utilisateur.
Terminologie
Terme | Autres noms | Définition |
---|---|---|
Onprem Agent | Bridge Agent , ldap agent , agent , identity agent | L'agent qui s'exécute surprem et s'interface avec un ou plusieurs sites onprem attribute sources pour effectuer l'authentification de l'utilisateur et la recherche d'attributs. |
Bridge Service | agentbridgesvc , Agent Bridge Service | Microservice ISV chargé de traiter les demandes de charge de travail interne et les réponses reçues de onprem agent . |
Support Service | agentbridgesupsvc , Agent Bridge Support Service | Microservice ISV responsable de la gestion des configurations des agents. |
Data binding | javascript binding | Une connexion à un site attribute source établie via des utilitaires golang et exposée via des fonctions javascript pour être traitée par un site javascript plugin . |
Javascript plugin | jsplugin | Un programme javascript écrit par un utilisateur d' IBM Security Verify Bridge. Il met en œuvre une logique de recherche d'attributs et d'authentification de l'utilisateur pour le compte de onprem agent par le biais de diverses bases de données spécifiques data bindings . |
Plugin configuration | jsconfig | Configuration requise par onprem agent pour établir une liaison de données avec attribute source au nom de javascript plugin . |
Primary LDAP | auth LDAP | Répertoire LDAP principal pour lequel l'authentification par nom d'utilisateur et mot de passe est effectuée. Peut être remplacé par la propriété authenticationSource . |
Attribute source | data source , attribute store , data store , database | Source de données sur laquelle l'authentification peut être effectuée et à partir de laquelle les attributs de l'utilisateur sont récupérés. Il peut s'agir de : LDAP , Db2 , PostgreSQL et OracleDB . |
Authentication source | auth source | Une adresse attribute source par rapport à laquelle l'authentification doit être effectuée. Est le primary LDAP par défaut. |
Installation de l'agent Bridge
Les plugins sont une nouvelle fonctionnalité de v1.0.14
de l'agent Bridge qui est fourni en tant que conteneur Docker. Voir Installation et configuration de Verify Bridge sur Docker.
Annuaires importants
Le site Bridge Agent
recherche les fichiers de configuration et les plugins JavaScript dans les deux répertoires suivants :
Répertoire | Description | Type de fichier |
---|---|---|
/go/src/jsconfig | Ce répertoire contient les fichiers jsconfig . Ils définissent les détails de la liaison et identifient le jsplugin. N.B. La passerelle peut charger un maximum de 10 plugins JavaScript. Les 10 premières configurations de ce répertoire seront chargées par ordre alphabétique, les autres seront ignorées. | .json |
/go/src/jsplugins | Ce répertoire contient jsplugins , de petits programmes JavaScript qui gèrent l'authentification et la récupération des attributs de l'utilisateur | .js |
/cert | Utilisé pour MTLS avec les plugins LDAP . Le pont sera ici en /cert/<clientCertLabel>_cert.pem /cert/<clientCertLabel>_key.pem | .pem |
Placez vos fichiers de configuration et de plugin dans leurs répertoires respectifs. Les montages Docker bind peuvent être utilisés pour simplifier ce processus. Voir l'exemple docker-compose.yml
pour l'utilisation des montages bind
# Example docker-compose.yml
version: "3"
services:
verify-bridge:
image: icr.io/isv-saas/verify-bridge:latest
container_name: bridge_agent
volumes:
- ./jsconfig:/go/src/jsconfig:ro
- ./jsplugins:/go/src/jsplugins:ro
- ./cert/:/cert:ro
environment:
TRACE: "true"
LICENSE_ACCEPT: "yes"
TENANT_URI: "https://tenant.verify.ibm.com"
CLIENT_ID: "12345678-1234-1234-1234-123456789012"
CLIENT_SECRET: "ABCDEFGHIJ"
restart: always
La section bind mount
- ./jsconfig:/go/src/jsconfig:ro
- ./jsplugins:/go/src/jsplugins:ro
- ./cert/:/cert:ro
Monte les répertoires locaux ./jsconfig
, ./jsplugins
, ./cert
aux emplacements correspondants dans le conteneur. L'option ro
monte ces répertoires en lecture seule. Il s'agit d'une bonne pratique de sécurité pour les montages bind, car elle garantit que les conteneurs en cours d'exécution ne peuvent pas apporter de modifications au système de fichiers de l'hôte.
Définir les configurations des plugins
Les configurations des plugins doivent être placées dans le répertoire /go/src/jsconfig
et doivent être des documents JSON valides. Les propriétés suivantes sont disponibles :
Configurations Standard
Propriété | Définition |
---|---|
pluginName | Le nom du plugin. L'agent Bridge recherchera le plugin correspondant sur le site /go/src/jsplugins/<pluginName>.js . |
pluginType | Le type de liaison. Doit être l'un des suivants : ldap , db2 , postgres ou oracle . |
executionOrder | L'ordre dans lequel le plugin doit être exécuté par rapport aux autres plugins. Exécuté du plus petit au plus grand, c'est-à-dire que 2 est exécuté avant 3 . |
hardFail | Définissez true si vous voulez que le pont renvoie si le plugin ne s'exécute pas ou renvoie autre chose que SUCCESS . |
isAuthenticationSource | Définir à true si ce plugin est destiné à être le authentication source . C I.e que l'authentification par nom d'utilisateur/mot de passe est effectuée par rapport à cette source d'attributs. En fixant cette valeur à true , le plugin se comportera automatiquement comme si hardFail était également vrai. Lorsque true , l'authentification n'est pas effectuée par rapport au LDAP primaire, mais la recherche d'attributs est toujours effectuée. Pour désactiver entièrement la recherche LDAP primaire (y compris la recherche d'attributs), vous devez remplacer disablePrimaryLdapLookup par true . NB Seul UN (1) plugin peut être une source d'authentification. |
disablePrimaryLdapLookup | Désactive le LDAP primaire. Ce paramètre doit être défini lorsque isAuthenticationSource est true et que vous souhaitez également désactiver la recherche d'attributs à partir du LDAP principal. |
custom | Cette section est facultative et peut inclure des propriétés personnalisées à transmettre à jsplugins au moment de l'exécution. |
Configurations de la reliure
Les configurations de liaison sont utilisées pour établir une liaison avec la source d'attributs et définir les détails de la connexion de la liaison. La colonne LDAP or DB
indique si la propriété est attendue pour les plugins LDAP
ou DB
( db2
, postgres
, oracle
).
Propriété | LDAP ou DB | Définition | Exemple |
---|---|---|---|
connectionString | Base de données | La chaîne de connexion utilisée pour établir une liaison avec cette source de données particulière. Utilisé uniquement pour db2 , postgres , et oracle . Voir chaînes de connexion. | Voir chaînes de connexion. |
maxPoolSize | BOTH | Nombre maximal de connexions dans le pool de connexions. | 50 |
minPoolSize | BOTH | Nombre minimum de connexions dans le pool de connexions. | 10 |
agedTimeout | BOTH | Délai en secondes avant qu'une connexion ne soit abandonnée. | 60 |
maxIdleTime | BOTH | Durée maximale d'inactivité d'une connexion avant qu'elle ne soit rejetée. | 10 |
bindDn | LDAP | Le DN de liaison utilisé pour établir une liaison LDAP. | cn=admin,dc=ibm,dc=com |
bindPassword | LDAP | Le mot de passe de liaison utilisé pour établir une liaison LDAP. | pTms!REJECs@hzdNEGZ8 |
uris | LDAP | Un tableau d'URI de serveurs LDAP. Il est utilisé pour le basculement, si le premier serveur de la matrice tombe en panne, le suivant sera essayé, etc. N.B. Le protocole est important ici. Si vous souhaitez utiliser TLS, vous devez utiliser le protocole ldaps:// . Les autres paramètres TLS seront ignorés si ce paramètre n'est pas défini. | ldaps://localhost:636 |
filter | LDAP | Le filtre à utiliser lors de la recherche LDAP. | (|(|(objectclass=ePerson)(objectclass=person))(objectclass=User)) |
userObjectClasses | LDAP | Les classes d'objets utilisateur. | top,Person,organizationalPerson,inetOrgPerson |
selector | LDAP | Sélecteurs utilisés lors de la recherche LDAP. | objectClass,cn,sn,givenName,userPassword,streetAddress,seeAlso,mobile |
baseDn | LDAP | Le DN de base utilisé lors d'une recherche LDAP standard. La logique du plugin peut remplacer cela si nécessaire. | dc=ibm,dc=com |
caCert | LDAP | Le certificat de l'autorité de certification utilisé pendant TLS pour vérifier l'authenticité du certificat présenté par le serveur LDAP pendant TLS. | -----BEGIN CERTIFICATE-----\nMIIDazCCAlOgA... |
insecureSkipVerify | LDAP | Ignorer la vérification du certificat TLS. N.B ne doit être utilisé que dans des environnements de test et non en production. | false |
tlsMinVersion | LDAP | Définir la version TLS minimale autorisée. Voir la version minimale de tls. | 771 |
clientCertLabel | LDAP | Utilisé pendant le MTLS. Vous devez définir ici une étiquette pour le certificat et la clé du client à présenter au serveur LDAP. L'agent de liaison recherchera cette information à l'adresse suivante /cert/<clientCertLabel>_cert.pem /cert/<clientCertLabel>_key.pem | ldap.client |
Chaînes de connexion
Les chaînes de connexion s'appliquent aux sources d'attributs de la base de données ( db2
, oracle
et postgres
). Les chaînes de connexion ont chacune leur propre format et peuvent être utilisées pour spécifier des détails de connexion tels que TLS, les délais d'attente et d'autres paramètres spécifiques à la base de données. Veuillez consulter la documentation de votre source de données pour obtenir une liste complète des options de chaîne de connexion disponibles. Voici des exemples de chaînes de connexion :
Oracle Database
oracle://system:[email protected]:1521/XE?CONNECTION TIMEOUT=5
Base de données Postgres
host=host.docker.internal port=8788 dbname=postgres user=postgres password=postgrespassword connect_timeout=5
Base de données Db2
HOSTNAME=host.docker.internal;PORT=50000;UID=db2inst1;PWD=db2_password;DATABASE=usersdb
Version TLS minimale
La propriété tlsMinVersion
définit la version TLS minimale autorisée. Il doit s'agir d'un nombre entier. Le tableau suivant présente une correspondance entre ces nombres entiers et leur version TLS.
Version TLS | Entier |
---|---|
v1.0 | 769 |
v1.1 | 770 |
v1.2 (par défaut) | 771 |
v1.3 | 772 |
Utilisez un nombre entier pour définir la version minimale de TLS, par exemple "tlsMinVersion": 770
. L'omission de cette propriété ou la définition d'une mauvaise valeur entraînera la définition par défaut de 771 (TLS version 1.2 ).
Exemple de configuration LDAP
Voici un exemple de LDAP jsconfig
qui utilise MTLS.
{
"pluginName": "ldap",
"pluginType": "ldap",
"executionOrder": 2,
"hardFail": false,
"authenticationSource": {
"isAuthenticationSource": false,
"disablePrimaryLDAPLookup": false
},
"bindingConfig": {
"bindDn": "cn=admin,dc=ibm,dc=com",
"bindPassword": "pass",
"uris": ["ldaps://host.docker.internal:8636", "http://localhost:8389"],
"maxPoolSize": 50,
"agedTimeout": 60,
"connectTimeout": 5,
"filter": "(|(|(objectclass=ePerson)(objectclass=person))(objectclass=User))",
"userObjectClasses": "top,Person,organizationalPerson,inetOrgPerson",
"selector": "objectClass,cn,sn,givenName,userPassword,streetAddress,seeAlso,mobile",
"baseDn": "dc=ibm,dc=com"
"tlsConfig": {
"caCert": "-----BEGIN CERTIFICATE-----\nMIIDazCCAlOgAwIB...\n-----END CERTIFICATE-----\n",
"insecureSkipVerify": false,
"tlsMinVersion": 771,
"clientCertLabel": "ldap.client"
}
}
}
Exemple de configuration de la base de données
Voici un exemple de PostgreSQL jsconfig
.
{
"pluginName": "PgPlug",
"pluginType": "postgres",
"executionOrder": 1,
"hardFail": true,
"authenticationSource": {
"isAuthenticationSource": true,
"disablePrimaryLDAPLookup": true
},
"bindingConfig": {
"connectionString": "host=host.docker.internal port=8788 dbname=postgres user=postgres password=postgrespassword connect_timeout=5",
"maxPoolSize": 50,
"minPoolSize": 10,
"agedTimeout": 60,
"maxIdleTime": 10
},
"custom": {
"table": "users"
}
}
Développer des plugins JavaScript
Les plugins JavaScript se composent de trois concepts importants :
Les objets d'entrée fournissent des instructions au plugin, la charge de travail opérationnelle à traiter, l'objet de travail actuel (résultats des opérations précédentes) et une copie de la configuration du plugin. Elles contiennent toutes les données nécessaires pour effectuer le traitement de votre plugin.
Fonction de liaison Les fonctions de liaison sont les fonctions et les classes mises à disposition pour interagir avec la liaison de données. Ils peuvent être utilisés pour effectuer des requêtes et extraire des attributs de la source de données.
objet outputData
L'objet output est un objet spécial qui doit être créé par votre script. L'objet de sortie doit se conformer à une structure spécifique.
Objets d'entrée
Lorsque le script est exécuté, trois adresses input objects
sont transmises au script :
Objet d'entrée | Description |
---|---|
requestParameters | La demande reçue de l'ISV. |
workingObject | Paramètres déjà récupérés du LDAP primaire ou des plugins précédents dans l'ordre d'exécution. |
pluginConfig | La configuration du plugin telle qu'elle existe dans le répertoire ./jsconfig . Plus l'ajout de l'objet userAttributes . |
N.B Ces objets d'entrée sont transmis au script du plugin sous forme de chaînes, ils doivent être analysés en JSON avant d'être utilisés :
let rp = JSON.parse(requestParameters);
let wo = JSON.parse(workingObject);
let pc = JSON.parse(pluginConfig);
requestParameters
Il s'agit de la charge utile de la demande récupérée auprès de l'ISV. Il possède les propriétés suivantes :
Les propriétés importantes sont les suivantes
Propriété | Description |
---|---|
addressedTo | Le nom du module, qui sera toujours ldapauth . |
enqueuedTime | Heure à laquelle l'opération a été mise en file d'attente. |
opération | L'opération à effectuer par le plugin. Il peut s'agir de password-verify ou de password-change . |
paramètres | Un ensemble de paramètres correspondant à l'opération spécifique. |
exemple de vérification de mot de passe
{
"addressedTo": "ldapauth",
"enqueuedTime": "2023-10-15 05:15:36.769",
"id": "jobUuId",
"operation": "password-verify",
"parameters": {
"password": "Passw0rd",
"username": "Scott"
}
}
exemple de changement de mot de passe
{
"addressedTo": "ldapauth",
"enqueuedTime": "2023-10-15 05:15:36.769",
"id": "jobUuId",
"operation": "password-change",
"parameters": {
"oldpassword": "OldPassw0rd",
"newpassword": "NewPassw0rd",
"username": "Scott"
}
}
N.B Vous ne devez traiter que password-change
pour votre source d'authentification.
workingObject
Le site workingObject
contient des attributs qui ont déjà été récupérés lors de consultations précédentes dans la chaîne de consultation. Il a la structure suivante :
Propriété | Description |
---|---|
groupes | Un tableau des groupes ISV auxquels l'utilisateur appartient. |
utilisateur | Un objet dont les objets enfants correspondent aux attributs renvoyés pour l'utilisateur. |
workingObject Exemple
{
"groups": [],
"user": {
"dn": ["uid=scott,ou=Verify,dc=ibm,dc=com"],
"mail": ["[email protected]"],
"mobile": ["+61 2345 6789"],
"sn": ["Administrator"],
"uid": ["scott"]
}
}
N.B. La valeur de l'attribut user doit être contenue dans un tableau, comme dans l'exemple ci-dessus.
pluginConfig
L'objet pluginConfig
contient simplement une copie exacte de la configuration du plugin qui s'exécute ainsi que l'objet userAttributes
.
Les userAttributes
sont les attributs que ce plugin devra récupérer. Ils sont injectés dans la configuration lorsque le script est appelé.
pluginConfig Exemple
// pluginConfig value that will be passed to the PgPlug.js plugin
{
"pluginName": "PgPlug",
"pluginType": "postgres",
"executionOrder": 1,
"hardFail": true,
"authenticationSource": {
"isAuthenticationSource": true,
"disablePrimaryLDAPLookup": true
},
"bindingConfig": {
"connectionString": "host=host.docker.internal port=8788 dbname=postgres user=postgres password=postgrespassword connect_timeout=5",
"maxPoolSize": 50,
"minPoolSize": 10,
"agedTimeout": 60,
"maxIdleTime": 10
},
"userAttributes": [ // These attributes sourced from ISV
"phone",
"address",
"sn"
]
"custom": {
"table": "users"
}
}
pluginConfig userAttributes
userAttributes
est la représentation sous forme de tableau de chaînes des attributs de l'utilisateur demandés par l'ISV.
let pc = JSON.parse(pluginConfig);
let requestedAttributes = pc.userAttributes; // Array of attributes requested for this user
Fonctions de liaison
Les fonctions de liaison sont des fonctions/classes fournies à votre script qui vous permettent d'interfacer avec votre source d'attributs via la liaison de connexion établie.
Il existe différentes fonctions de liaison pour databases
et ldap
:
- Fonctions de liaison avec les bases de donnéesdb2, postgres, oracle)
- Fonctions de liaison LDAP
Consignateur
Une fonction de liaison avec l'enregistreur est fournie. Pour enregistrer, ajoutez ce qui suit au début de votre script de plugin
importClass(logger);
La classe logger offre les fonctions de journalisation suivantes :
Fonction | Description |
---|---|
trace(message) | Journal avec niveau trace. |
debug(message) | Log avec le niveau debug. |
info(message) | Journal avec informations sur le niveau. |
warn(message) | Journal avec niveau d'avertissement. |
error(message) | Journal avec erreur de niveau. |
Exemple d'enregistreur
importClass(logger); // Import logger at the top of your plugin script
// Log with logging level info
logger.info(`Plugin script logging with level info`)
Niveau de journalisation
Le niveau de journalisation est donné à titre indicatif et apparaîtra dans la sortie standard de l'agent bridge.
time="2023-10-24T11:15:47Z" level=<log level> msg="log message" func=pkg.binding.logger.log
Fonctions de liaison avec la base de données
Pour accéder à database binding functions
, placez l'importation suivante au début du script de votre plugin.
// Place this at the top of your Plugin.js file
importClass(database);
Ceci importera l'objet javascript database
qui a les fonctions suivantes définies sur lui :
database.query()
database.query()
accepte
database.query(serverName, query);
Paramètres:
serverName
(String
): Spécifie le nom du serveur interne de la base de données sur laquelle la requête sera effectuée. Elle peut être réglée sur la valeurserverName
, qui est une variable prédéfinie contenant la valeur correcte.query
(Object
): Un objet de la forme :
{
"sql": "query string",
"args": [
["argument 1", "argument 2"]
]
}
Les arguments seront remplacés par des marqueurs de paramètres.
Voici un exemple d'appel complet à database.query
:
// Db2 style substitution using the `?` symbol
result = database.query(serverName, {
"sql": "SELECT * FROM USERS WHERE ID = ? AND PASSWORD = ?",
"args": [
["scott", "Password"]
]
});
Le symbole ?
ci-dessus est un parameter marker
est un substitut des valeurs de la propriété args
.
N.B: les différents types de bases de données utilisent des marqueurs de paramètres différents :
Marqueurs de paramètres
Base de données | Marqueur de paramètre |
---|---|
Db2 | ? |
Oracle Database | :1 |
PostgreSQL | $1 |
Voici le même exemple, mais en utilisant le style PostgreSQL
parameter markers
:
// Postgres style substitution using the `$1` symbol
result = database.query(serverName, {
"sql": "SELECT * FROM USERS WHERE ID = $1 AND PASSWORD = $1",
"args": [
["scott", "Password"]
]
});
Objet du résultat
Lorsque la requête est renvoyée, elle renvoie l'un des éléments suivants :
Objet du résultat
Propriété | Description |
---|---|
rowsAffected | Nombre de lignes modifiées par l'opération. |
lignes | Un tableau de Object . Chaque objet représente une ligne renvoyée par la requête. Chaque propriété de l'objet correspond à une colonne et à sa valeur. |
{
"rowsAffected": 0, // Rows changed
"rows": [ // Array of objects representing each row. Each property represents a column and its value
{
"CREATED_ON": "2023-11-02T00:00:00Z",
"EMAIL": "[email protected]",
"ISLOCKED": false,
"LAST_LOGIN": "2023-10-24T00:00:00Z",
"PASSWORD": "scottpass",
"PGATTR": "scottpsec1234",
"USERNAME": "Scott",
"USER_ID": 2
}
]
}
Si aucune ligne n'est renvoyée, null
sera renvoyé pour rows
.
Exemple :
{"rowsAffected":0,"rows":null}
Objet d'erreur
Un objet d'erreur est renvoyé lorsque database.query
échoue.
Propriété | Description |
---|---|
Erreur | La chaîne d'erreur. |
Exemple d'objet de résultat d'erreur :
{ "error": "the error string" }
Un objet d'erreur est renvoyé dans les cas où la requête n'a pas été exécutée correctement.
database.execute()
Exécute une requête SQL paramétrée avec des arguments optionnels et renvoie le nombre de lignes affectées. Cette fonction fonctionne de la même manière que la fonction database.query
mais est utilisée pour INSERT, UPDATE, DELETE, DROP
.
result = database.execute(serverName, query)
Pour une description de ces paramètres, voir les paramètres d'interrogation de la base de données.
Voir l'objet résultat pour une description des objets result
et error
.
Exemple
result = database.execute(serverName,
{
"sql": "DELETE FROM TEST_DB_BINDING WHERE ID = ?",
"args": [
["test_key001"],
["test_key002"]
]
}
);
Comme pour database.query
, des substitutions sont possibles.
database.ping()
La fonction ping est une simple requête qui permet de vérifier si la base de données est vivante.
result = database.ping(serverName);
- Passer le paramètre
serverName
comme avec database.query()
Un résultat sain renvoie les informations suivantes :
{"rowsAffected":0,"rows":null}
Dans le cas contraire, un objet d'erreur sera renvoyé.
Fonctions de liaison LDAP
Les fonctions de liaison LDAP sont fournies par deux classes d'aide :
Classe | Description |
---|---|
ldapUserLookupHelper | Rechercher des attributs et procéder à l'authentification de l'utilisateur associé à un identifiant d'utilisateur. |
ldapAttributeUtil | Créer, modifier, supprimer et rechercher des attributs en fonction de leur DN. |
Voir la section " quickstart" pour des exemples d'utilisation de ces classes par les jsplugins.
Aide à la recherche d'utilisateurs
Pour accéder aux fonctions de liaison LDAP, placez l'importation suivante en tête de votre script de plugin
importClass(ldapUserLookupHelper);
Cet import expose les classes suivantes :
Classe | Présentation |
---|---|
UserLookupHelper | Fournit des fonctions pour la recherche d'un utilisateur. |
Utilisateur | Représente un utilisateur et fournit des fonctions pour les opérations de l'utilisateur. |
Référence de la classe UserLookupHelper
Le UserLookupHelper fournit des classes pour aider à l'authentification et à la recherche d'attributs d'utilisateurs. Des exemples de démarrage rapide sont fournis.
Initialiser UserLookupHelper
avec :
// Initialize new user lookup helper
let pc = JSON.parse(pluginConfig);
let configName = `${pc.pluginName}_config`
let userLookupHelper = new UserLookupHelper(configName);
Le paramètre configName
est une chaîne de caractères qui doit être fournie sous la forme <pluginName>_config
. L'exemple de code ci-dessus extrait l'adresse pluginName
de l'objet pluginConfig
et la formate de manière appropriée.
Méthodes de UserLookupHelper
Méthode | Type de retour | Description |
---|---|---|
isReady() | booléen ou erreur | true lorsqu'il est prêt. Objet d'erreur sur l'erreur. |
createUser(userName, dn, password, firstName, LastName ) | Utilisateur | Crée un utilisateur LDAP. Renvoie un objet User . |
getUser(userName) | Utilisateur | Renvoie un objet User avec l'objet User correspondant. |
getUserByNativeId(nativeId) | Utilisateur | Renvoie un objet User . nativeId représente un nom complet (distinguished name). |
deleteUser(userName) | booléen, null | Supprime l'utilisateur avec le nom d'utilisateur userName . Renvoie true si la suppression a été effectuée avec succès. Peut renvoyer null en cas d'erreur. |
Toutes les recherches susmentionnées (à l'exception de createUser
et getUserByNativeId
) seront effectuées en utilisant la configuration de recherche LDAP définie dans la configuration de liaison LDAPuserIdentifier, baseDn, etc.).
getUserByNativeId
utilise un DN complet pour rechercher l'utilisateur et contourne donc userIdentifier
.
Référence de l'objet utilisateur
L'objet utilisateur représente un utilisateur. Il fournit des méthodes pour les opérations des utilisateurs telles que l'authentification par mot de passe et la recherche d'attributs.
Initialisation
Cet objet ne doit pas être initialisé manuellement, mais renvoyé par une fonction UserLookupHelper.
let ulh = new UserLookupHelper(configName);
user = ulh.getUser(`Scott`) // returned user is a User object for the user with id `Scott`
Méthodes d'utilisateur
Méthode | Types de retour | Description |
---|---|---|
hasError() | booléen | Renvoie true si l'objet utilisateur présente une erreur. Cette erreur peut être déclenchée pendant la fonction de recherche de l'utilisateur ( getUser , getUserByNativeId , createUser ). N.B Vous devez vérifier cette valeur avant d'appeler toute autre méthode sur un objet User . |
getError() | chaîne | Renvoie la valeur de l'objet Error (le message d'erreur). |
authentifier(mot de passe) | bool, null | Renvoie true si la chaîne password est correcte pour l'utilisateur. |
getId() | chaîne de caractères, null | Renvoie l' userId/username de l'utilisateur. |
getNativeId() | chaîne de caractères, null | Renvoie le nom distinctif complet (dn) de l'utilisateur. |
getAttributeNames() | Tableau | Renvoie un tableau des noms d'attributs de cet utilisateur. Remarque : cette opération ne renvoie pas les valeurs de ces attributs. |
getAttribute(attrName) | chaîne de caractères, null | Renvoie la valeur de l'attribut attrName . null si aucun attribut correspondant n'a été trouvé. Remarque: si l'attribut attrName renvoie un tableau, cette fonction renvoie le premier élément de ce tableau. Si vous souhaitez renvoyer ce tableau, utilisez la méthode getAttributes . |
getAttributes(attrName) | Tableau, null | Renvoie un tableau de valeurs correspondant au nom de l'attribut attrName . Si la valeur de attrName n'est pas un tableau, elle sera renvoyée sous la forme d'un tableau à un seul membre contenant cette valeur. |
attributeExists(attrName) | booléen | Renvoie true si l'attribut utilisateur attrName existe. |
Référence de la classe AttributeUtil
Les classes ldapAttributeUtil
peuvent être utilisées pour effectuer des opérations personnalisées de recherche et de manipulation d'attributs. Un exemple de démarrage rapide est fourni.
Importer la classe d'aide avec :
// Add import to the top of your javascript plugin
importClass(ldapAttributeUtil);
Cet import expose les classes suivantes :
Classe | Présentation |
---|---|
LdapAttributeUtil | Utilisé pour la création et la récupération d'attributs LDAP. |
Attribut | Représente un tableau de valeurs d'attributs correspondant à un ID d'attribut. |
Attributs | Représente un tableau d'objets Attribut. |
SearchResult | Représente une entrée de résultat de recherche. |
NamingEnumeration | Classe permettant d'énumérer les données d'un site type . |
LdapAttributeResult | Représente la réponse à l'opération de l'attribut util . |
Référence de LdapAttributeUtil
Le site LdapAttributeUtil
est utilisé pour la création et l'extraction d'attributs LDAP. Initialiser LdapAttributeUtil
en utilisant le nom de la configuration du plugin :
// Initialize attribute util
let pc = JSON.parse(pluginConfig);
let configName = `${pc.pluginName}_config`
let attrUtil = new LdapAttributeUtil(configName);
Méthodes de LdapAttributeUtil
Méthode | Types de retour | Description |
---|---|---|
Init() | LdapAttributeResult | Effectue un contrôle de santé de la source d'attributs LDAP et renvoie un objet LdapAttributeResult. En cas d'échec du contrôle de santé, la propriété result de cet objet est un objet Error. |
isReady() | booléen | Effectue un contrôle de santé sur la source d'attributs LDAP. Renvoie true lorsqu'il est en bonne santé. |
addAttributeValue(dn, attributeName, attributeValue) | LdapAttributeResult | Ajoute un attribut LDAP attributeName avec la valeur attributeValue à dn . |
createSubContext(dn, attributes) | LdapAttributeResult | Crée le sous-contexte dn avec les attributs attributes . Pour plus d'informations sur la manière de spécifier les attributs d'entrée, voir le format des attributs. |
getAttributeValue(dn, attributeNames) | LdapAttributeResult | Récupère les valeurs des attributs de dn . Le paramètre d'entrée attributeNames doit être un tableau codé en JSON de noms d'attributs à récupérer. Par exemple [``pommes'', 'banane'']. |
removeAttribute(dn, attributeName, attributeValue) | LdapAttributeResult | Supprime l'attribut attributeName avec la valeur attributeValue de dn . |
search(dn, filter) | LdapAttributeResult | Rechercher les entrées sur dn avec le filtre filter . Par exemple : (objectclass=*) . |
setAttributeValue(dn, attributeName, attributeValue) | LdapAttributeResult | Définit l'attribut attributeName de dn à la valeur attributeValue . |
attributes
format
attributes
formatSpécifiez les attributs sous la forme d'un objet JSON qui associe le nom de l'attribut à un tableau de ses valeurs. Exemple :
// createSubContext(dn, attributes)
attrUtil.createSubContext("ou=newOu1", {"objectClass": ["top", "organizationalUnit"]}
Référence de l'attribut
L'objet Attribut représente un tableau de valeurs d'attributs.
Propriété | Type | Description |
---|---|---|
identificateur | chaîne | L'ID de l'attribut |
attr | Tableau | Un tableau de valeurs d'attributs |
Méthode | Types de retour | Description |
---|---|---|
constructor(id, attr) | Attribut | Crée un objet Attribute avec l'ID id et un tableau de valeurs d'attributs attr . |
isOrdered() | booléen | Retourne toujours true . |
getID() | chaîne | Retourne la propriété id de l'attribut. |
get(idx) | chaîne | Renvoie la valeur de l'attribut indexée par idx . |
getAll() | NamingEnumeration des valeurs d'attributs | Renvoie une adresse NamingEnumeration des valeurs d'attribut que cet objet représente. |
taille() | entier | Renvoie le nombre de valeurs que cet objet représente. |
contains attrVal ) | booléen | Renvoie true lorsque cet attribut contient la valeur attrVal . |
Documentation de référence des attributs
L'objet Attributs représente un tableau d'objets Attributs.
Propriété | Type | Description |
---|---|---|
attrs | Objet | Objet dont les propriétés correspondent à celles des objets Attribut. |
Méthode | Types de retour | Description |
---|---|---|
constructeur(attrs) | Attributs | Prend un tableau d 'objets JSON attr et renvoie un objet Attributes. |
isCaseIgnored() | booléen | Retourne toujours false . |
taille() | entier | Renvoie le nombre d'attributs représentés par l'objet. |
get attrID ) | Attribut | Renvoie un attribut spécifique avec l'ID d'attribut attrID . |
getIDs() | NamingEnumeration de string | Renvoie les ID des attributs représentés par cet objet. |
getAll() | NamingEnumeration of Attribut | Renvoie les valeurs des attributs représentés par cet objet. |
attr
Format d'objet JSON
attr
Format d'objet JSON{
"name": "attributeName", // The attribute name
"attrs": [] // Array of attribute values
}
Référence NamingEnumeration
Le site NamingEnumeration
propose des fonctions permettant de compter dans un tableau d'objets. Le tableau sous-jacent est accessible directement via la propriété results
. next()
renvoie l'élément suivant de l'énumération.
Propriété | Type | Description |
---|---|---|
l'année en cours | Le type dans lequel le résultat de next() est enveloppé. | |
wrapObj | booléen | Lorsque true est le résultat de next() enveloppé dans type . |
résultats | Tableau | Un tableau de résultats à énumérer. |
curIdx | entier | L'indice d'énumération actuel. |
Méthode | Types de retour | Description |
---|---|---|
constructor(results, wrapObj, type) | NamingEnumeration | Accepte un tableau de results . Définir wrapObj à true si results doit être enveloppé dans un type avant d'être renvoyé. |
hasMore() | booléen | Renvoie true si l'énumération comporte plus d'éléments. |
suivant() | Résultat de recherche, Attribut, Chaîne, Objet | Renvoie l'élément suivant de l'énumération. Il est du type attendu. |
Référence du SearchResult
Représente une entrée de résultat de recherche.
Propriété | Type | Description |
---|---|---|
entrée | chaîne | Entrée du résultat de la recherche. |
entry.attributes | Attributs | Attributs retournés. |
entry.name | chaîne | Entrées d'attributs renvoyées. |
Référence LdapAttributeResult
La classe LdapAttributeResult
représente une réponse d'opération d'attribut. Propriétés définies pour cette classe :
Propriété | Type | Description |
---|---|---|
cfgName | chaîne | Nom de la configuration du plugin. Il se présente sous la forme <pluginName>_config . |
résultat | Objet | Le résultat de l'opération. |
namingEum | NamingEnumeration | Enumération des résultats de la recherche sous forme d'objets SearchResult |
attrs | Attributs | Attributs de SearchResult. |
Méthodes définies pour la classe LdapAttributeResult
:
Méthode | Types de retour | Description |
---|---|---|
getAttributes() | Attributs | Renvoie les attributs demandés par LdapAttributeUtil.getAttributeValue(). |
getNamingEnumeration() | NamingEnumeration de SearchResult | Renvoie le résultat NamingEnumeration l'opération LdapAttributeUtil.search(). |
isSuccessful() | booléen | Renvoie true si l'opération s'est terminée par une erreur. |
hasError() | booléen | Renvoie true si l'opération s'est terminée par une erreur. |
getError() | Erreur | Renvoie l'erreur qui s'est produite. |
getNamingException() | Erreur | Alias pour getError() . Renvoie l'erreur qui s'est produite. |
outputData Référence de l'objet
Votre script de plugin doit se terminer par la définition d'un objet appelé outputData
. L'objet outputData
représente une charge utile de réponse à renvoyer à l'ISV. Il possède les propriétés suivantes :
Propriété | Définition |
---|---|
status.result | Le code de résultat. |
status.message | Un message d'état facultatif. |
parameters.groups | Tableau d' objets de groupes ISV auxquels un utilisateur doit appartenir. |
utilisateur | Un objet dont les objets enfants représentent les paramètres renvoyés par cette opération. Remarque : la valeur de chaque attribut doit être un tableau. |
Exemple
// Define this object at the end of your plugin script
outputData = {
status: {
result: "Success",
message: "",
},
parameters: {
groups: [
{
name: "AGroup1",
id: "AGroup1Id1",
},
{
name: "AGroup2",
id: "AGroup2Id2",
},
],
user: {
attribute1: ["value for attribute 1"],
attribute2: ["value for attribute 2"],
},
},
};
Objet de groupe
Propriété | Description |
---|---|
nom | Le site displayName du groupe ISV. |
identificateur | Le site id du groupe ISV. |
Vous pouvez obtenir des identifiants de groupe via le point d'accès ISV /v2.0/Groups
.
Exemple :
curl --request GET \
--url https://tenant.verify.ibm.com/v2.0/Groups \
--header 'authorization: Bearer <token>'
// Response from /v2.0/Groups
{
"displayName": "developer",
"meta": {
"created": "2023-03-15T04:52:32Z",
"lastModified": "2023-03-15T05:06:57Z"
},
"id": "60500081MT",
"urn:ietf:params:scim:schemas:extension:ibm:2.0:Group": {
"totalMembers": 1,
"groupType": "reserved",
"description": ""
}
}
La définition d'objets de groupe permet d'intégrer l'utilisateur renvoyé dans le groupe ISV correspondant.
Démarrage rapide
Cette section contient des exemples de scripts de plugins simplistes/minimaux. Pour utiliser ces exemples, vous devez d'abord définir une configuration de plugin pour pointer vers le script et établir correctement la liaison.
- Échafaudage minimal
- Exemple de recherche simple LDAP
- Exemple d'authentification simple LDAP
- Exemple d'utilitaire d'attribut LDAP
Échafaudage minimal LDAP
L'échafaudage suivant est un plugin LDAP incomplet. La logique d'authentification et de récupération des attributs peut être ajoutée dans la section TODO
.
// LDAP minimal scaffold
// Import binding functions
importClass(logger);
importClass(ldapUserLookupHelper);
// Parse Input Objects
let rp = JSON.parse(requestParameters);
let wo = JSON.parse(workingObject);
let pc = JSON.parse(pluginConfig);
// Initialize the UserLookupHelper
let configName = `${pc.pluginName}_config`;
let userLookupHelper = new UserLookupHelper(configName);
// Define the output object to be returned
let output = {
status: {
result: "",
message: "",
},
parameters: {
groups: [],
user: {},
},
};
// Inserting main logic inside a function allows for `return` to be used in order to break execution
let process = () => {
// TODO: Insert plugin logic here
};
process();
// End script by defining the outputData object
let outputData = output;
Exemple de recherche simple LDAP
// simpleLdapLookup.js - Simple
// Import binding functions
importClass(logger);
importClass(ldapUserLookupHelper);
// Parse Input Objects
let rp = JSON.parse(requestParameters);
let wo = JSON.parse(workingObject);
let pc = JSON.parse(pluginConfig);
// Initialize the UserLookupHelper
let configName = `${pc.pluginName}_config`;
let userLookupHelper = new UserLookupHelper(configName);
// Define the output object to be returned
let output = {
status: {
result: "",
message: "",
},
parameters: {
groups: [],
user: {},
},
};
// Inserting main logic inside a function allows for `return` to be used in order to break execution
let process = () => {
// Get the requested user
let userName = rp.parameters.username;
// Get the requested attributes
let requestedAttributes = pc.userAttributes;
if (!Array.isArray(requestedAttributes)) {
requestedAttributes = Array.from([requestedAttributes]);
}
// Get the user
let user = userLookupHelper.getUser(userName);
// Check if user has error
if (user.hasError()) {
// Get the error object
let errorString = user.getError();
// Log error
logger.info(`Unable to get user: ${errorString}`);
// Update the output object with the error
output.status.result = "ERROR";
output.status.message = errorString;
// Return will break execution and cause the output object to return with the above error
return;
}
// Get the requested attributes
requestedAttributes.forEach((attrName) => {
// Retrieve this attribute from the user
output.parameters.user[attrName] = user.getAttribute(attrName);
});
// Set the status to successful
output.status.result = "SUCCESS";
};
process();
// End script by defining the outputData object
let outputData = output;
Exemple d'authentification simple LDAP
Cet exemple ajoute l'authentification à l'exemple de recherche simple LDAP.
Veillez à identifier ce plugin comme authentication source
dans la configuration du plugin:
// simpleLdapAuth_config.json
"authenticationSource": {
"isAuthenticationSource": true,
"disablePrimaryLDAPLookup": true
},
// simpleLdapAuth.js
// Import binding functions
importClass(logger);
importClass(ldapUserLookupHelper);
// Parse Input Objects
let rp = JSON.parse(requestParameters);
let wo = JSON.parse(workingObject);
let pc = JSON.parse(pluginConfig);
// Initialize the UserLookupHelper
let configName = `${pc.pluginName}_config`;
let userLookupHelper = new UserLookupHelper(configName);
// Define the output object to be returned
let output = {
status: {
result: "",
message: "",
},
parameters: {
groups: [],
user: {},
},
};
// Inserting main logic inside a function allows for `return` to be used in order to break execution
let process = () => {
// Get the requested user
let userName = rp.parameters.username;
let password = rp.parameters.password;
// Get the requested attributes
let requestedAttributes = pc.userAttributes;
if (!Array.isArray(requestedAttributes)) {
requestedAttributes = Array.from([requestedAttributes]);
}
// Get the user
let user = userLookupHelper.getUser(userName);
// Check if user has error
if (user.hasError()) {
// Get the error object
let errorString = user.getError();
// Log error
logger.info(`Unable to get user: ${errorString}`);
// Update the output object with the error
output.status.result = "ERROR";
output.status.message = errorString;
// Return will break execution and cause the output object to return with the above error
return;
}
// Perform authentication
if (user.authenticate(password) !== true) {
output.status.result = "PASSWORD_NOT_VALID";
output.status.message = "Invalid user password";
return;
}
// Get the requested attributes
requestedAttributes.forEach((attrName) => {
// Retrieve this attribute from the user
output.parameters.user[attrName] = user.getAttribute(attrName);
});
// Set the status to successful
output.status.result = "SUCCESS";
};
process();
// End script by defining the outputData object
let outputData = output;
Notez que cet exemple ne diffère de l'exemple de recherche LDAP simple que par l'ajout de l'authentification :
// Perform authentication
if (user.authenticate(password) !== true) {
output.status.result = "PASSWORD_NOT_VALID";
output.status.message = "Invalid user password";
return;
}
Exemple d'utilitaire d'attribut LDAP
Cet exemple montre comment utiliser la classe LdapAttributeUtil pour définir, récupérer et rechercher des attributs LDAP. La sortie est donnée par l'intermédiaire de l'enregistreur. L' objet outputData ne contient aucun attribut.
// LdapAttributeUtil Example
// Import binding functions
importClass(logger);
importClass(ldapUserLookupHelper);
importClass(ldapAttributeUtil);
// Parse Input Objects
let rp = JSON.parse(requestParameters);
let wo = JSON.parse(workingObject);
let pc = JSON.parse(pluginConfig);
// Initialize the UserLookupHelper
let configName = `${pc.pluginName}_config`;
let userLookupHelper = new UserLookupHelper(configName);
let attrUtil = new LdapAttributeUtil(configName)
// Define the output object to be returned
let output = {
status: {
result: "",
message: "",
},
parameters: {
groups: [],
user: {},
},
};
// Inserting main logic inside a function allows for `return` to be used in order to break execution
let process = () => {
if (!attrUtil.isReady()) {
output.status.result = "ERROR";
output.status.message = "Attribute Utility failed healthcheck";
return;
}
// Random integer for sub context
let rand = Math.floor(Math.random() * 100);
let newOu = `ou=newOu${rand}`;
// Create a new sub context
let resultCreateSubContextErr = attrUtil.createSubContext(newOu, {"objectClass": ["top", "organizationalUnit"]});
if (resultCreateSubContextErr.hasError()) {
let error = resultCreateSubContextErr.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Created sub context entry ${newOu}`);
// Create an attribute
let attributeName = "description";
let attributeValue = "1234";
let attributeValue2 = "4567";
let resultAddAttributeValue = attrUtil.addAttributeValue(newOu, attributeName, attributeValue);
if (resultAddAttributeValue.hasError()) {
let error = resultAddAttributeValue.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Added attribute ${attributeName} with value ${attributeValue} to the entry ${newOu}`);
// Validate that the entry has been written successfully by retrieving the value
let resultGetAttributeValue = attrUtil.getAttributeValue(newOu, ['description']);
if (resultGetAttributeValue.hasError()) {
let error = resultGetAttributeValue.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
// Check value is correct
let retrievedAttr = resultGetAttributeValue.getAttributes().get(attributeName).get(0);
if (retrievedAttr !== attributeValue) {
let error = `Retrieved attribute ${retrievedAttr}, expected ${attributeValue}`;
logger.info(error);
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Retrieved attribute ${retrievedAttr}, matches expected ${attributeValue}`);
// Modify the new entries description value
let resultSetAttributeValue = attrUtil.setAttributeValue(newOu, attributeName, attributeValue2);
if (resultSetAttributeValue.hasError()) {
let error = resultSetAttributeValue.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Set entry ${newOu} attribute ${attributeName} to value ${attributeValue2}`);
// Remove the description value
let resultRemoveAttribute = attrUtil.removeAttribute(newOu, attributeName, attributeValue2);
if (resultRemoveAttribute.hasError()) {
let error = resultRemoveAttribute.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Removed attribute ${attributeName} with value ${attributeValue2} from entry ${newOu}`);
// Perform a search
let resultSearch = attrUtil.search(newOu, "(objectclass=top)");
if (resultSearch.hasError()) {
let error = resultSearch.getError();
output.status.result = "ERROR";
output.status.message = error;
return;
}
logger.info(`Removed attribute ${attributeName} with value ${attributeValue2} from entry ${newOu}`);
// Enumerate through the search results
let searchEnumerator = resultSearch.getNamingEnumeration();
let i = 0;
while (searchEnumerator.hasMore()) {
let searchResult = searchEnumerator.next();
logger.info(`Search results [${i}]: ${searchResult.getName()}`);
}
// Set the status to successful
output.status.result = "SUCCESS";
};
process();
// End script by defining the outputData object
let outputData = output;
Updated about 1 month ago