Setup OCI Serverless Function to Connect with REST-based Identity Aware System

How Does the Generic REST Orchestrated System Use OCI Functions?

Oracle Access Governance leverages OCI Functions for REST API integrations. Each Generic REST Orchestrated System you create is associated with an OCI function which contains the logic to process requests and generate responses. It calls REST APIs of the Managed System for data reconciliation and provisioning operations when triggered by Oracle Access Governance.

For full details of how to use OCI Functions refer to Oracle Cloud Infrastructure Functions.

Configuring Your Tenancy to Enable OCI Functions

Before you can use OCI Functions to create and deploy functions, you must create Oracle Cloud Infrastructure resources to support this. Resources you need to create include a user account, a group to which the user account will belong, a compartment, virtual cloud network (VCN), vaults and secrets, and policies to give the group (and the user accounts that belong to it) access to function-related resources. If suitable resources already exist, there is no need to create new ones.

Create Users and Groups

If you do not have a suitable user or group for managing your OCI functions:

  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Identity & Security → Identity → Domains → <YourDomain> -> Groups → Create Group.
  3. Create a group, for example ocifn_grp: For details on how to create a group see To create a group.
  4. Select Identity & Security → Identity → Domains → <YourDomain> → Users → Create user.
  5. Create a user, for example ocifn_user: For details on how to create a user see To create a user.
  6. Select Groups → Assign user to groups.
  7. Assign ocifn_user to the group: For details on how to add a user to a group see To add a user to a group

Create Compartment

If you do not have a suitable compartment in which you can create network resources and OCI Functions resources:
  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Identity & Security → Identity → Compartments.
  3. Select Create Compartment and add a compartment, for example ocifn_compartment: For details on creating a compartment see To create a compartment

Note:

You create a compartment to own:
  • Network resources
  • Function-related resources
You can create a single compartment to contain both sets of resources, or you can create separate compartments for network resources and function-related resources.

Create VCN and Subnets

If you do not have a suitable VCN in which to create network resources:
  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Networking → Virtual cloud networks.
  3. Select Start VCN Wizard to create a new VCN.
  4. In the dialog, select Create VCN with Internet Connectivity and click the Start VCN Wizard.
  5. In the wizard, enter the following details:
    1. VCN Name: Enter the VCN name, for example ocifn_vcn.
    2. Compartment : Enter the compartment within which the VCN resources will be created, for example ocifn_compartment.
  6. Click Next, then click Create to create the VCN and related network resources.

For details of all options when creating the VCN see Creating the VCN and Subnets to Use with OCI Functions.

Create OCI Vault and Secret

If you do not have a suitable vault in which to store client credentials:

  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Identity & Security → Key Management & Secret Management
  3. Click Create Vault.
  4. Select the compartment into which the Vault will be created, and give the Vault a Name. Click Create Vault.
  5. Open the Vault you created and click Create Key. Create the Key in the same compartment you created your Vault. Give the Key a name and click Create Key.
  6. From the Resources menu, select Secrets. Click Create Secret.
  7. On the Create Secret page, add details for compartment, name, and description. Select the key you created from the Encryption Key drop down list. Select the Manual secret generation option, and enter your client code and client secret in JSON format into the Secret Contents field, for example:
    {
      "clientCode": "69b48365-14e2-430a-bd75-171f89c158fa",
      "clientSecret": "*/Z9g:gM*SWWLLCGkQhQg2hdWelAZD82"
    }
  8. Select Create Secret to save your changes.

The secret you have created can be used to pass client secrets in your request function. Select the secret you created and copy the value of the secret OCID, which will look something like ocid1.vaultsecret.oc1.iad.dyyyyehdl4ggaawnqt47hfj48ltofzkdg6wy5fjne859jg0.

Edit the <SampleBase>/grc-request-template/src/main/resources/request/applications/<YourApplicationName>/config.yaml file and add the details of the secret and region, for example:
secretId: "ocid1.vaultsecret.oc1.iad.dyyyyehdl4ggaawnqt47hfj48ltofzkdg6wy5fjne859jg0"
region: "us-ashburn-1"

For further details on OCI Vault Secrets see Managing Vault Secrets.

Create or Update your Dynamic Group

In order to use OCI Vault and Secret Services, your function must be part of a dynamic group. For details on how to create your dynamic group, follow the instructions given in Managing Dynamic Groups.

As part of the creation of your dynamic group you will be required to define a set of matching rules to define the group member. When specifying the matching rule it is recommended that you match all functions in a compartment with the following rule:
ALL { resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..fdfdfege4om6nat7fue56566556qqvj3eesjqhmjaegeiaxa' }

Create Policy for OCI Vault and Secret

Create a new policy that allows the dynamic group created in above step to read secret-family in your tenancy. For further information on creating OCI policies see Policy Syntax

  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Identity & Security → Identity → Policies.
  3. Select Create Policy, specify a name for the policy, for example ocifn_policy, and select the tenancy's root compartment.
  4. Add a policy statement similar to:
    Allow dynamic-group <dynamic-group-name> to read secret-family in tenancy

Create Policy for Group and Service

If one or more OCI Functions users, for example ocifn_user is not a tenancy administrator:
  1. Sign on to the Oracle Cloud Infrastructure Console as a tenancy administrator.
  2. Open the navigation menu and select Identity & Security → Identity → Policies.
  3. Select Create Policy, specify a name for the policy, for example ocifn_policy, and select the tenancy's root compartment.
  4. Using Policy Builder, select Functions from the Policy use cases list, and base your policy on the Let users create, deploy, and manage functions and applications template.
  5. Select the group created earlier, ocifn_group and the ocifn_compartment for the location. This should give you a policy statement similar to:
    Allow group 'Default'/'ocifn_grp' to use cloud-shell in tenancy
    Allow group 'Default'/'ocifn_grp' to manage repos in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to read objectstorage-namespaces in tenancy
    Allow group 'Default'/'ocifn_grp' to manage logging-family in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to read metrics in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to manage functions-family in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to use virtual-network-family in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to use apm-domains in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to read vaults in compartment ocifn_compartment
    Allow group 'Default'/'ocifn_grp' to use keys in compartment ocifn_compartment
    Allow service faas to use apm-domains in compartment ocifn_compartment
    Allow service faas to read repos in tenancy where request.operation='ListContainerImageSignatures'
    Allow service faas to {KEY_READ} in compartment ocifn_compartment where request.operation='GetKeyVersion'
    Allow service faas to {KEY_VERIFY} in compartment ocifn_compartment where request.operation='Verify'

For more details on creating policies for OCI Functions see Creating Policies to Control Access to Network and Function-Related Resources

Create an Application to Group Your OCI Functions

In OCI Functions, an application is a logical grouping of functions. The properties you specify for an application determine resource allocation and configuration for all functions in that application. You have to create a function within an application, so at least one application must exist before you can create a function in OCI Functions.

To create an application:
  1. Sign on to the Oracle Cloud Infrastructure Console as a functions developer.
  2. Open the navigation menu and select Developer Services → Functions → Applications.
  3. Select the compartment you are using for Generic REST functions.
  4. Click Create application.
  5. Add a name for the application, for example agcs-generic-rest-connector. You will deploy your functions into this application, and specify this application when invoking the function.
  6. Select the VCN and subnet in which to run the function.
  7. Click Create.

For full details on creating applications with OCI Functions see Creating Applications.

Setup Environment for Developing OCI Functions

In order to create and deploy your OCI Functions you need to install and setup a development environment.

Before you can create OCI functions for the Generic REST Orchestrated System. you need to install and configure a development environment, if you do not already have one available. Setup of a development environment can be done in a number of ways, and includes some or all of the following steps:
  • Install and start Docker
  • Setup API signing key and OCI profile
  • Install Fn Project command line interface (CLI)
  • Setup Fn Project CLI context provider
  • Complete Fn Project CLI context configuration
  • Generate auth token
  • Log into registry
Full details of how to setup your development environment in different in different contexts can be found in the Oracle Cloud Infrastructure documentation as follows:

Once your development environment is setup, you can start to develop and deploy functions for the Generic REST Orchestrated System.

Develop and Deploy Function to OCI

In order to deploy the Generic REST Orchestrated System you need to develop and deploy an OCI function which enables you to connect to the identity-aware system that you want to integrate with Oracle Access Governance using REST.

To develop and deploy OCI Functions for use with the Generic REST Orchestrated System:

Setup Sample Implementation

To help with development of your OCI Functions a sample implementation is provided with the Generic REST Orchestrated System. To download this example you should follow the instructions given in the Select System procedure.

The sample implementation downloaded, idm-agcs-generic-rest-reference-implementation.zip, comprises four use cases. When unzipping the file, you will see the following four directories from which you can choose a sample that meets your requirements.

Note:

In the details that follow, the directory to which you have unzipped the sample implementation is referred to as <SampleBase>. Use this to locate the files mentioned. For example:

If you unzip the sample implementation to a directory, say, /myagfunctions then the file <SampleBase>/grc-schema-template/src/main/resources/schema/config.yaml can be found at /myagfunctions/grc-schema-template/src/main/resources/schema/config.yaml.

  1. idm-agcs-serverless-getting-started-sample: This is a basic and easy-to-understand sample with minimal code, demonstrating how functions work. This use case is ideal for customers needing to integrate a single application with the Generic REST connector, requiring minimal configuration. Initial set up is with an Oracle Identity Cloud Service (IDCS) application. Detailed steps to configure and deploy this function can be found in the `README.md` file within this directory.
  2. idm-agcs-serverless-idcs-application-sample: This sample focuses on the IDCS application example with minimal configuration. It includes the framework to add more applications in the future within this function. Configuration and deployment steps are detailed in the `README.md` file located in this directory.
  3. idm-agcs-serverless-azuread-application-sample: This sample is specifically for customers who need an AzureAD application example with minimal configuration. It contains the framework to add more applications in the future within this function. Detailed steps to configure and deploy this function are available in the `README.md` file inside this directory.
  4. idm-agcs-serverless-multi-application-sample: This sample is for customers needing both IDCS and AzureAD application examples with minimal configuration. It includes the framework to add more applications in the future within this function. The `README.md` file in this directory provides all necessary steps to configure and deploy this function.

Create Functions for Your Application

Create the functions for your own REST-based identity-aware system, by referring to the reference templates, and configuring the functions as defined below, with values specific to your application.

Table - GRC-SCHEMA-TEMPLATE

Item Description
Input Orchestrated System name
Configuration

List of configured custom REST identity aware systems:<SampleBase>/grc-schema-template/src/main/resources/schema/config.yaml

For example, from the sample implementation:
applications:
  - "idcs"

List of Orchestrated Systems linked to custom REST identity aware system: <SampleBase>/grc-schema-template/src/main/resources/schema/applications/<YourApplicationName>/config.yaml

For example, from the sample implementation:
application: "idcs"
connectedSystemConfigs:
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_1>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_2>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_3>>"
Output
JSON Schema template document, with one or more entity schemas, including any of the following entity types:
  • ACCOUNT
  • ENTITLEMENT
  • LOOKUP
  • TARGETACCOUNT

<SampleBase>/grc-schema-template/src/main/resources/schema/applications/<YourApplicationName>/TEMPLATE.json

For an example from the sample implementation see Schema Output.

Table - GRC-REQUEST-TEMPLATE

Item Description
Input
  • Orchestrated System name
  • Operation name
  • Entity name
Configuration

List of configured custom REST identity aware systems: <SampleBase>/grc-request-template/src/main/resources/request/config.yaml

For example, from the sample implementation:
applications:
  - "idcs"

List of Orchestrated Systems linked to custom REST identity aware system: <SampleBase>/grc-request-template/src/main/resources/request/applications/<YourApplicationName>/config.yaml

For example, from the sample implementation:
application: "idcs"
connectedSystemConfigs:
  - connectedSystemName: "<<CONNECTED_SYSTEM_NAME_1>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_1>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_1>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_1>>"
  - connectedSystemName: "<<CONNECTED_SYSTEM_NAME_2>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_2>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_2>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_2>>"
  - connectedSystemName: "<<CONNECTED_SYSTEM_NAME_3>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_3>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_3>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_3>>"
Output

JSON Request template document, for defined entities and operations:

Entities
  • ACCOUNT
  • ENTITLEMENT
  • LOOKUP
  • TARGETACCOUNT
Operations
  • CREATE
  • GET
  • SEARCH
  • DELETE
  • UPDATE
  • ADD_CHILD_DATA
  • REMOVE_CHILD_DATA
  • ENABLE
  • DISABLE

<SampleBase>/grc-schema-template/src/main/resources/request/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json

For an example from the sample implementation see Request Output.

Table - GRC-RESPONSE-TEMPLATE

Item Description
Input
  • Orchestrated System name
  • Operation name
  • Entity name
Configuration

List of configured custom REST identity aware systems: <SampleBase>/grc-response-template/src/main/resources/response/config.yaml

For example, from the sample implementation:
applications:
  - "idcs"

List of Orchestrated Systems linked to custom REST identity aware system: <SampleBase>/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/config.yaml

For example, from the sample implementation:
application: "idcs"
connectedSystemConfigs:
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_1>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_2>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_3>>"
Output

JSON Response template document, for defined entities and operations:

Entities
  • ACCOUNT
  • ENTITLEMENT
  • LOOKUP
  • TARGETACCOUNT
Operations
  • CREATE
  • GET
  • SEARCH
  • DELETE
  • UPDATE
  • ADD_CHILD_DATA
  • REMOVE_CHILD_DATA
  • ENABLE
  • DISABLE

<SampleBase>/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json

For an example from the sample implementation see Response Output.

Table - GRC-TEST-TEMPLATE

Item Description
Input Orchestrated System name
Configuration

List of configured custom REST identity aware systems: <SampleBase>/grc-test-template/src/main/resources/test/config.yaml

For example, from the sample implementation:
applications:
  - "idcs"

List of Orchestrated Systems linked to custom REST identity aware application: <SampleBase>/grc-test-template/src/main/resources/test/applications/<YourApplicationName>/config.yaml

For example, from the sample implementation:
application: "idcs"
connectedSystemConfigs:
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_1>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_1>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_1>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_1>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_2>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_2>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_2>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_2>>"
  - connectedSystemName: "<<IDCS_CONNECTED_SYSTEM_NAME_3>>"
    authenticationDetail:
      scheme: "https"
      host: "<<IDCS_AUTH_API_HOST_3>>"
      path: "/oauth2/v1/token"
      method: "POST"
      grantType: "client_credentials"
      scope: "urn:opc:idm:__myscopes__"
      secretId: "<<SECRET_ID_3>>"
      region: "<<REGION>>"
    applicationInstanceDetail:
      scheme: "https"
      host: "<<IDCS_API_HOST_3>>"
Output

JSON Test Request template document: <SampleBase>/grc-test-template/src/main/resources/test/applications/<YourApplicationName>/TEMPLATE.json

For example, from the sample implementation:
{
  "id": "1",
  "name": "Test connectivity invoking schema API",
  "method": "GET",
  "uri":
  {
    "scheme": "<<SCHEME>>",
    "host": "<<HOST>>",
    "path": "/admin/v1/Schemas"
  },
  "queryParameters":
  [
    {
      "name": "startIndex",
      "value": "1"
    },
    {
      "name": "count",
      "value": "1"
    }
  ],
  "headers":
  [
    {
      "name": "Content-Type",
      "value": "application/json"
    },
    {
      "name": "Authorization",
      "value": "<<CREDENTIALS>>"
    }
  ]
}

Test Infra Module Guide

Request and Response templates are complex and errors can occur during development. It is crucial to identify and validate all configured Request and Response templates for correctness during the build time itself.

To address this challenge, the grc-test-infra module has been introduced. This module includes tests corresponding to each configured Request and Response template. These tests aim to verify the requests made to the target application's REST API and the responses received. To achieve this, the tests utilize a utility, such as a generic Request and Response processor, capable of handling any REST API call developed within the module. Essentially, it internally interacts with the target application's endpoints and validates the responses based on the configured response templates.

To effectively identify and validate all configured GRC Request and Response templates for correctness during the build time, follow these steps:
  1. Develop tests following the example outlined below:
    grc-test-infra sample test
    package com.oracle.idm.agcs.grc.fn.test.infra;
     
    public class RequestResponseTemplateValidationTest {
     
        public void validateSearchUserAsIdentityRequestResponseTemplate() throws IOException, URISyntaxException, InterruptedException {
            // Get the configured Request template by passing the connectedSystem Name, entity name, and operation
            RequestTemplateOutput requestTemplate = getRequestTemplateOutput(connectedSystemName, UserAsIdentityEntity, Operation.SEARCH);
             
            // Get the configured Response template by passing the connectedSystem Name, entity name, and operation
            ResponseTemplateOutput responseTemplate = getResponseTemplateOutput(connectedSystemName, UserAsIdentityEntity, Operation.SEARCH);
             
            // Pass the required attributes in the request template by putting them in the attribute map
            HashMap<String, Object> attributesMap = new HashMap<>();
             
            // Call the generic utility method to validate request and response template
            Map<String, Object> lastRecord = processAndValidateRequestAndResponseTemplate(requestTemplate, responseTemplate, attributesMap);
             
            // Retrieve the necessary data from the response for further processing
            userAsIdentityUid = ((ArrayList<String>) lastRecord.get("uid")).get(0);
        }
    }
    • The first line inside the test is to get the configured Request template by passing the connectedSystem Name, entity name, and operation.
    • The second line gets the configured Response template using similar parameters.
    • Users need to pass the required attributes in the request template by putting them in the attribute map.
    • Then, users just need to call the generic utility method processAndValidateRequestAndResponseTemplate, which internally validates both the request and response templates for correctness by invoking the API and mapping its response with the configured response template.
    • The test will pass if the configured request and response templates are correctly configured; otherwise, it will fail, allowing users to see the failure reason and correct the templates accordingly.

    The example test file can be found in the sample implementation at the following location: <SampleBase>/grc-test-infra/src/test/java/com/oracle/idm/agcs/grc/fn/test/infra/RequestResponseTemplateValidationTest.java

  2. Add the following prerequisites before running the test:
    1. Update the <SampleBase>/grc-test-infra/src/test/resources/config file with the following values for your environment:
      [DEFAULT]
      user=<<USER>>
      fingerprint=<<FINGERPRINT>>
      key_file=<<PEM_FILE_RELATIVE_PATH>>
      tenancy=<<TENANCY>>
      region=<<REGION>>
    2. Update the <SampleBase>/grc-test-infra/src/test/resources/config.properties file with the following value for your environment:
      connectedSystemName=<connectedSystemName>
    3. Add the private SSH key (.pem file) for the API Signing Key to the following location:
      <SampleBase>/grc-test-infra/src/test/resources/oci_api_key.pem
  3. Execute the developed test and build the function:
    1. Navigate to the functions directory of the sample implementation.
    2. Compile and package the functions
      mvn clean package-DisDevMode=true

Build and Deploy Your Function

  1. Build your function.
    cd <SampleBase>
    mvn package
    
  2. Deploy your function on OCI. The steps should be carried out for each function
    • grc-schema-template
    • grc-request-template
    • grc-response-template
    • grc-test-template
    cd <SampleBase>/grc-schema-template
    fn -v deploy --app <ApplicationName>