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 du service des fonctions pour OCI afin de mettre à jour le système orchestré avec des classes d'objet, des types de consultation et des données de transformation sortantes.
Flux de travail de haut niveau de détection de schéma
La détection 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 la détection du schéma, des classes d'objet, des attributs et des détails de connexion pour la source faisant autorité ou le système géré configuré.
La détection de schéma se produit lorsqu'un système orchestré est créé dans Oracle Access Governance. Les flux de travail simplifiés pour les scénarios Day0 et DayN sont détaillés dans les tableaux suivants.
Flux de travail Day0
| Étape n° | Tâche/opération | Description |
|---|---|---|
| 1 | Créer un système orchestré |
Créer un système orchestré à l'aide de la console Oracle Access Governance. Le système orchestré est créé avec les détails de la fonction OCI que vous avez créée pour retourner les détails à partir de la source faisant autorité ou du système géré requis. En fonction des détails entrés dans le système orchestré, l'opération suivante est créée.
|
| 2 | Valider l'exécution de l'opération |
L'opération Validate 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 post-validation |
Une fois l'opération Validate exécutée avec succès, les opérations suivantes sont créées :
|
Flux de travail DayN
| Étape n° | Tâche/opération | Description |
|---|---|---|
| 1 | Sélectionnez Extraire les attributs dans la page Attributs d'identité d'Oracle Access Governance. Voir Extraire les derniers attributs personnalisés pour plus de détails. | Une opération de détection de schéma est créée dans le système orchestré |
| 2 | Exécution de l'opération de détection de schéma | L'opération de détection de schéma est exécutée et, sur la base 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 détection de schéma REST générique
Lors de la détection du schéma, certains attributs obligatoires doivent être retournés dans la sortie du schéma.
Classe d'objet d'identité
Les attributs obligatoires qui doivent être retournés dans la sortie de schéma pour la classe d'objet Identity sont les suivants :
- uid
- name
- courriel
- firstName
- middleName
- lastName
- displayName
- employeeType
- titre
- empNo
- statut
- jobCode
- État
- risque
- emplacement
- service
- managerUid
- managerLogin
- organizationUid
- organizationName
- pays
- Code postal
- territoire
[
{
"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 de non-identité
Les attributs obligatoires qui doivent être retournés dans la sortie du schéma pour la classe d'objet Non-Identity sont les suivants :
- uid
- name
[
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
Structure du modèle de schéma
Pour prendre en charge la détection de schéma, vous devez créer votre modèle de schéma à l'aide de l'outline prise en charge.
Structure du 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 retourné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"
]
}
]
}
]
}
Structure du modèle de demande
Pour prendre en charge les demandes à la source faisant autorité ou au système géré requis, vous devez créer votre modèle de demande à l'aide de la structure prise en charge.
Structure 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
- COMPENSATION
- PAGE_INCREMENT
- PAGE_TOKEN
| Type de pagination | Conditions requises | Configuration |
|---|---|---|
| COMPENSATION | L'API REST que vous intégrez à Oracle Access Governance doit prendre en charge la pagination OFFSET lors du retour 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 retour 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 retour d'une réponse. |
Si
|
Le nom d'un paramètre de pagination particulier peut varier selon 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 utilisez les valeurs décrites dans cet article.Sortie du modèle de demande
La sortie du modèle de demande est retournée en tant que document JSON pour les entités et les opérations définies.
Sortie du modèle de demande
La sortie de votre modèle de demande sera semblable à celle fournie dans la mise en oeuvre 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>>"
}
]
}
Structure 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 la structure prise en charge.
Structure de la 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 retourné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 de votre modèle de réponse ressemblera à celle fournie dans la mise en oeuvre 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 l'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 codage 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.
Autorisation OAuth - 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 codage de cette fonction :
Exemple de code de création de jeton
Pour le 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 AzureAD système orchestré :
<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();
}
}