Generic REST Orchestrated System Reference
A Generic REST Orchestrated System is created with a minimal template, which is updated at runtime using OCI Functions to update the Orchestrated System with object classes, lookup types, and outbound transformation data.
Schema Discovery High-Level Workflow
Schema discovery is the process by which a Generic REST Orchestrated System applies OCI Function templates to enable discovery of the schema, object classes, attributes, and connection details for the configured Authoritative Source or Managed System.
Schema discovery occurs when an Orchestrated System is created in Oracle Access Governance. Simplified workflows for Day0 and DayN scenarios are detailed in the following tables.
Day0 Workflow
Table - Day0 Workflow
Step # | Task/Operation | Description |
---|---|---|
1 | Create Orchestrated System |
Create Orchestrated System using the Oracle Access Governance Console. The Orchestrated System is created with details of the OCI Function you have created to return details from the required Authoritative Source or Managed System. Based on the details entered into
the Orchestrated System, the following operation is created.
|
2 | Validate operation execution |
The Validate operation is executed and, based
on the configured schema template, fetches the
schema, including the following object classes:
The configure test template is called to validate connectivity with the Managed System. |
3 | Post Validate operation |
On successful execution of the
Validate operation, the following operations are
created:
|
DayN Workflow
Table - DayN Workflow
Step # | Task/Operation | Description |
---|---|---|
1 | Select Fetch Attributes from the Identity Attributes page of the Oracle Access Governance. See Fetch Latest Custom Attributes for further details. | A Schema Discovery operation is created in the Orchestrated System |
2 | Schema Discovery operation execution | The Schema Discovery operation
is executed and, based on the configured schema
template, fetches the schema, including the
following object classes:
|
3 | Refresh the Identity Attributes page | The custom attributes list starts showing the new custom attributes for identity object class. |
Generic REST Schema Discovery Mandatory Schema Attributes
During schema discovery certain mandatory attributes must be returned as part of the schema output.
Identity Object Class
The mandatory attributes that must be returned as part of the schema output for the Identity object class are:
- uid
- name
- firstName
- middleName
- lastName
- displayName
- employeeType
- title
- empNo
- status
- jobCode
- state
- risk
- location
- department
- managerUid
- managerLogin
- organizationUid
- organizationName
- country
- 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"
]
}
]
Non-Identity Object Class
The mandatory attributes that must be returned as part of the schema output for the Non-Identity object class are:
- uid
- name
[
{
"name": "uid",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
},
{
"name": "name",
"dataType": "TEXT",
"nature": [
"REQUIRED"
],
"usage": [
"READ"
]
}
]
Schema Template Outline
In order to support schema discovery you need to create your schema template using the supported outline.
Schema Outline
{
"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
]
}
}
]
}
]
}
Schema Template Output
Output of the schema template is returned as a JSON document.
Schema Template Output
<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"
]
}
]
}
]
}
Request Template Outline
In order to support requests to the required Authoritative Source or Managed System you need to create your request template using the supported outline.
Request Outline
{
"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
}
}
]
}
Pagination Support
- OFFSET
- PAGE_INCREMENT
- PAGE_TOKEN
Table - Pagination Support
Pagination Type | Prerequisite | Configuration |
---|---|---|
OFFSET | The REST API that you are integrating with Oracle Access Governance must support OFFSET pagination when returning a response. |
If
|
PAGE_INCREMENT | The REST API that you are integrating with Oracle Access Governance must support PAGE_INCREMENT pagination when returning a response. |
If
|
PAGE_TOKEN | The REST API that you are integrating with Oracle Access Governance must support PAGE_TOKEN pagination when returning a response. |
If
|
Note:
The name for a particular pagination parameter may vary depending on the REST API that you are connecting with. For example, for OFFSET pagination, the parameters could be:{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
or{"name": "beginIndex", "value": "<EL>currentOffset</EL>"}
{"name": "increment", "value": "<EL>limit</EL>"}
You should use the name specified by your API, but use the values as discussed in this
article.Request Template Output
Output of the request template is returned as a JSON document for defined entities and operations.
Request Template Output
Your request template output will look similar to that provided in the reference
implementation
(<ReferenceBase>/functions/grc-schema-template/src/main/resources/request/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json
):
For example, from the reference implementation:
- EntityName: UserAsIdentity
- Operation: 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
- Operation: SEARCH
{
"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>>"
}
]
}
Response Template Outline
In order to support response format for identity and account data you need to create your response template using the supported outline.
Response Outline
{
"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
}
]
}
]
}
Response Template Output
Output of the response template is returned as a JSON document for defined entities and operations.
Response Template Output
Your response template output will look similar to that provided in the reference
implementation
(<ReferenceBase>/functions/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json
):
For example, from the reference implementation:
- EntityName: UserAsIdentity
- Operation: 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
- Operation: SEARCH
{
"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>"
}
]
}
Basic Authorization - Sample Token Creation Code
If you use basic authorization with your Generic REST you will need to create an authorization token. The sample code which follows, gives an example of how to code this function:
Sample Token Creation Code
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 Authorization - Sample Token Creation Code
If you use OAuth authorization with your Generic REST you will need to create an authorization token. The samples which follow, give an example of how to code this function:
Sample Token Creation Code
For 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());
}
}
For AzureAD :
<SampleBase>/grc-serverless-function-samples/idm-agcs-serverless-multi-application-sample/grc-commons/src/main/java/com/oracle/idm/agcs/grc/fn/commons/provider/AzureAdAuthenticationProvider.java
./*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
*/
package com.oracle.idm.agcs.grc.fn.commons.provider;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.oracle.idm.agcs.grc.fn.commons.config.ConnectedSystemConfig;
import com.oracle.idm.agcs.grc.fn.commons.exception.ProcessingFailedException;
import com.oracle.idm.agcs.icfconnectors.commons.util.VaultUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class AzureAdAuthenticationProvider extends AuthenticationProvider {
@Override
public String getAuthorizationValue(ConnectedSystemConfig connectedSystemConfig) {
String url =
connectedSystemConfig
.getAuthenticationDetail()
.get("scheme")
.concat("://")
.concat(connectedSystemConfig.getAuthenticationDetail().get("host"))
.concat(connectedSystemConfig.getAuthenticationDetail().get("path"));
String requestBody;
try {
String vaultJsonValue = VaultUtil.getDataFromVault(connectedSystemConfig.getAuthenticationDetail().get("secretId"), connectedSystemConfig.getAuthenticationDetail().get("region"));
requestBody =
"client_id="
+ VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientCode")
+ "&client_secret="
+ VaultUtil.getAttributeValueFromJson(vaultJsonValue, "clientSecret")
+ "&grant_type="
+ connectedSystemConfig.getAuthenticationDetail().get("grantType")
+ "&scope="
+ connectedSystemConfig.getAuthenticationDetail().get("scope");
} catch (UnsupportedEncodingException | JsonProcessingException e) {
System.err.println("Exception occurred while getting secret from vault. " + e.getMessage());
throw new ProcessingFailedException(
"Exception occurred while getting secret from vault", e);
}
final HttpClient client = getHttpClient(connectedSystemConfig);
final HttpRequest request =
HttpRequest.newBuilder()
.uri(URI.create(url))
.header(AuthenticationProvider.HEADER_NAME_CONTENT_TYPE, AuthenticationProvider.HEADER_VALUE_CONTENT_TYPE_FORM_URL_ENCODED)
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response;
try {
response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to IOException."
+ e.getMessage());
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to IOException.", e);
} catch (InterruptedException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException."
+ e.getMessage());
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpRequest failed due to InterruptedException.",
e);
}
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpResponse is :: " + response.body());
JsonNode jsonNode;
try {
jsonNode = AuthenticationProvider.objectMapper.readTree(response.body());
} catch (JsonProcessingException e) {
System.err.println(
"AzureAdAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.");
throw new ProcessingFailedException(
"AzureAdAuthenticationProvider Auth Token API HttpResponse parsing to json is failed.",
e);
}
return AuthenticationProvider.TOKEN_PREFIX_BEARER.concat(jsonNode.get(AuthenticationProvider.ACCESS_TOKEN_ATTRIBUTE).textValue());
}
private HttpClient getHttpClient(ConnectedSystemConfig connectedSystemConfig) {
if (null == connectedSystemConfig.getAuthenticationDetail().get("proxyHost")
|| null == connectedSystemConfig.getAuthenticationDetail().get("proxyPort")) {
return HttpClient.newHttpClient();
}
return HttpClient.newBuilder()
.proxy(
ProxySelector.of(
new InetSocketAddress(
connectedSystemConfig.getAuthenticationDetail().get("proxyHost"),
Integer.parseInt(connectedSystemConfig.getAuthenticationDetail().get("proxyPort")))))
.build();
}
}
For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.
Access to Oracle Support
Oracle customers that have purchased support have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.