きめ細かいアクセス権管理による UiPath Data Service のAPI連携

# はじめに

本記事では、Data Service Open APIを使用して外部のアプリケーションからUiPath Data Serviceのリソースにアクセスする方法をご紹介します。

Automation Cloudのリソースにアクセスする外部アプリケーションを認可する場合、Automation Cloudの***外部アプリケーション***からアクセス権を付与できます。
外部アプリケーションのリソースの選択肢として、Data Serviceに対しても"Data Service API"が用意されています。しかしながら、"Data Service API"にはアプリケーションスコープが用意されていないため、クライアントクレデンシャル(資格情報)方式によりアクセストークンを取得する方法ができず、無人実行には不向きな点があります(※)。
そこで、外部アプリケーションの***きめ細かいアクセス権***を使って、APIのアクセス許可をクライアントクレデンシャル方式で付与する方法をご紹介します。


::: note info

※ [各種の許可を使用する](https://docs.uipath.com/ja/automation-cloud/automation-cloud/latest/api-guide/accessing-uipath-resources-using-external-applications#using-the-different-grant-types) に記載の認可の種類は以下の通りです。
ユーザー スコープに基づく権限付与では、外部アプリケーションがそれらのリソースにユーザー コンテキスト内でアクセス可能であり、適切な権限を持つユーザーがログインする必要があることを意味します。

| アプリケーションの種類 | スコープ | 必要な許可の種類 |
|:-|:-|:-|
| 機密  | ユーザー  | 認可コード  |
| 機密  | アプリケーション  | クライアント資格情報  |
| 非機密  | ユーザー  | PKCE による認可コード  |

認可の種類については [外部アプリケーション機能(OAuth)によるOrchestrator APIコール実装方法](https://www.uipath.com/ja/community-blog/knowledge-base/implementing-orchestrator-api-with-oauth) に詳細の説明があるので、そちらもご参照ください。
:::

::: note info
UiPathからData Serviceのエンティティにアクセスするには、[UiPath.DataService.Activitiesパッケージ](https://docs.uipath.com/ja/data-service/automation-cloud/latest/user-guide/data-service-studio-activities)をご利用頂くと簡便です。
:::
::: note info

Automation Cloud, Data Serviceの仕様は本稿執筆時点2023年5月の情報を基にしています。
:::

## 外部アプリケーションのきめ細かいアクセス権

[UiPath Automation Cloud: きめ細かいアクセス権の細かい話](https://qiita.com/mstgsg/items/8a1773a9219831fb4bd2) の記事では、外部アプリケーションに付与するOrchestratorのアクセス権を細かく設定する方法として、***きめ細かいアクセス権***をご紹介しました。
本記事では、同様に***きめ細かいアクセス権***を使用し、外部アプリケーションの無人実行に適したアクセス権の付与方法をご紹介します。


# 設定手順

以下に設定手順をご紹介します。大まかな手順としては以下の通りです。
1. 外部アプリケーションの追加
1. DataServiceのロール割り当て
1. APIリクエスト送信の実装


## 外部アプリケーションの追加

外部アプリケーションを追加手順は以下の通りです。

1. Automation Cloudの　管理 > 外部アプリケーション　を開きます。
1. "+アプリケーションを追加"を選択します。
1. 任意の"アプリケーション名"を設定し、***リソースとスコープの設定をせず***、"追加"をクリックします。機密アプリケーションを選択します。
1. 表示されるアプリケーションIDとアプリケーションシークレットをメモします。<br>外部アプリケーションの追加作業は以上です。

[ UiPath Automation Cloud: きめ細かいアクセス権の細かい話 ](https://qiita.com/mstgsg/items/8a1773a9219831fb4bd2#%E5%A4%96%E9%83%A8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%BF%BD%E5%8A%A0)でも図付きで説明しているので、よかったらご確認ください。


## Data Serviceのロール割り当て

上記の***外部アプリケーションの追加***では、特定のアクセス権を設定しませんでした。きめ細かいアクセス権ではData Service側でアクセス許可を設定します。例として、以下のような```TestEntityA```と```TestEntityB```の二つのエンティティを用意し、読み取りのアクセス権を付与する場合を考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/7fda72b8-f584-fd37-6994-96a6870fb6b9.png)


### テナント全体に対してアクセス権を付与する

Data Serviceを展開しているテナントに対してアクセス許可を設定します。テナント内の全てのエンティティに対してアクセス権を付与する場合、標準ロールを使用するのが便利です。以下に手順をご紹介します。
1. エンティティ一覧の画面上側のメニューアイコンをクリックし、"アクセス権を管理"をクリックします。<br><img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/3aaf1109-5bb1-d75a-2cc9-5bb8ec51bdd3.png">
1. "ロールを割り当て"をクリックします。<br><img width="400" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/ba3008ed-4ff9-a7af-c6e0-393238ee269b.png">
1. 対象の外部アプリケーションを選択します。"ロールを選択"の項目で"Data Reader"を選択して"保存"をクリックします。<br><img width="400" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/f16ffb31-3ee0-e022-4b8f-7c41b7036db4.png">
1. "ロールを割り当て"タブのリストにおいて外部アプリケーションに"Data Reader"のロールが割り当てられていることを確認します。<br><img width="500" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/b4d78be0-a272-ef6b-3490-80f4b518b5f6.png">


:::note info
標準ロールとして設定されている***Data Reader***, ***Data Writer***はすべてのエンティティに対するアクセス権限を持っています。詳細については [標準ロールの権限](https://docs.uipath.com/ja/data-service/automation-cloud/latest/user-guide/managing-access#standard-role-permissions) を参照してください。
:::

### 個別のエンティティに対してアクセス権を付与する

エンティティ単位でアクセス権を制御する場合、カスタムロールを作成してエンティティ単位でアクセス権を設定します。作成手順は以下の通りです。

1. エンティティ一覧の画面上側のメニューアイコンをクリックし、"アクセス権を管理"をクリックします。
1. "新しいロールを作成"をクリックします。<br><img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/950a2464-78de-4271-10e0-ba70ef5d2de6.png">
1. "ロール名", "管理権限", "データのアクセス権限"を設定します。"管理権限"は***Data Reader***等の標準ロールに合わせて"スキーマの表示"を選択します。"データのアクセス権限"の箇所では"+エンティティを追加"をクリックして対象のエンティティを選択の上、付与するアクセス権を選択します。ここでは```TestEntityA```の"読み取り"権限を付与して"保存"をクリックします。<br><img width="550" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/eaf477fe-f98e-f946-8bed-f2da9b8fff33.png"><br>"ロール"の一覧に作成したカスタムロールが表示されます。<br><img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/ca767723-7dd3-0e5c-fa94-ae7a155689e1.png">
1. "ロールを割り当て"をクリックします。
1. 対象の外部アプリケーションと、上で作成したカスタムロール"TestEntityA_Read"を選択して"保存"をクリックします。<br><img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/f2fe37aa-a18e-946e-d0d2-09604ea75503.png">
1. "ロールを割り当て"タブのリストにおいて外部アプリケーションにカスタムロールが割り当てられていることを確認します。<br><img width="500" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/ccbe3071-a390-ec2d-8291-b49b798f59ed.png">



## APIリクエスト送信の実装

リクエスト送信のためのエンドポイントの確認と、リクエスト送信の実装例をご紹介します。付与したアクセス権の確認のため、***エンティティに対してロールを付与する***で紹介した通り、外部アプリケーションに対して```TestEntityA```の"読み取り"権限のみを付与した場合を考えます。


### エンドポイントの確認

対象のエンティティからAPIアクセスをクリックしてJSONファイルをダウンロードします

リクエストを送信するエンドポイントはJSONファイルの中に記載されています。
Data Service API エンドポイントの構文は次のようになっています。
```
HTTP メソッド + ベース URL + リソース カテゴリ + Data Service エンティティ + 操作 + パス変数とクエリ パラメーター
```

ダウンロードしたJSONファイルを"EntityService"の文字列で一括検索するとエンティティのエントリポイントの一覧を確認できます。
<img width="400" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/0f703a90-8164-7398-91cb-6c8778245b87.png">

参考：[Automation Cloud の Data Service ガイド > API アクセス](https://docs.uipath.com/ja/data-service/automation-cloud/latest/user-guide/api-access)



### UiPath Studioの実装例

UiPath Studioで『HTTP要求』アクティビティを使用してAPIリクエストを送信する実装例をご紹介します。
APIリクエストを送信し、アクセストークンとエンティティの情報を取得する実装例をご紹介します。アクセストークン取得のワークフローの一例は以下の通りです。

<img width="450" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/0d771040-4f63-3455-1e28-d928535a136e.png">

『HTTP要求』アクティビティの最低限必要な設定項目は以下です。
| 項目 | 値 |
|:-|:-|
| 要求URL  |  "https://cloud.uipath.com/identity_/connect/token"  |
| 応答コンテンツ | authResponse（String型の変数） |
| パラメータ | 下のテーブルに記載します |

『HTTP要求』アクティビティで設定しているパラメータのコレクションは以下の通りです。
| 名前 | 方向 | 型 | 値 |
|:-|:-|:-|:-|
| client_id  | 入力  | String  | {アプリケーションID}  |
| client_secret  | 入力  | String  | {アプリケーションシークレット}  |
| grant_type  | 入力  | String  | "client_credentials"  |
| scope  | 入力  | String  | "DataService.Default" |


返ったレスポンスをString型の"authResponse"で受け取り、『JSONを逆シリアル化』アクティビティでJsonObject型の"authResponseobj"に変換しています。正しくアクセストークンを取得できている場合、
```authReponseobj("access_token").ToString``` としてアクセストークンを取得できます。

::: note
『HTTP要求』、『JSONを逆シリアル化』アクティビティを使用するためにはUiPath.WebAPI.Activitiesパッケージをインストールする必要があります。
:::

:::note warn
"scope"には```DataService.Data.Read```等の操作に必要なスコープを直接指定せず、```DataService.Default```のみを指定します。
:::


続いてエンティティの情報取得の部分です。
『HTTP要求』アクティビティを使用して```/dataservice_/api/EntityService/TestEntityA/read```のエンドポイントにGET リクエストを送信します。リクエストの際に上で取得したアクセストークンをヘッダーに追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/fdfb9d9d-3121-12be-0c4f-479c8827b2b4.png)

『HTTP要求』アクティビティで設定しているヘッダーのコレクションは以下の通りです。
（パラメータには何も指定しません）
| 名前 | 方向 | 型 | 値 |
|:-|:-|:-|:-|
| Authorization  | 入力  | String  | "Bearer " + {上で取得したアクセストークン}  |

実行すると、TestEntityAのレコード情報がJSON形式のレスポンスとして返ります。
<img width="300" alt="Response" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/243a7a16-c8e1-a06e-dd7a-1ddf0c9616bf.png">


```TestEntityB```のエンドポイントに対して同様のリクエストを送信した場合、```"error":"You don't have permission to access the entity, field or record or you are using an unsupported robot type. Please
     | contact your administrator for necessary permissions."```のエラーが返ります。


### Power Shellの実装例

もう一つの実装例として、Power Shellによる実装例をご紹介します。

``` dsEntity.ps1
param (
    [string] $automationCloudUrl = "https://cloud.uipath.com/",
    [string] $organizationId = "{組織名}",
    [string] $tenantName = "{テナント名}",
    [string] $cliendId = "{アプリケーションID}",
    [string] $clientSecret = "{アプリケーションシークレット}",
    [string] $scopes = "DataService.Default",
    [string] $entity = "TestEntityA",
    [string] $operation = "read"
)

# Get Access Token Function
function Get-BearerToken {
    $Body = @{
       "client_id" = $cliendId
       "client_secret" = $clientSecret
       "scope" = $scopes
       "grant_type" = "client_credentials"
    }
    $tokenEndpoint = "$automationCloudUrl/identity_/connect/token"
    $response = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Body $Body -ContentType "application/x-www-form-urlencoded"
    return $response.access_token
}

# Call Token Request
$bearerToken = Get-BearerToken 

# Data Service API Function
function Invoke-DataServiceAPI {
    param (
        [string] $bearerToken
    )
    $headers = @{
        "Authorization" = "Bearer $bearerToken"
    }
    $DSEndpoint = "$automationCloudUrl/$organizationId/$tenantName/dataservice_/api/EntityService/$entity/$operation"
    $response = Invoke-RestMethod -Uri $DSEndpoint -Method Get -Headers $headers -ContentType "application/json"
    return $response | ConvertTo-Json
}

# Call Data Service Request
$dsResult = Invoke-DataServiceAPI -bearerToken $bearerToken

# Export to file
echo $dsResult > "$entity.json"
```


# おわりに

本記事では、Automation Cloudの***きめ細かいアクセス権***を使って外部のアプリケーションからUiPath Data Serviceのリソースにアクセスする方法をご紹介しました。実際にリソースを操作するクエリについては調整が必要ですが、認可の方法について参考になれば幸いです。


それでは快適なUiPathライフを！