Authorization Management Service (AMS)を利用したCAPの権限管理 - アップデート

## はじめに
以下の記事で、Authorization Management Service (AMS)を利用した権限管理について説明しました。

https://qiita.com/tami/items/70a8a67e63ec54925ac3

上の記事を書いた時点では、CAPでAMSを利用する設定をしてみてもビルドが失敗するという状況でした。その後`cds add ams`コマンドが利用できるようになり、デプロイまでできるようになったので手順を紹介したいと思います。

## ステップ
1. プロジェクトを作成
1. UIを追加
1. デプロイのための設定
1. AMSを使用する設定
1. デプロイ
1. Cloud Identity Servicesでの設定
1. SAP Build Work Zoneから利用

※cds-dkのバージョン：8.7.2

ソースコードは以下にアップしています。
https://github.com/miyasuta/cap-ams

### 1. プロジェクトを作成
以下のコマンドでプロジェクトを作成します。

```
cds init cap-ams
cd cap-ams
cds add tiny-sample //サンプルを追加
```

生成されたサービスの`Books`エンティティから`@readonly`を外してドラフトを有効にします。さらに、権限制御を追加します。

```
using my.bookshop as my from '../db/schema';

@requres: ['Admin', 'Viewer']
service CatalogService {
    @restrict: [{grant: ['READ','WRITE'], to: 'Admin'},
                {grant: ['READ'], to: 'Viewer'}]
    entity Books as projection on my.Books;
}

annotate CatalogService.Books with @odata.draft.enabled;

```

### 2. UIを追加
Fiori toolsでList Reportの画面を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/97ca519f-f7a5-47aa-9d4f-bdda676f4947.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9412711a-4215-4b8d-b8d4-fb8ccd06439d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8bcdd027-12d4-4e5e-acd1-9d680f6373b6.png)

ローカルで実行するため、package.jsonにモックユーザを追加します。
```json
  "cds": {
    "requires": {
      "[development]": {
        "auth": {
          "kind": "mocked",
          "users": {
            "alice": {
              "roles": [
                "Admin"
              ]
            },
            "bob": {
              "roles": [
                "Viewer"
              ]
            }
          }
        }
      }
    }
  }
```
`cds watch`を実行し、Adminロールをつけたユーザ"**alice**"でCRUD処理ができることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f0b42546-2981-4456-9bd7-0433ab57c562.png)

### 3. デプロイのための設定
デプロイのために以下の設定を追加します。
```
cds add hana --for production
cds add workzone
cds add mta
```

Cloud Foundryにデプロイするため、`app/<uiフォルダ>/webapp/manifest.json`でODataのuriから先頭のスラッシュを削除します。
```json
    "dataSources": {
      "mainService": {
        "uri": "odata/v4/catalog/",
        "type": "OData",
        "settings": {
          "annotations": [],
          "odataVersion": "4.0"
        }
      }
    }
```    

### 4. AMSを利用する設定
#### 4.1. AMSの設定を追加
以下のコマンドを実行します。

```
cds add ams --for production
```
その結果、package.jsonに3つのdependencyが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9b575a00-4bca-4641-acb0-d828a2f63975.png)

また、`cds.requires`セクションに以下の設定が追加されます。
```json
  "cds": {
    "requires": {
    ...
      "[production]": {
        "auth": {
          "kind": "ias"
        }
      }
```
mta.yamlにも設定が追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b2a9af2e-c3af-4c7e-8e39-dff74d32f68c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/532dc4fd-8ab2-4d14-a805-ce574392938b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/26e2f130-c069-43ff-83c5-c59c6db12e48.png)

#### 4.2. マニュアルでの調整
以下の調整を行います。

##### ①xs-app.json
- xs-app.jsonに`"authenticationType": "ias"`を追加
```json:app/uiフォルダ/xs-app.json
{
  "welcomeFile": "/index.html",
  "authenticationMethod": "route",
  "routes": [
    {
      "source": "^/?odata/(.*)$",
      "target": "/odata/$1",
      "destination": "cap-ams-srv-api",
      "csrfProtection": true,
      "authenticationType": "ias"
    },
    {
      "source": "^(.*)$",
      "target": "$1",
      "service": "html5-apps-repo-rt",
      "authenticationType": "ias"
    }
  ]
}
```
##### ②mta.yaml
- destinationモジュールから"auth"の設定を削除（`cds add workzone`により自動で追加されるが、IAS認証では使用しない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3e8b21d6-75f0-43a2-89ea-aab0fb8ae94c.png)

- IASのサービスインスタンスに`provided-apis`を追加
```yaml
  - name: cap-ams-auth
    type: org.cloudfoundry.managed-service
    parameters:
      service: identity
      service-name: cap-ams-auth
      service-plan: application
      config:
        display-name: cap-ams
        authorization:
          enabled: true
        # 追加
        provided-apis:
          - name: catalog-api
            description: api exposed by catalog service app  
```
- Destinationにプロパティ`HTML5.IASDependencyName`を追加し、前のステップで指定したAPIの名前を設定
```yaml
resources:
  - name: cap-ams-destination
    type: org.cloudfoundry.managed-service
    parameters:
      service: destination
      service-plan: lite
      config:
        HTML5Runtime_enabled: true
        init_data:
          instance:
            existing_destinations_policy: update
            destinations:
              - Name: cap-ams-srv-api
                URL: ~{srv-api/srv-url}
                Authentication: NoAuthentication
                Type: HTTP
                ProxyType: Internet
                HTML5.ForwardAuthToken: true
                HTML5.DynamicDestination: true
                # 追加
                HTML5.IASDependencyName: catalog-api
```

### 5. デプロイ
以下のコマンドでビルド、デプロイします。
```
//dependencyをインストール
npm i --prefix app/<uiフォルダ>
npm i
//ビルド、デプロイ
mbt build -t gen --mtar mta.tar
cf deploy gen/mta.tar
```
※ビルドの結果、`ams`というフォルダが作成され、中にポリシーが設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/cd960349-89c2-45f5-8b41-f417fb7e48f0.png)


### 6. Cloud Identity Servicesでの設定
以下のドキュメントに従って、Cloud Identity Servicesで設定を行います。
https://github.com/SAP-samples/btp-developer-guide-cap/blob/main/documentation/xsuaa-to-ams/3-deploy-to-cf.md#check-your-ias-application-and-uploaded-ams-policies

#### 6.1. ポリシーをユーザに割り当て
登録されたアプリケーションの"**Authorization Policies**"タブでポリシーが登録されていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3cbfa6b3-560b-4c24-a0eb-16a9494a2e1e.png)

ポリシーを選択してユーザに割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/04118940-31c4-4859-9010-ea33252c567f.png)

#### 6.2. SAP Build Work ZoneからCAPのAPIを利用するための設定
SAP Build Work ZoneとCAPはそれぞれ別のIASアプリケーションに紐づいています。Work ZoneにログインしたユーザがCAPのAPIを使用する際、ApprouterはAPIを利用する権限をもったトークンをリクエストする必要があります（トークンの交換）。このために以下のステップが必要になります。

1. プロバイダーアプリケーション（CAP）は、**Provided API**を定義する
1. コンシュマーアプリケーション（SAP Build Work Zone）は、利用するAPIを**Dependency**として登録する
1. SAP Build Work Zoneから利用するDestinationは、**IASDependencyName**というプロパティに利用するAPIを指定する
1. SAP Build Work ZoneからAPIにアクセスする際、ApprouterはDestinationに設定された**IASDependencyName**を利用してトークンの交換を行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/46d086ed-5668-4d9e-a7c5-f7306ac60991.png)

以下で設定を見ていきます。

##### ①CAPのIASアプリケーション
デプロイ時に"Provided API"が登録されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f0c904ec-cdd8-48ae-bb19-a02d38a526d1.png)

Trust -> OpenID Connect Configuration -> Advanced Settings -> Access Token Formatより、**JSON Web Token**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2d8bd7f3-e24e-4e3b-a633-ad32c794ac9a.png)

##### ②SAP Build Work ZoneのIASアプリケーション
DependencyにCAPのProviced APIで定義したAPIを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8223c983-ab36-4e30-a33c-8673e3447458.png)

##### ③Destination
デプロイ時に"IASDependencyName"が設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/33d861bd-0f8e-43ae-81cd-3648a1bacae8.png)


### 7. SAP Build Work Zoneから利用
SAP Build Work Zoneにタイルを配置し、アプリケーションを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/366eb490-2174-4646-b37d-00de871dd42b.png)
アプリケーションにアクセスできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/7d442428-e456-4d74-b814-f61504431614.png)

## 参考
- [Configure Authorization and Authentication Using the Authorization Management Service and the Identity Authentication Service](https://github.com/SAP-samples/btp-developer-guide-cap/blob/main/documentation/xsuaa-to-ams/README.md)
- [Switching to SAP Cloud Identity Services - Identity Authentication > App to App Navigation](https://help.sap.com/docs/build-work-zone-standard-edition/sap-build-work-zone-standard-edition/switching-to-sap-cloud-identity-services-identity-authentication#app-to-app-navigation)