UiPath Automation Cloud: きめ細かいアクセス権の細かい話

# Automation Cloudの外部アプリケーションとは？

外部アプリケーションを登録することにより、Automation Cloud上で利用しているUiPathのサービスとサードパーティのアプリケーションを連携することができます。外部アプリケーションにはスコープと許可の種類を設定でき、それに対応したアクセストークンを取得することができます。許可の種類として、"認可コード"、"クライアント資格情報"、"PKCEによる認可コード"があります。その他の情報と基本的な設定方法については以下のガイドを参照してください。

参考：[外部アプリケーションを使用して UiPath のリソースにアクセスする](https://docs.uipath.com/ja/automation-cloud/automation-cloud/latest/admin-guide/setting-up-the-external-application)


# きめ細かいアクセス権管理

組織レベルのアプリケーションでは、組織の全てのリソースに対してアクセス権が付与されます。組織の中でアクセスを許可するリソースを細かく制御したい場合、例えばあるテナントのOrchestratorにおいて「```フォルダA```にはアクセスさせたいが、```フォルダB```にはアクセスさせたくない」といったような場合、上記の認可の方法では権限を過剰に付与してしまう問題があります。

<img width="450" alt="access_externalapps" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/f842aa1f-b933-c7f9-17ff-1db96468fdc7.png">

外部アプリケーションの***きめ細かいアクセス権管理***を使用することで、アクセス権を付与するフォルダ、テナント等のリソースを細かく設定できます。

<img width="450" alt="finegrained_externalapps" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/373c83d5-0404-cfd1-8703-6d0bdeb14dca.png">


参考：[外部アプリのきめ細かいアクセス権を設定する](https://docs.uipath.com/ja/orchestrator/automation-cloud/latest/user-guide/configuring-access-for-external-apps)


# 設定手順

きめ細かいアクセス権管理で必要な手順は以下です。
1. 外部アプリケーションの追加
1. サービス側のロール設定
1. リクエスト送信の実装

ここではOrchestratorのフォルダアクセス（ジョブ情報の取得）を例に説明します。以下のように、FolderAとFolderBを用意し、FolderAとFolderBで実行された"LogHello"というジョブの情報を```/odata/Jobs```のエンドポイントを使用して取得する場合を考えます。
<img width="600" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/525fde35-493b-bda2-1e23-a1a47f90c46f.png">



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

Automation Cloudの管理ページより、外部アプリケーションを追加します。手順は以下の通りです。

1. Automation Cloudの　管理 > 外部アプリケーション　を開きます。<br><img width="600" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/d56cee31-863b-b1a0-6b4f-9a6bdcee1ec8.png">
2. "+アプリケーションを追加"を選択します。<br><img width="600" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/4faf809f-7df2-6649-b22c-ef067fbc2667.png">
3. 任意の"アプリケーション名"を設定し、**リソースとスコープの設定をせず**"追加"をクリックします。ここでは機密アプリケーションを選択します。<br><img width="500" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/df454cfb-b6b5-b60f-44ed-dda3e1489aee.png">
表示されるアプリケーションIDとアプリケーションシークレットをメモします。外部アプリケーションの追加作業は以上です。


## サービス側のロール設定

1. Orchestratorのページにアクセスし、対象のテナント、フォルダのページを開きます。ここではFolderAに対してジョブを表示するロールを割り当てます。比較のため、FolderBにはロールを割り当てない設定とします。<br><img width="600" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/9d71a448-956b-0d87-6bbe-5a3bb2d4f10f.png">
1. ユーザー > "アカウント/グループを割り当て"を開きます。
1. "アカウント、グループ、または外部アプリ"の欄で追加した外部アプリケーションを選択します。ここでは"+新しいロール"より```ジョブ:表示```を許可した"JobsRead"というロールを作成して割り当てます。<br><img width="500" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/0f67c96c-cd9f-c573-7f83-e68196f02050.png">
1. ユーザー一覧に表示されていれば、ロール設定は完了です。<br><img width="500" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/19df6d2c-1989-6c00-da0e-51e7b8b32a36.png">




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

### UiPath Studioの実装例

『HTTP要求』アクティビティを使用してAPIリクエストを送信し、アクセストークンとフォルダのジョブ情報取得する実装例をご紹介します。アクセストークン取得のワークフローの一例は以下の通りです。
<img width="400" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/7553cfd9-f54f-b9ec-6927-44548aa1afe4.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  | "OR.Default" |

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

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

:::note warn
ここで指定するscopeに```OR.Jobs.Read```等の操作に必要なスコープを直接指定しないようにします。指定した場合、```{"error":"invalid_scope"}```のエラーが返り、アクセストークンを取得できません。
また、```OR.Default```の大文字小文字に注意してください。"D"が大文字である必要があります。```OR.default```としてもアクセストークンを取得できますが、取得したトークンでAPIコールすると権限不足のエラーが返ります。
:::


次にジョブ情報の取得部分です。
フォルダで実行されたジョブを取得するにはフォルダの情報を```X-UIPATH-OrganizationUnitId```として指定する必要があります。フォルダのページを開いた時にアドレスバーに表示される```fid=```の箇所を確認するか、```/odata/Folders```のエンドポイントを使用して対象のフォルダのIDを取得しておくとよいと思います。Swaggerで簡単に確認できます。Swaggerの使い方については [UiPath OrchestratorのAPIをSwaggerで簡単に試してみる](https://qiita.com/cazu/items/284444110c93ceb7bd09) を参考にしてください。

ジョブを取得するワークフローの一例は以下の通りです。
『HTTP要求』アクティビティを使用して```/odata/Jobs```のエンドポイントにリクエストを送信します。リクエストの際に上で取得したアクセストークンをヘッダーに追加します。

<img width="400" alt="WF_jobs" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/6e0d1518-1960-97c0-95a6-e0f27d940a75.png">

『HTTP要求』アクティビティの設定項目は以下です。
| 項目 | 値 |
|:-|:-|
| 要求URL  |  "https://cloud.uipath.com/{組織名}/{テナント名}/odata/Jobs"  |
| 応答コンテンツ | jobsResponse（String型の変数） |
| ヘッダー | 下のテーブルに記載します |

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

実行すると、FolderAのジョブ実行情報がJSON形式のレスポンスとして返ります。
<img width="400" alt="Response" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334074/c1a643f8-1fd9-be24-5b05-0d12f0a21844.png">
FolderBに対して同様のリクエストを送信した場合、ロールを設定していない為```"You are not authorized!"```のエラーが返ります。このように、きめ細かいアクセス権を使用することで適切なアクセス権を付与できることが確認できました。


参考：
[Orchestrator Automation Cloud API Guide > ジョブの要求](https://docs.uipath.com/ja/orchestrator/automation-cloud/latest/api-guide/jobs-requests)
[UiPath OrchestratorのAPIをSwaggerで簡単に試してみる](https://qiita.com/cazu/items/284444110c93ceb7bd09)


### PowerShellの実装例

もう一つ例を挙げるとして、Powershellスクリプトによりアクセストークン取得とジョブ情報取得をする実装例を掲載しておきます。Invoke-RestMethodを使用してリクエストを送信しています。最後に取得したレスポンスをjobs.jsonのファイルに書き出しています。


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

# Get Access Token Function
function Get-BearerToken {
    $Body = @{
       "client_id" = $clientId
       "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

# Get Jobs Function
function Invoke-GetOCJobsAPI {
    param (
        [string] $bearerToken,
        [string] $folderId
    )
    $jobsEndpoint = "$automationCloudUrl/$organizationId/$tenantName/orchestrator_/odata/Jobs"
    $headers = @{
        "Authorization" = "Bearer $bearerToken"
        "X-UIPATH-OrganizationUnitId" = $folderId
    }
    $response = Invoke-RestMethod -Uri $jobsEndpoint -Method Get -Headers $headers -ContentType "application/json"
    return $response| ConvertTo-Json -Depth 5
}

# Call Jobs Request
$jobsResult = Invoke-GetOCJobsAPI -bearerToken $bearerToken -folderId {フォルダID}

# Export to file
echo $jobsResult > jobs.json
```




# おわりに

最後まで読んで頂きありがとうございました。本稿では外部アプリケーションのきめ細かいアクセス権を使ってアクセス権を管理する方法をご紹介しました。サードパーティのツールからAPI連携をする際には便利な機能だと思います。ぜひ活用してみてください。

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