Referencia REST genérica

Se crea un sistema REST orquestado genérico con una plantilla mínima, que se actualiza en tiempo de ejecución mediante OCI Functions para actualizar el sistema orquestado con clases de objetos, tipos de consulta y datos de transformación salientes.

Flujo de trabajo de alto nivel de detección de esquemas

La detección de esquemas es el proceso mediante el cual un sistema REST orquestado genérico aplica plantillas de funciones de OCI para permitir la detección del esquema, las clases de objetos, los atributos y los detalles de conexión para el origen autorizado o el sistema gestionado configurados.

La detección de esquemas se produce cuando se crea un sistema orquestado en Oracle Access Governance. Los flujos de trabajo simplificados para los escenarios Day0 y DayN se detallan en las siguientes tablas.

Flujo de trabajo Day0

Flujo de trabajo Day0
Paso Número Tarea/operación Descripción
1 Crear sistema orquestado

Cree un sistema orquestado mediante la consola de Oracle Access Governance.

El sistema orquestado se crea con los detalles de la función de OCI que ha creado para devolver los detalles del origen autorizado o el sistema gestionado necesarios.

En función de los detalles introducidos en el sistema orquestado, se crea la siguiente operación.
  • Validar
2 Validar ejecución de operación
La operación Validate se ejecuta y, según la plantilla de esquema configurada, recupera el esquema, incluidas las siguientes clases de objetos:
  • Identidad: recupera solo los atributos del núcleo. Debe tener los objetos principales obligatorios detallados aquí
  • No Identidad: recupera todos los atributos. Debe tener los atributos mínimos detallados aquí

Se llama a la plantilla de prueba de configuración para validar la conectividad con el sistema gestionado.

3 Operación posterior a validación
Al ejecutar correctamente la operación Validar, se crean las siguientes operaciones:
  • Carga de datos de consulta
  • Carga de datos completa

Flujo de trabajo DayN

Flujo de trabajo DayN
Paso Número Tarea/operación Descripción
1 Seleccione Recuperar atributos en la página Atributos de identidad de Oracle Access Governance. Consulte Recuperación de los últimos atributos personalizados para obtener más información. Se crea una operación de Schema Discovery en el sistema orquestado
2 Ejecución de la operación de detección de esquemas La operación de detección de esquemas se ejecuta y, según la plantilla de esquema configurada, recupera el esquema, incluidas las siguientes clases de objetos:
  • Identidad: recupera atributos básicos y personalizados
  • No Identidad: recupera todos los atributos
3 Refrescar la página Atributos de Identidad La lista de atributos personalizados comienza a mostrar los nuevos atributos personalizados para la clase de objeto de identidad.
Si todo lo anterior se completa correctamente, el sistema orquestado está disponible para que el programador cree las siguientes operaciones de carga de datos completa.

Atributos de esquema obligatorios de detección de esquema REST genérico

Durante la detección de esquemas, se deben devolver ciertos atributos obligatorios como parte de la salida del esquema.

Clase de Objeto de Identidad

Los atributos obligatorios que se deben devolver como parte de la salida del esquema para la clase de objeto Identity son:

  • UID
  • nombre
  • correo electrónico
  • firstName
  • middleName
  • lastName
  • displayName
  • employeeType
  • título
  • empNo
  • estado
  • jobCode
  • estado
  • riesgo
  • ubicación
  • departamento
  • managerUid
  • managerLogin
  • organizationUid
  • organizationName
  • país
  • 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"
    ]
  }
]

Clase de objeto no de identidad

Los atributos obligatorios que se deben devolver como parte de la salida del esquema para la clase de objeto Non-Identity son:

  • UID
  • nombre
[
  {
    "name": "uid",
    "dataType": "TEXT",
    "nature": [
      "REQUIRED"
    ],
    "usage": [
      "READ"
    ]
  },
  {
    "name": "name",
    "dataType": "TEXT",
    "nature": [
      "REQUIRED"
    ],
    "usage": [
      "READ"
    ]
  }
]

Esquema de plantilla de esquema

Para soportar la detección de esquemas, debe crear la plantilla de esquema mediante el esquema soportado.

Esquema de esquema

El esquema que debe seguir al crear la plantilla de esquema es:
{
 "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
                    ]
                }
            }
        ]
    }
  ]
}

Salida de plantilla de esquema

La salida de la plantilla de esquema se devuelve como documento JSON.

Salida de plantilla de esquema

La salida de la plantilla de esquema será similar a la proporcionada en la implantación de referencia (<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"
          ]
        }
      ]
    }
  ]
}

Esquema de plantilla de solicitud

Para admitir solicitudes al origen autorizado o sistema gestionado necesario, debe crear la plantilla de solicitud mediante el esquema soportado.

Esquema de solicitud

El esquema de solicitud que debe seguir al crear la plantilla de solicitud es:
{
  "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
      }
    }
  ]
}

Soporte de paginación

El esquema de solicitud admite una serie de métodos de paginación para evitar que los resultados de búsqueda grandes causen un trafijo de red excesivo. Se admiten los siguientes métodos de paginación:
  • DESFASE
  • PAGE_INCREMENT
  • PAGE_TOKEN
Los parámetros para estos métodos se detallan de la siguiente manera. Se deben agregar al esquema de solicitud.
Soporte de paginación
Tipo de Paginación Requisito Configuración
DESFASE La API de REST que está integrando con Oracle Access Governance debe soportar la paginación de OFFSET al devolver una respuesta.

Si paginationType está definido en OFFSET, debe agregar los siguientes valores de parámetros al esquema:

"queryParameters": [
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
] 
PAGE_INCREMENT La API de REST que está integrando con Oracle Access Governance debe soportar la paginación PAGE_INCREMENT al devolver una respuesta.

Si paginationType está definido en PAGE_INCREMENT, debe agregar los siguientes valores de parámetros al esquema:

"queryParameters": [
{"name": "currentPage", "value": "<EL>currentPage</EL>"}
{"name": "pageSize", "value": "<EL>pageSize</EL>"}
] 
PAGE_TOKEN La API de REST que está integrando con Oracle Access Governance debe soportar la paginación PAGE_TOKEN al devolver una respuesta.

Si paginationType está definido en PAGE_TOKEN, debe agregar los siguientes valores de parámetros al esquema:

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

El nombre de un parámetro de paginación concreto puede variar en función de la API de REST con la que se conecte. Por ejemplo, para la paginación de OFFSET, los parámetros podrían ser:
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
o
{"name": "beginIndex", "value": "<EL>currentOffset</EL>"}
{"name": "increment", "value": "<EL>limit</EL>"}
Debe utilizar el nombre especificado por la API, pero utilizar los valores como se describe en este artículo.

Salida de plantilla de solicitud

La salida de la plantilla de solicitud se devuelve como un documento JSON para las entidades y operaciones definidas.

Salida de plantilla de solicitud

La salida de la plantilla de solicitud será similar a la proporcionada en la implantación de referencia (<ReferenceBase>/functions/grc-schema-template/src/main/resources/request/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json):

Por ejemplo, desde la implementación de referencia:

  • EntityName: UserAsIdentity
  • Operación: 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
  • Operación: Búsqueda
{
  "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>>"
    }
  ]
}

Esquema de plantilla de respuesta

Para soportar el formato de respuesta para los datos de identidad y de cuenta, debe crear la plantilla de respuesta mediante el esquema soportado.

Esquema de respuesta

El esquema de respuesta que debe seguir al crear la plantilla de respuesta es:
{
  "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
        }
      ]
    }
  ]
}

Salida de plantilla de respuesta

La salida de la plantilla de respuesta se devuelve como documento JSON para las entidades y operaciones definidas.

Salida de plantilla de respuesta

La salida de la plantilla de respuesta será similar a la proporcionada en la implantación de referencia (<ReferenceBase>/functions/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json):

Por ejemplo, desde la implementación de referencia:

  • EntityName: UserAsIdentity
  • Operación: 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
  • Operación: Búsqueda
{
  "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>"
    }
  ]
}

Autorización básica - Código de creación de token de muestra

Si utiliza una autorización básica con el sistema REST genérico orquestado, deberá crear un token de autorización. El código de ejemplo que se muestra a continuación ofrece un ejemplo de cómo codificar esta función:

Código de creación de token de muestra

Si utiliza una autorización básica con el sistema REST genérico orquestado, deberá crear un token de autorización. El código de ejemplo que se muestra a continuación ofrece un ejemplo de cómo codificar esta función:
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 Autorización - Código de creación de token de ejemplo

Si utiliza la autorización OAuth con el sistema REST genérico orquestado, deberá crear un token de autorización. Los ejemplos que siguen, dan un ejemplo de cómo codificar esta función:

Código de creación de token de muestra

Para el sistema orquestado de IDCS:

Este código se proporciona con la implantación de ejemplo que incluye el conector REST genérico y se puede encontrar en <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());
  }
}

En el sistema orquestado AzureAD:

Este código se proporciona con la implantación de ejemplo que incluye el conector REST genérico y se puede encontrar en <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();
  }
}