汎用REST参照

Generic REST Orchestrated Systemは、最小限のテンプレートで作成されます。このテンプレートは、OCI Functionsを使用して実行時に更新され、オブジェクト・クラス、参照タイプおよびアウトバウンド変換データでオーケストレート済システムを更新します。

スキーマ検出の高度なワークフロー

スキーマ検出とは、Generic REST Orchestrated SystemがOCI関数テンプレートを適用して、構成された認可ソースまたは管理対象システムのスキーマ、オブジェクト・クラス、属性および接続詳細の検出を有効にするプロセスです。

スキーマ検出は、Oracle Access Governanceでオーケストレート済システムが作成されたときに発生します。次の表に、Day0およびDayNシナリオの簡略化されたワークフローを示します。

Day0ワークフロー

Day0ワークフロー
ステップ番号 タスク/操作 説明
1 オーケストレート済システムの作成

Oracle Access Governanceコンソールを使用して、オーケストレート済システムを作成します。

オーケストレート済システムは、必要な認可ソースまたは管理対象システムから詳細を戻すために作成したOCI関数の詳細とともに作成されます。

オーケストレート済システムに入力された詳細に基づいて、次の操作が作成されます。
  • 検証
2 操作実行の検証
検証操作が実行され、構成済のスキーマ・テンプレートに基づいて、次のオブジェクト・クラスを含むスキーマがフェッチされます。
  • アイデンティティ: コア属性のみをフェッチします。必須のコア・オブジェクトの詳細は、ここを参照してください
  • 非アイデンティティ: すべての属性をフェッチします。ここに記載されている最小限の属性が必要です

構成テスト・テンプレートは、管理対象システムとの接続を検証するためにコールされます。

3 検証後操作
検証操作が正常に実行されると、次の操作が作成されます。
  • 参照データのロード
  • フル・データ・ロード

DayNワークフロー

DayNワークフロー
ステップ番号 タスク/操作 説明
1 Oracle Access Governanceの「アイデンティティ属性」ページから「属性のフェッチ」を選択します。詳細は、最新のカスタム属性のフェッチを参照してください。 スキーマ検出操作がオーケストレート済システムに作成されます
2 スキーマ検出操作の実行 スキーマ検出操作が実行され、構成済のスキーマ・テンプレートに基づいて、次のオブジェクト・クラスを含むスキーマがフェッチされます。
  • アイデンティティ: コアおよびカスタム属性をフェッチします
  • 非アイデンティティ: すべての属性をフェッチします
3 アイデンティティ属性ページをリフレッシュします カスタム属性リストでは、アイデンティティ・オブジェクト・クラスの新しいカスタム属性の表示が開始されます。
前述のすべてが正常に完了した場合、スケジューラでオーケストレーションされたシステムを使用して後続のフル・データ・ロード操作を作成できます。

汎用RESTスキーマ検出必須スキーマ属性

スキーマ検出中に、特定の必須属性をスキーマ出力の一部として返す必要があります。

IDオブジェクトクラス

Identityオブジェクト・クラスのスキーマ出力の一部として返す必要がある必須属性は、次のとおりです。

  • uid
  • 名前
  • Eメール
  • firstName
  • middleName
  • lastName
  • displayName
  • employeeType
  • タイトル
  • empNo
  • ステータス
  • jobCode
  • 国家
  • リスク
  • 場所
  • 部門
  • managerUid
  • managerLogin
  • organizationUid
  • organizationName
  • 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オブジェクト・クラスのスキーマ出力の一部として返す必要がある必須属性は、次のとおりです。

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

スキーマ・テンプレート・アウトライン

スキーマ検出をサポートするには、サポートされているアウトラインを使用してスキーマ・テンプレートを作成する必要があります。

スキーマ・アウトライン

スキーマ・テンプレートの作成時に従う必要があるスキーマ・アウトラインは次のとおりです。
{
 "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
                    ]
                }
            }
        ]
    }
  ]
}

スキーマ・テンプレート出力

スキーマ・テンプレートの出力は、JSONドキュメントとして返されます。

スキーマ・テンプレート出力

スキーマ・テンプレートの出力は、リファレンス実装(<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"
          ]
        }
      ]
    }
  ]
}

リクエスト・テンプレート・アウトライン

必要な認可ソースまたは管理対象システムへのリクエストをサポートするには、サポートされているアウトラインを使用してリクエスト・テンプレートを作成する必要があります。

リクエスト・アウトライン

リクエスト・テンプレートの作成時に従う必要のあるリクエスト・アウトラインは次のとおりです。
{
  "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
      }
    }
  ]
}

ページ区切りサポート

リクエスト・アウトラインでは、大量の検索結果が過剰なネットワーク・トラフィックスを引き起こさないように、多数のページ区切り方法がサポートされています。次のページ区切りメソッドがサポートされています。
  • オフセット
  • PAGE_INCREMENT
  • PAGE_TOKEN
これらのメソッドのパラメータについては、次のように詳しく説明します。これらは、リクエスト・アウトラインに追加する必要があります。
ページ区切りサポート
ページ区切りタイプ 前提条件 構成
オフセット Oracle Access Governanceと統合するREST APIは、レスポンスを返すときにOFFSETページ区切りをサポートする必要があります。

paginationTypeがOFFSETに設定されている場合、アウトラインに次のパラメータ値を追加する必要があります。

"queryParameters": [
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
] 
PAGE_INCREMENT Oracle Access Governanceと統合するREST APIでは、レスポンスを返すときにPAGE_INCREMENTページ区切りをサポートする必要があります。

paginationTypeがPAGE_INCREMENTに設定されている場合は、アウトラインに次のパラメータ値を追加する必要があります。

"queryParameters": [
{"name": "currentPage", "value": "<EL>currentPage</EL>"}
{"name": "pageSize", "value": "<EL>pageSize</EL>"}
] 
PAGE_TOKEN Oracle Access Governanceと統合するREST APIでは、レスポンスを返すときにPAGE_TOKENページ区切りをサポートする必要があります。

paginationTypeがPAGE_TOKENに設定されている場合は、アウトラインに次のパラメータ値を追加する必要があります。

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

特定のページ区切りパラメータの名前は、接続しているREST APIによって異なる場合があります。たとえば、OFFSETページ区切りの場合、パラメータは次のようになります。
{"name": "startIndex", "value": "<EL>currentOffset</EL>"}
{"name": "count", "value": "<EL>limit</EL>"}
または
{"name": "beginIndex", "value": "<EL>currentOffset</EL>"}
{"name": "increment", "value": "<EL>limit</EL>"}
APIで指定されている名前を使用する必要がありますが、この記事で説明するように値を使用してください。

リクエスト・テンプレート出力

リクエスト・テンプレートの出力は、定義されたエンティティおよび操作のJSONドキュメントとして返されます。

リクエスト・テンプレート出力

リクエスト・テンプレートの出力は、リファレンス実装(<ReferenceBase>/functions/grc-schema-template/src/main/resources/request/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json)に用意されているものと似ています。

たとえば、リファレンス実装から次のようにします。

  • EntityName: UserAsIdentity
  • 操作: 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
  • 操作: 検索
{
  "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>>"
    }
  ]
}

レスポンス・テンプレート・アウトライン

アイデンティティおよびアカウント・データのレスポンス・フォーマットをサポートするには、サポートされているアウトラインを使用してレスポンス・テンプレートを作成する必要があります。

応答概要

レスポンス・テンプレートの作成時に従う必要のあるレスポンス・アウトラインは次のとおりです。
{
  "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
        }
      ]
    }
  ]
}

応答テンプレート出力

レスポンス・テンプレートの出力は、定義されたエンティティおよび操作のJSONドキュメントとして返されます。

応答テンプレート出力

レスポンス・テンプレートの出力は、リファレンス実装(<ReferenceBase>/functions/grc-response-template/src/main/resources/response/applications/<YourApplicationName>/<EntityName>/<Operation>_TEMPLATE.json)に用意されているものと似ています。

たとえば、リファレンス実装から次のようにします。

  • EntityName: UserAsIdentity
  • 操作: 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
  • 操作: 検索
{
  "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認可- サンプル・トークン作成コード

Generic RESTオーケストレート済システムで基本認可を使用する場合は、認可トークンを作成する必要があります。次のサンプル・コードは、この関数のコーディング方法の例を示しています。

サンプル・トークン作成コード

Generic RESTオーケストレート済システムで基本認可を使用する場合は、認可トークンを作成する必要があります。次のサンプル・コードは、この関数のコーディング方法の例を示しています。
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認可- サンプル・トークン作成コード

Generic RESTオーケストレート済システムでOAuth認可を使用する場合は、認可トークンを作成する必要があります。次に、この関数のコーディング方法の例を示します。

サンプル・トークン作成コード

IDCSオーケストレート済システムの場合:

このコードは、Generic RESTコネクタに付属するサンプル実装とともに提供されており、<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());
  }
}

AzureADオーケストレート済システムの場合:

このコードは、Generic RESTコネクタに付属するサンプル実装とともに提供されており、<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();
  }
}