Référence REST générique
Un système orchestré REST générique est créé avec un modèle minimal, qui est mis à jour lors de l'exécution à l'aide d'OCI Functions pour mettre à jour le système orchestré avec des classes d'objet, des types de code express et des données de transformation sortantes.
Workflow de haut niveau de repérage de schéma
Le repérage de schéma est le processus par lequel un système orchestré REST générique applique des modèles de fonction OCI pour permettre le repérage du schéma, des classes d'objet, des attributs et des détails de connexion pour la source ou le système géré faisant autorité configuré.
Le repérage de schéma se produit lorsqu'un système orchestré est créé dans Oracle Access Governance. Les workflows simplifiés pour les scénarios Day0 et DayN sont détaillés dans les tableaux suivants.
Day0 Workflow
| N° d'étape | Tâche/opération | Description |
|---|---|---|
| 1 | Créer un système orchestré |
Créez un système orchestré à l'aide de la console de gouvernance Oracle Access. Le système orchestré est créé avec les détails de la fonction OCI que vous avez créée pour renvoyer les détails de la source ou du système géré faisant autorité requis. En fonction des détails saisis dans le système orchestré, l'opération suivante est créée.
|
| 2 | Valider l'exécution de l'opération |
L'opération de validation est exécutée et, en fonction du modèle de schéma configuré, extrait le schéma, y compris les classes d'objet suivantes :
Le modèle de test de configuration est appelé pour valider la connectivité avec le système géré. |
| 3 | Opération après validation |
Une fois l'opération de validation exécutée, les opérations suivantes sont créées :
|
DayN Workflow
| N° d'étape | Tâche/opération | Description |
|---|---|---|
| 1 | Sélectionnez Extraire les attributs sur la page Attributs d'identité d'Oracle Access Governance. Pour plus d'informations, reportez-vous à Extraction des derniers attributs personnalisés. | Une opération de découverte de schéma est créée dans le système orchestré |
| 2 | Exécution de l'opération de repérage de schéma | L'opération de repérage de schéma est exécutée et, en fonction du modèle de schéma configuré, extrait le schéma, y compris les classes d'objet suivantes :
|
| 3 | Actualiser la page Attributs d'identité | La liste des attributs personnalisés commence à afficher les nouveaux attributs personnalisés pour la classe d'objet d'identité. |
Attributs de schéma obligatoires de repérage de schéma REST générique
Lors du repérage de schéma, certains attributs obligatoires doivent être renvoyés dans la sortie de schéma.
Classe d'objet d'identité
Les attributs obligatoires qui doivent être renvoyés dans la sortie de schéma pour la classe d'objet Identity sont les suivants :
- UID
- nom
- firstName
- middleName
- lastName
- displayName
- employeeType
- titre
- empNo
- statut
- jobCode
- département
- risque
- lieu
- service
- managerUid
- managerLogin
- organizationUid
- organizationName
- pays
- postalCode
- territory
[
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "email",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "firstName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "middleName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "lastName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "displayName",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "employeeType",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "title",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "empNo",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "status",
"dataType": "FLAG",
"usage": [
"READ"
]
},
{
"name": "jobCode",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "state",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "risk",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "location",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "department",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "managerUid",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "managerLogin",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "organizationUid",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "organizationName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "country",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "postalCode",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "territory",
"dataType": "TEXT",
"usage": [
"READ"
]
}
]
Classe d'objet non-identité
Les attributs obligatoires qui doivent être renvoyés dans le cadre de la sortie de schéma pour la classe d'objet Non-Identité sont les suivants :
- UID
- nom
[
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
Schéma du modèle de schéma
Pour prendre en charge le repérage de schéma, vous devez créer le modèle de schéma à l'aide de l'outline prise en charge.
Schéma
{
"schemaTemplates":[
{
"type": "", // Type of entity i.e. either object class type i.e. "ACCOUNT", "ENTITLEMENT", "TARGETACCOUNT" or "LOOKUP"
"name": "", // Name of entity i.e. name of either object class or lookup
"displayName": "", // display name of entity
"data": {
// Key-value pairs representing lookup data if any, or else it will be missing from here.
}
"attributes": [
{
"name": "", // Name of attribute
"dataType": "", // Either of TEXT, DATE, NUMBER, DECIMAL_NUMBER, FLAG
"nature": [ // Adjectives i.e. One or more of "REQUIRED", "MULTIVALUED", "SENSITIVE". It can be missing from here if nothing applies.
],
"usage": [ // Verbs i.e. One or more of "READ", "PROVISION". It can be missing from here if nothing applies.
],
"relationship": { // Entity relationship details
"relatedTo": "", // Entity name in relationship with
"relatedBy": "", // Attribute to define the relation
"relationshipProperties": [ // Additional relationship properties
{
"name": "", // Name of additional attribute
"dataType": "", // Either of TEXT, DATE, NUMBER, DECIMAL_NUMBER, FLAG
"nature": [ // Only READ_ONLY is possible, or else it will be missing from here
]
}
]
},
"outboundTransformation": { // Outbound transformation script if applicable, or it will be missing from here
"script": "" // Script to execute for transformation
},
"uiProperties": { // ARMD if applicable, or it will be missing from here
"inputType": "" // Either of Auto, User, Admin
"widget": "", // Widget to use on UI i.e. Either of Text, Password, Number, Date, SelectOne, RepeatableFieldSet, CheckboxSet
"title": "", // Title to use on UI
"labelHint": "", // Labelhint to use on UI
"minLength": {SOME_POSITIVE_NUMBER},
"maxLength": {SOME_POSITIVE_NUMBER},
"defaultValues": [ // Default values if applicable, or it will be missing from here
]
}
}
]
}
]
}
Sortie du modèle de schéma
La sortie du modèle de schéma est renvoyée en tant que document JSON.
Sortie du modèle de schéma
<ReferenceBase>/functions/grc-schema-template/src/main/resources/schema/applications/<YourApplicationName>/TEMPLATE.json) :{
"schemaTemplates": [
{
"type": "ACCOUNT",
"name": "UserAsIdentity",
"displayName": "User As Identity",
"attributes": [
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "email",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "firstName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "middleName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "lastName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "displayName",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "employeeType",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "title",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "empNo",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "jobCode",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "state",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "risk",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "location",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "department",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "managerUid",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "organizationUid",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "organizationName",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "postalCode",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "territory",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "usageLocation",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "country",
"dataType": "TEXT",
"usage": [
"READ"
],
"relationship": {
"relatedTo": "countries",
"relatedBy": "uid"
}
},
{
"name": "managerLogin",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "preferredLanguage",
"dataType": "TEXT",
"usage": [
"READ"
],
"relationship": {
"relatedTo": "languages",
"relatedBy": "uid"
}
},
{
"name": "status",
"dataType": "FLAG",
"usage": [
"READ"
]
}
]
},
{
"type": "ENTITLEMENT",
"name": "GroupAsEntitlement",
"displayName": "Group As Entitlement",
"attributes": [
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
},
{
"type": "TARGETACCOUNT",
"name": "UserAsAccount",
"displayName": "User As Account",
"attributes": [
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ",
"PROVISION"
],
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "User ID",
"labelHint": "User ID",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "user.getPrimaryEmail()"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "User Name",
"labelHint": "User Name",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "email",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "user.getPrimaryEmail()"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "Email",
"labelHint": "Email",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "firstName",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "user.getName().getGivenName()"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "First Name",
"labelHint": "First Name",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "lastName",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "user.getName().getFamilyName()"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "Last Name",
"labelHint": "Last Name",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "displayName",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "[user.getName().getGivenName(), user.getName().getFamilyName()].filter(element => { return element !== null && element.length > 0}).join(' ')"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "Display Name",
"labelHint": "Display Name",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "mailNickname",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "[user.getName().getGivenName(), user.getName().getFamilyName()].filter(element => { return element !== null && element.length > 0}).join('')"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "Nick Name",
"labelHint": "Nick Name",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "password",
"dataType": "TEXT",
"nature": [
"REQUIRED",
"SENSITIVE"
],
"usage": [
"READ",
"PROVISION"
],
"uiProperties": {
"inputType": "User",
"widget": "Password",
"title": "Password",
"labelHint": "Password",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "usageLocation",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"relationship": {
"relatedTo": "countries"
},
"outboundTransformation": {
"script": "user.getLocation() != null ? transformationUtil.getLookupCode(agcs_tenant_id, agcs_target_id, 'countries', user.getLocation()) : null"
},
"uiProperties": {
"inputType": "Auto",
"widget": "SelectOne",
"title": "Location",
"labelHint": "Location",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "city",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"uiProperties": {
"inputType": "User",
"widget": "Text",
"title": "City",
"labelHint": "City",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "country",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"relationship": {
"relatedTo": "countries",
"relatedBy": "uid"
},
"outboundTransformation": {
"script": "user.getAddresses() != null && user.getAddresses().size() > 0 ? transformationUtil.getLookupCode(agcs_tenant_id, agcs_target_id, 'countries', user.getAddresses().get(0).getCountry()) : null"
},
"uiProperties": {
"inputType": "Auto",
"widget": "SelectOne",
"title": "Country",
"labelHint": "Country",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "managerLogin",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"uiProperties": {
"inputType": "Admin",
"widget": "Text",
"title": "Manager Login",
"labelHint": "Manager Login",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "preferredLanguage",
"dataType": "TEXT",
"usage": [
"READ",
"PROVISION"
],
"relationship": {
"relatedTo": "languages",
"relatedBy": "uid"
},
"uiProperties": {
"inputType": "Admin",
"widget": "SelectOne",
"title": "Language",
"labelHint": "Language",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "userType",
"dataType": "TEXT",
"usage": [
"READ"
]
},
{
"name": "status",
"dataType": "FLAG",
"usage": [
"READ",
"PROVISION"
],
"outboundTransformation": {
"script": "true"
},
"uiProperties": {
"inputType": "Auto",
"widget": "Text",
"title": "Status",
"labelHint": "Status",
"minLength": 1,
"maxLength": 256
}
},
{
"name": "groups",
"dataType": "TEXT",
"nature": [
"MULTIVALUED"
],
"usage": [
"READ",
"PROVISION"
],
"relationship": {
"relatedTo": "GroupAsEntitlement",
"relatedBy": "uid",
"relationshipProperties": []
},
"uiProperties": {
"inputType": "Admin",
"widget": "RepeatableFieldSet",
"title": "Groups",
"labelHint": "Groups",
"minLength": 1,
"maxLength": 256
}
}
]
},
{
"name": "countries",
"type": "LOOKUP",
"attributes": [
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
},
{
"name": "languages",
"type": "LOOKUP",
"attributes": [
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
}
]
}
Plan du modèle de demande
Pour prendre en charge les demandes vers la source ou le système géré faisant autorité requis, vous devez créer votre modèle de demande à l'aide de l'outline prise en charge.
Plan de la demande
{
"id": "", // request id
"name": "", // request name
"paginationType": "", // either of OFFSET,PAGE_INCREMENT,PAGE_TOKEN
"method": "", // either of GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE
"uri": {
"scheme": "", // request URI scheme either of http, https
"host": "", // request URI host
"path": "" // request URI path
},
"queryParameters": [
{
"name": "", // queryParameter name
"value": "" // queryParameter value
}
],
"headers": [
{
"name": "", // request header name
"value": "" // request header value
}
],
"body": {
"type": "text",
"textBody": {} // json request body
},
"subRequests": [ // subrequest if any
{
"id": "", // subrequest id
"name": "", // subrequest name
"paginationType": "", // either of OFFSET,PAGE_INCREMENT,PAGE_TOKEN
"method": "", // either of GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE
"uri": {
"scheme": "", // subrequest URI scheme either of http, https
"host": "", // subrequest URI host
"path": "" // subrequest URI path
},
"queryParameters": [
{
"name": "", // subrequestqueryParameter name
"value": "" // subrequest queryParameter value
}
],
"headers": [
{
"name": "", // subrequest header name
"value": "" // subrequest header value
}
],
"body": {
"type": "text",
"textBody": {} // json subrequest body
}
}
]
}
Prise en charge de la pagination
- DÉCALAGE
- PAGE_INCREMENT
- PAGE_TOKEN
| Type de pagination | Prérequis | Configuration |
|---|---|---|
| DÉCALAGE | L'API REST que vous intégrez à Oracle Access Governance doit prendre en charge la pagination OFFSET lors du renvoi d'une réponse. |
Si
|
| PAGE_INCREMENT | L'API REST que vous intégrez à Oracle Access Governance doit prendre en charge la pagination PAGE_INCREMENT lors du renvoi d'une réponse. |
Si
|
| PAGE_TOKEN | L'API REST que vous intégrez à Oracle Access Governance doit prendre en charge la pagination PAGE_TOKEN lors du renvoi d'une réponse. |
Si
|
Le nom d'un paramètre de pagination particulier peut varier en fonction de l'API REST avec laquelle vous êtes connecté. Par exemple, pour la pagination OFFSET, les paramètres peuvent être les suivants :
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}ou{"name": "beginIndex", "value": "<EL>currentOffset</EL>"}
{"name": "increment", "value": "<EL>limit</EL>"}
Vous devez utiliser le nom spécifié par votre API, mais utiliser les valeurs comme indiqué dans cet article.Sortie du modèle de demande
La sortie du modèle de demande est renvoyée en tant que document JSON pour les entités et les opérations définies.
Sortie du modèle de demande
La sortie du modèle de demande ressemblera à celle fournie dans l'implémentation de référence (<ReferenceBase>/functions/grc-schema-template/src/main/resources/request/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json) :
Par exemple, à partir de l'implémentation de référence :
- EntityName: UserAsIdentity
- Opération : GET
{
"id": "1",
"name": "Get User As Identity By ID",
"method": "GET",
"uri": {
"scheme": "<<SCHEME>>",
"host": "<<HOST>>",
"path": "/admin/v1/Users/<EL>attributes.get('uid').get(0)</EL>"
},
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "<<CREDENTIALS>>"
}
]
}
- EntityName: UserAsIdentity
- Opération : RECHERCHE
{
"id": "1",
"name": "Search Users As Identity sort by displayName",
"paginationType": "OFFSET",
"method": "GET",
"uri": {
"scheme": "<<SCHEME>>",
"host": "<<HOST>>",
"path": "/admin/v1/Users"
},
"queryParameters": [
{
"name": "startIndex",
"value": "<EL>currentOffset</EL>"
},
{
"name": "count",
"value": "<EL>limit</EL>"
},
{
"name": "sortBy",
"value": "displayName"
}
],
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "<<CREDENTIALS>>"
}
]
}
Plan du modèle de réponse
Pour prendre en charge le format de réponse pour les données d'identité et de compte, vous devez créer votre modèle de réponse à l'aide de l'outline prise en charge.
Plan de réponse
{
"items": "", // items json path
"attributes": [
{
"name": "", // attribute name
"value": "" // attribute value json path
},
{
"name": "", // attribute name for subrequest response
"responseOfSubRequestId": "", // subrequest id
"items": "", // items json path for subrequest response
"subAttributes": [ // sub attributes for subrequest response
{
"name": "", // subrequest response attribute name
"value": "" // subrequest response attribute value json path
}
]
}
]
}
Sortie du modèle de réponse
La sortie du modèle de réponse est renvoyée en tant que document JSON pour les entités et les opérations définies.
Sortie du modèle de réponse
La sortie du modèle de réponse sera similaire à celle fournie dans l'implémentation de référence (<ReferenceBase>/functions/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json) :
Par exemple, à partir de l'implémentation de référence :
- EntityName: UserAsIdentity
- Opération : GET
{
"attributes": [
{
"name": "uid",
"value": "<JP>$.id</JP>"
},
{
"name": "name",
"value": "<JP>$.userName</JP>"
},
{
"name": "email",
"value": "<JP>$.emails[?(@.primary == true)].value</JP>"
},
{
"name": "firstName",
"value": "<JP>$.name.familyName</JP>"
},
{
"name": "lastName",
"value": "<JP>$.name.givenName</JP>"
},
{
"name": "displayName",
"value": "<JP>$.displayName</JP>"
},
{
"name": "usageLocation",
"value": "<JP>$.addresses[?(@.type == 'work')].country</JP>"
},
{
"name": "country",
"value": "<JP>$.addresses[?(@.type == 'work')].country</JP>"
},
{
"name": "managerLogin",
"value": "<JP>$.['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'].manager.value</JP>"
},
{
"name": "preferredLanguage",
"value": "<JP>$.preferredLanguage</JP>"
},
{
"name": "status",
"value": "<JP>$.active</JP>"
}
]
}
- EntityName: UserAsIdentity
- Opération : RECHERCHE
{
"items": "<JP>$.Resources[*]</JP>",
"attributes": [
{
"name": "uid",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].id</JP>"
},
{
"name": "name",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].userName</JP>"
},
{
"name": "email",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].emails[?(@.primary == true)].value</JP>"
},
{
"name": "firstName",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].name.familyName</JP>"
},
{
"name": "lastName",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].name.givenName</JP>"
},
{
"name": "displayName",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].displayName</JP>"
},
{
"name": "usageLocation",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].addresses[?(@.type == 'work')].country</JP>"
},
{
"name": "country",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].addresses[?(@.type == 'work')].country</JP>"
},
{
"name": "managerLogin",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'].manager.value</JP>"
},
{
"name": "preferredLanguage",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].preferredLanguage</JP>"
},
{
"name": "status",
"value": "<JP>$.Resources[<EL>currentIndex</EL>].active</JP>"
}
]
}
Autorisation de base - Exemple de code de création de jeton
Si vous utilisez une autorisation de base avec votre système orchestré REST générique, vous devrez créer un jeton d'autorisation. L'exemple de code qui suit donne un exemple de code de cette fonction :
Exemple de code de création de jeton
public static String getAuthorizationValue(Config config) {
String TOKEN_PREFIX_BASIC = "Basic ";
try {
String vaultJsonValue =
VaultUtil.getDataFromVault(
config.getAuthenticationDetail().get("secretId"),
config.getAuthenticationDetail().get("region"));
String username = VaultUtil.getAttributeValueFromJson(vaultJsonValue, "username");
String password = VaultUtil.getAttributeValueFromJson(vaultJsonValue, "password");
String authHeader = username.concat(":").concat(password);
return TOKEN_PREFIX_BASIC
+ Base64.getEncoder()
.encodeToString(authHeader.getBytes(StandardCharsets.UTF_8));
} catch (UnsupportedEncodingException | JsonProcessingException e) {
System.err.println("Exception occurred while getting secret from vault. " + e.getMessage());
throw new RuntimeException("Exception occurred while getting secret from vault", e);
}
}
// secretId and region value will come from config.yaml file
// username and password value will come from vault secret which has been configured in above steps.
OAuth Autorisation - Exemple de code de création de jeton
Si vous utilisez l'autorisation OAuth avec votre système orchestré REST générique, vous devrez créer un jeton d'autorisation. Les exemples qui suivent donnent un exemple de code de cette fonction :
Exemple de code de création de jeton
Pour un système orchestré IDCS :
<SampleBase>/grc-serverless-function-samples/idm-agcs-serverless-multi-application-sample/grc-commons/src/main/java/com/oracle/idm/agcs/grc/fn/commons/provider/IDCSAuthenticationProvider.java./*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
*/
package com.oracle.idm.agcs.grc.fn.commons.provider;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.oracle.idm.agcs.grc.fn.commons.config.ConnectedSystemConfig;
import com.oracle.idm.agcs.grc.fn.commons.exception.ProcessingFailedException;
import com.oracle.idm.agcs.icfconnectors.commons.util.VaultUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Base64;
public class IDCSAuthenticationProvider extends AuthenticationProvider {
@Override
public String getAuthorizationValue(ConnectedSystemConfig connectedSystemConfig) {
String url =
connectedSystemConfig
.getAuthenticationDetail()
.get("scheme")
.concat("://")
.concat(connectedSystemConfig.getAuthenticationDetail().get("host"))
.concat(connectedSystemConfig.getAuthenticationDetail().get("path"));
String requestBody = "grant_type=client_credentials&scope=urn%3Aopc%3Aidm%3A__myscopes__";
String authHeader;
try {
String vaultJsonValue = VaultUtil.getDataFromVault(connectedSystemConfig.getAuthenticationDetail().get("secretId"), connectedSystemConfig.getAuthenticationDetail().get("region"));
String clientCode = VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientCode");
String clientSecret = VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientSecret");
authHeader = clientCode.concat(":").concat(clientSecret);
} catch (UnsupportedEncodingException | JsonProcessingException e) {
System.err.println("Exception occurred while getting secret from vault. " + e.getMessage());
throw new ProcessingFailedException(
"Exception occurred while getting secret from vault", e);
}
HttpClient client = HttpClient.newBuilder().build();
String connectorProxyHost = System.getProperty(CONNECTOR_PROXY_HOST);
String connectorProxyPort = System.getProperty(CONNECTOR_PROXY_PORT);
if (null != connectorProxyHost
&& !connectorProxyHost.trim().isEmpty()
&& null != connectorProxyPort
&& !connectorProxyPort.trim().isEmpty()) {
System.out.println(
MessageFormat.format(
"connectorProxyHost {0} and connectorProxyPort {1} is available in system property",
connectorProxyHost, connectorProxyPort));
try {
client =
HttpClient.newBuilder()
.proxy(
ProxySelector.of(
new InetSocketAddress(
connectorProxyHost, Integer.parseInt(connectorProxyPort))))
.build();
} catch (NumberFormatException exception) {
System.err.println("connectorProxyPort value is not integer : "+exception);
}
}
final HttpRequest request =
HttpRequest.newBuilder()
.uri(URI.create(url))
.header(HEADER_NAME_CONTENT_TYPE, HEADER_VALUE_CONTENT_TYPE_FORM_URL_ENCODED)
.header(
HEADER_NAME_AUTHORIZATION,
TOKEN_PREFIX_BASIC
+ Base64.getEncoder()
.encodeToString(authHeader.getBytes(StandardCharsets.UTF_8)))
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response;
try {
response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
System.err.println(
"IDCSAuthenticationProvider Auth Token API HttpRequest failed due to IOException."
+ e.getMessage());
throw new ProcessingFailedException(
"IDCSAuthenticationProvider Auth Token API HttpRequest failed due to IOException.", e);
} catch (InterruptedException e) {
System.err.println(
"IDCSAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException."
+ e.getMessage());
throw new ProcessingFailedException(
"IDCSAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException.",
e);
}
System.err.println(
"IDCSAuthenticationProvider Auth Token API HttpResponse is :: " + response.body());
JsonNode jsonNode;
try {
jsonNode = objectMapper.readTree(response.body());
} catch (JsonProcessingException e) {
System.err.println(
"IDCSAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.");
throw new ProcessingFailedException(
"IDCSAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.", e);
}
return TOKEN_PREFIX_BEARER.concat(jsonNode.get(ACCESS_TOKEN_ATTRIBUTE).textValue());
}
}
Pour le système orchestré AzureAD :
<SampleBase>/grc-serverless-function-samples/idm-agcs-serverless-multi-application-sample/grc-commons/src/main/java/com/oracle/idm/agcs/grc/fn/commons/provider/AzureAdAuthenticationProvider.java./*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
*/
package com.oracle.idm.agcs.grc.fn.commons.provider;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.oracle.idm.agcs.grc.fn.commons.config.ConnectedSystemConfig;
import com.oracle.idm.agcs.grc.fn.commons.exception.ProcessingFailedException;
import com.oracle.idm.agcs.icfconnectors.commons.util.VaultUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class AzureAdAuthenticationProvider extends AuthenticationProvider {
@Override
public String getAuthorizationValue(ConnectedSystemConfig connectedSystemConfig) {
String url =
connectedSystemConfig
.getAuthenticationDetail()
.get("scheme")
.concat("://")
.concat(connectedSystemConfig.getAuthenticationDetail().get("host"))
.concat(connectedSystemConfig.getAuthenticationDetail().get("path"));
String requestBody;
try {
String vaultJsonValue = VaultUtil.getDataFromVault(connectedSystemConfig.getAuthenticationDetail().get("secretId"), connectedSystemConfig.getAuthenticationDetail().get("region"));
requestBody =
"client_id="
+ VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientCode")
+ "&client_secret="
+ VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientSecret")
+ "&grant_type="
+ connectedSystemConfig.getAuthenticationDetail().get("grantType")
+ "&scope="
+ connectedSystemConfig.getAuthenticationDetail().get("scope");
} catch (UnsupportedEncodingException | JsonProcessingException e) {
System.err.println("Exception occurred while getting secret from vault. " + e.getMessage());
throw new ProcessingFailedException(
"Exception occurred while getting secret from vault", e);
}
final HttpClient client = getHttpClient(connectedSystemConfig);
final HttpRequest request =
HttpRequest.newBuilder()
.uri(URI.create(url))
.header(AuthenticationProvider.HEADER_NAME_CONTENT_TYPE, AuthenticationProvider.HEADER_VALUE_CONTENT_TYPE_FORM_URL_ENCODED)
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response;
try {
response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to IOException."
+ e.getMessage());
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to IOException.", e);
} catch (InterruptedException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException."
+ e.getMessage());
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException.",
e);
}
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpResponse is :: " + response.body());
JsonNode jsonNode;
try {
jsonNode = AuthenticationProvider.objectMapper.readTree(response.body());
} catch (JsonProcessingException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.");
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.",
e);
}
return AuthenticationProvider.TOKEN_PREFIX_BEARER.concat(jsonNode.get(AuthenticationProvider.ACCESS_TOKEN_ATTRIBUTE).textValue());
}
private HttpClient getHttpClient(ConnectedSystemConfig connectedSystemConfig) {
if (null == connectedSystemConfig.getAuthenticationDetail().get("proxyHost")
|| null == connectedSystemConfig.getAuthenticationDetail().get("proxyPort")) {
return HttpClient.newHttpClient();
}
return HttpClient.newBuilder()
.proxy(
ProxySelector.of(
new InetSocketAddress(
connectedSystemConfig.getAuthenticationDetail().get("proxyHost"),
Integer.parseInt(connectedSystemConfig.getAuthenticationDetail().get("proxyPort")))))
.build();
}
}