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

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.
  • Valider
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 :
  • Identité : extrait uniquement les attributs principaux. Les objets principaux obligatoires doivent être détaillés ici
  • Non-identité : extrait tous les attributs. Les attributs minimum doivent être détaillés ici

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 :
  • Chargement des données de recherche
  • Chargement complet des données

DayN Workflow

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 :
  • Identité : extrait les attributs principaux et personnalisés
  • Non-identity : extrait tous les attributs
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é.
Si tout ce qui précède se termine avec succès, le système orchestré est disponible pour le planificateur afin de créer des opérations de chargement complet de données ultérieures.

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
  • e-mail
  • 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

L'outline de schéma à suivre lors de la création du modèle de schéma est la suivante :
{
 "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

La sortie du modèle de schéma ressemblera à celle fournie dans l'implémentation de référence (<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

L'outline de demande que vous devez suivre lors de la création du modèle de demande est la suivante :
{
  "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

L'outline de la demande prend en charge un certain nombre de méthodes de pagination pour éviter que des résultats de recherche volumineux ne provoquent un traffixe réseau excessif. Les méthodes de pagination suivantes sont prises en charge :
  • DÉCALAGE
  • PAGE_INCREMENT
  • PAGE_TOKEN
Les paramètres de ces méthodes sont détaillés comme suit. Ils doivent être ajoutés à l'outline de la demande.
Prise en charge de la pagination
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 paginationType est défini sur OFFSET, vous devez ajouter les valeurs de paramètre suivantes à l'outline :

"queryParameters": [
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
] 
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 paginationType est défini sur PAGE_INCREMENT, vous devez ajouter les valeurs de paramètre suivantes à l'outline :

"queryParameters": [
{"name": "currentPage", "value": "<EL>currentPage</EL>"}
{"name": "pageSize", "value": "<EL>pageSize</EL>"}
] 
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 paginationType est défini sur PAGE_TOKEN, vous devez ajouter les valeurs de paramètre suivantes à l'outline :

"queryParameters": [
{"name": "top", "value": "<EL>pageSize</EL>"}
{"name": "skiptoken", "value": "<EL>previousRequestResponseHeaders.get('token')==null ? '' :
    previousRequestResponseHeaders.get('token').get(0)</EL>"}
] 
Remarque

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

Le profil de réponse que vous devez suivre lors de la création du modèle de réponse est le suivant :
{
  "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

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 :
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 :

Ce code est fourni avec l'exemple d'implémentation fourni avec le connecteur REST générique et se trouve à l'adresse <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 :

Ce code est fourni avec l'exemple d'implémentation fourni avec le connecteur REST générique et se trouve à l'adresse <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();
  }
}