【IBM Application Gateway】Credential Serviceを利用したアプリケーションへのユーザーID/パスワードの代行入力機能を試してみる

# はじめに

IBM Application Gatewayは、バックエンドアプリケーションにユーザーの資格情報を提供する機能がいくつか提供されています。
また、一部のアプリケーションについては、外部の資格サービス（*1,*2,*3)と連携したユーザー情報の提供機能や、ユーザー情報の学習機能も提供されています。

|連携方法  |説明  |外部資格サービスの利用（Credential Service） |資格情報の学習機能（Credential Learning） |
|---|---|---|---|
|HTTPヘッダー連携 |HTTPヘッダーにユーザー名を設定してユーザー情報を提供する|非対応 |非対応 |
|フォーム認証|フォーム認証画面にユーザーID/パスワードを代行入力する |対応 |対応 |
|基本認証（ベーシック認証）|Authorization ヘッダーにユーザ名、パスワードを設定する|対応 |非対応 |
|他連携方法|LTPA、KeAuthorization、jwtなど|非対応 |非対応 |

外部資格サービスの選択肢(*1)としては以下の3つがあります。
- IBM Security Verify
- IBM Security Verify Access
- 独自開発のサービス

今回は、外部資格サービス（Credential Service）を使ってみました。全体構成は以下のようになります。
- クライアントは、IBM Application Gateway経由で フォーム認証アプリケーション（*5)にアクセスする。
- IBM Application Gatewayは、IBM Security VerifyとOIDC連携する。
- 外部資格サービスとして、IBM Security VerifyのPassword Vaultを利用する。
- IBM Application Gatewayは、IBM Security VerifyのPassword Vaultに登録したユーザーID/パスワードをフォーム認証画面に代行入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/c7df04e9-576e-9f46-5083-c3ea30abaddb.png)



# 1.設定の流れ
以下の順番で実施します。
- 事前作業
- IBM Security VerifyのPassword Vault構成
- IBM Security Verifyへのアプリケーション登録（IBM Application GatewayとのOIDC連携）
- IBM Application Gatewayのデプロイ
- 動作確認

# 2.事前作業
Credential Serviceのサンプル設定は、[services/credential](https://docs.verify.ibm.com/gateway/docs/yaml-services-credential）にあります。

この中でenc_keyと、services/credential[]/authentication/ssoの設定がポイントになります。

```
services:
  credential:
    - name: myCredService
      enc_key: "@vault-rsa.pem"
      host: ibm_app_gw.ice.ibmcloud.com
      proxy: "proxy.ibm.com:3128"
      url_pattern: "/v1.0/pwdvault/{user}/resources/{resource}"
      ssl:
        certificate:
          - "@vault-ibm-com.crt"
        server_dn: cn=vault
        sni: vault.verify.ibm.com
      user_attribute: "AZN_PRINCIPAL_ID"
      user_attribute_encoding: url
      authentication:
        sso:
          client_id: 36bxxxx-xxxx-xxxx-xxxx-xxxxxxxxxae5
          client_secret: ctZxxxxqQs
          endpoint: https://ibm_app_gw.ice.ibmcloud.com/v1.0/endpoint/default/token
          payload: form
```

enc_keyは、IBM Application GatewayとIBM Security Verify間でパスワードの暗号化/復号化に利用するキーです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/df26f785-5b2f-0d38-7e5c-4193c35bf50b.png)

RSAの秘密鍵と、発行した証明書を結合したものをenc_keyに指定します。

```
秘密鍵生成
$ openssl genrsa -out iag_private.pem 2048
公開鍵生成
$ openssl rsa -pubout -in iag_private.pem -out iag_public.pem
証明書作成
$ openssl req -x509 -days 3000 -new -key iagJWE_privateKey.pem -out iagJWE_cert.pem
enc_key作成
cat iagJWE_privateKey.pem >> iagJWE_cert_join.pem
cat iagJWE_cert.pem >> iagJWE_cert_join.pem
```

なお、Password Vaultに保管されたユーザーのパスワードを取得するフローは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/9061d45c-0f5a-a348-c17b-00ce2f351197.png)

マニュアル（*1)にもKid Validationについて記載があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/c5c98166-8374-7c0c-aa88-294ab7dff01b.png)

次に、2つ目のポイントになるservices/credential[]/authentication/sso設定です。
こちらは、OpenID Connect連携で利用するclient_idとclient_secretとは別のものを用意する必要があります。
IBM Security Verifyに、Manage Password Vault for all usersの資格を持つAPIクライアントを登録し、発行されたclient_idとclient_secretを利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/3b7392bc-9635-d26c-df4b-35040c91b615.png)
IBM Security Verifyの管理画面で、「セキュリティ」>「APIアクセス」>「APIクライアント」から登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/b3432c3e-d8ce-175b-e0ec-32171d55f272.png)

# 3.IBM Security VerifyのPassword Vault構成
Password Vaultの構成は、password vault configuration API（*5)を利用してPUTリクエストで設定します。IBM Security Verifyの管理画面からは設定できません。

リソース名は複数設定もできます。動作確認の際には、「testresource」として登録しました。

```
PUT https://xxx.verify.ibm.com/config/v1.0/pwdvault
Body設定：
{
    "publicKey": {
        "id": "証明書のラベル名 例）CN=iag,OU=test,O=test,L=Chuoku,ST=Tokyo,C=JP",
        "key": "公開鍵"
    },
    "enabled": true
    "resources": [
        "testresource"
    ]
}
```

次に、password vault enrollment API（*5)を使って、ユーザーの資格情報を登録します。

```
PUT https://xxx.verify.ibm.com/v1.0/pwdvault/<userid>
Body設定：
{
    "resources": [
        {
            "resource": {
                "username": "ユーザー名",
                "password": "パスワード（暗号化しない状態でも登録できました）"
            },
            "name": "testresources"
        }
    ]
}
```

# 4.IBM Security Verifyへのアプリケーション登録（IBM Application GatewayとのOIDC連携）
カスタムアプリケーションを登録します。
リダイレクトURIは、https://IBM Application GatewayのアクセスURL/pkmsoidc となります。

設定を保存すると、client_idとclient_secretが発行されるのでコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/3ad7d1fc-6c78-c19f-50a5-71ae10013bf1.png)

# 5.IBM Application Gatewayの設定、Docker環境へのデプロイ
これまで登録した情報をもとにconfig.yamlを更新し、IBM Application Gatewayをデプロイします。

```config.yaml
version: "23.04"

services:
  credential:
    - name: myCredService
      enc_key: "@iagJWE_cert_join.pem"
      host: xxxxx.verify.ibm.com
      url_pattern: "/v1.0/pwdvault/{user}/resources/{resource}"
      user_attribute: "AZN_CRED_PRINCIPAL_NAME"
      user_attribute_encoding: url
      authentication:
        sso:
          client_id: xxxxx
          client_secret: xxxxx
          endpoint: https://xxxxx.verify.ibm.com/v1.0/endpoint/default/token
          payload: form

resource_servers:
  - path: "/form"
    connection_type: "tcp"
    servers:
      - host: "x.x.x.x"
        port: 80
    forms_login:
        credential_learning: false
        login_resources:
            - resource:      /login.aspx
              form_action:   "./login.aspx"
              service:       myCredService
              resource_name: testresources
              fields:
                  - name:   username
                    source: service
                    value:  username
                  - name:   password
                    source: service
                    value:  password
                  - name:   login
                    source: static
                    value:  "ログイン"
                  - name:   SSO_SOURCE
                    source: static
                    value:  "IAG-SSO"
                  - name:   LOGIN_ORIGIN
                    source: attribute
                    value:  AZN_CRED_MECH_ID
              response_rules:
                  - success: true
                    response_code: 302
                    headers:
                        - name: location
                          value: "*/default.aspx"
                  - success: false
                    response_code: 200

identity:
  oidc:
    discovery_endpoint: "https://xxx.verify.ibm.com/oidc/endpoint/default/.well-known/openid-configuration"
    client_id: xxxxx
    client_secret: xxxxx

logging:
  tracing:
    - file_name: /var/iag/trace.log
      component: pdweb.debug
      level: 9
    - file_name: /var/iag/snoop.log
      component: pdweb.snoop
      level: 9
    - file_name: /var/iag/fsso.log
      component: pdweb.wan.fsso
      level:     9
```

# 6.動作確認

IBM Application Gatewayにアクセスします。
https://127.0.0.1:8443/form/login.aspx

IBM Security Verifyにリダイレクトされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/8d7ab46d-20b9-ebed-96fd-beea1228f24d.png)

アプリケーションのフォーム認証画面が表示されずにアプリケーションにアクセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/8bf8d6b9-795e-d2cf-1e0b-de8df94a851e.png)

# 最後に
IBM Application GatewayのCredential Serviceの基本的な使い方についてご紹介しました。

# 参考
（*1)https://docs.verify.ibm.com/gateway/docs/tasks-credential-service
（*2)https://docs.verify.ibm.com/gateway/docs/yaml-services-credential
（*3)https://docs.verify.ibm.com/gateway/docs/yaml-resource_servers-forms_login
（*4)利用させて頂いたフォーム認証アプリ
https://www.atmarkit.co.jp/ait/articles/0307/26/news002.html
（*5)https://docs.verify.ibm.com/verify/reference/getpwdvaultconfiguration
（*6)https://docs.verify.ibm.com/verify/reference/getpwdvaultenrollment_10