検証環境としての Kapplets インストール・フリー構築法 ～ 超簡単 ～

## はじめに

前回構築した Management Console（以降、MC）とは別で、今回は社内で運用中のMCと連携する Kapplets 環境を構築していきます。

Kapplets を構築する基盤としては過去に紹介した Tomcat9 と MySQL8 構築を前提にします。

https://qiita.com/ParakeetOnTheHead/private/317598fb34af24633867

https://qiita.com/ParakeetOnTheHead/items/ec3821d2bc1f9c905716

:::note 
本ブログは、BizRobo! v11.3.0.2 の利用を前提に解説します。
:::

## 環境の準備

Kapplets の構築に必要なファイルやリソースを準備します。細かい調達方法は省略します。

### Kapplets構築のための調達リソース

| # | リソース | 準備方法 |
|:-:|:-|:-|
| 1  | kapplets.war  | BizRobo!のインストールフォルダ配下の`📁WebApps` から `kapplets.war` をコピー  |
| 2  |kapplets.xml  | ファイルを新規作成  |
|3|mysql-connector-java-8.0.22.jar|「[公式サイト](https://downloads.mysql.com/archives/c-j/)」から 検証用のバージョンの `Platform Independent` ZIP をダウンロードします。[^1]|

[^1]: 以下が画面のイメージ。下段のZIPをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/207b700b-39d2-28f8-f764-528d3698e282.png)

### 環境構築におけるパラメータ一覧

以下を前提として構築作業を実行

| パラメータ | 設定値 |補足|
|:-|:-|:-|
| DBのホスト名  |  localhost ||
|  DB接続ポート |  3306 ||
|  接続先DB | kapplets  ||
| 接続ユーザー名  | kapuser | |
|接続パスワード|kppassword||
|Authorization ServerのURL|http://public-bizrobo-server.com/mc|MCです。kapplets.services.mc.connection.oauth.mc-base-url を使用して、認可リクエストやトークンリクエストを受け付けます。|
|ClientのURL|http://192.168.3.13/kapplets|kapplets.services.mc.connection.oauth.kapplets-base-url を使用して、認可サーバーからリダイレクトされる際にコードを受け取ります。|
|Resource ServerのURL|http://public-bizrobo-server.com/mc|MCです。kapplets.services.mc.connection.url を使用して、アプリからのリソースリクエストを受け付けます。|

### 構築する環境のサーバー構成

ちょっとした検証作業用に、単体のPCへ一式セットアップします。すべてローカルでのアクセス前提なので、通信ポートの解放など細かいことについては考えません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/c5261cb5-706e-aacb-34ff-8dbc0b28513f.png)



### 構築環境のフォルダ構成

```bash
📁 apache-tomcat-9.0.x
 ├─ 📁 conf        # Tomcatの設定ファイルが格納されています。
 │  └─ 📁 Catalina
 │      └─ 📁 localhost
 │          └─ 📄 kapplets.xml 
 ├─ 📁 lib         # Tomcatが必要とするライブラリやクラスが格納されています。
 │  └─ 📄 mysql-connector-java-8.0.22.jar
 ├─ 📁 webapps     # TomcatにデプロイするWebアプリケーションが格納されています。
 │  ├─ 📁 kapplets
 │  └─ 📄 kapplets.war
 :
```

## 環境構築の流れ

細かい設定・調整をし始めるときりがないですが、最低限動くものを構築するのは以下の４ステップで完了です。

1. アプリケーションで利用するデータベースとユーザーの作成
1. アプリケーションで利用するコンテキストファイルの作成（DBへの接続とOAuthの設定）
1. アプリケーションファイルのサーバへの配置
1. JDBCコネクターのサーバへの配置

## 構築手順

### サーバ状態の確認

環境セットアップに先駆けて以下を確認します。

- MySQL8 サーバーが**起動**していること
- Tomcat9 サーバーが**停止**していること

***

### 1．MySQL8 へのデータベースの作成

`root` ユーザで MySQL8 サーバにログインし、以下の SQL を実行します。

```sql:DBとユーザの一括作成
CREATE DATABASE kapplets CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'kapuser'@'localhost' IDENTIFIED BY 'kppassword';
GRANT ALL PRIVILEGES ON kapplets.* TO 'kapuser'@'localhost';
```
- `kapplets` という名前のデータベースを作成
- localhost からのみアクセス可能な `kapuser` というユーザを作成
- `kapplets` データベースに対してすべての権限を付与

***

### 2．Tomcat コンテキストファイルの作成

`📁 conf\Catalina\localhost` 配下に `📄 kapplets.xml` という名前でファイルを生成し、テキストエディタで以下記述します。（UTF-8で保存）

**BOM** なし保存が必須。[^2]

[^2]: https://uxmilk.jp/48923

:::note warn
`kapplets.xml` のフォーマットはバージョンによって異なる場合があります。先日 v11.5 を使って再度試してみたところ、一部下記（v11.3）とは差異があり Kappletsの起動に失敗しました。
:::

```xml:kapplets.xml （v11.3）
<?xml version='1.0' encoding='utf-8'?>
<Context useHttpOnly="true">
  <!-- Default set of monitored resources -->
  <WatchedResource>WEB-INF/web.xml</WatchedResource>
  <Resource name="jdbc/kapow/kapplets" auth="Container"
    type="javax.sql.DataSource"
    initialSize="5" maxTotal="100" maxIdle="10" maxWaitMillis="-1"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    validationQuery="/* ping */" testOnBorrow="true" testWhileIdle="true"
    username="kapuser" password="kppassword"
    driverClassName="com.mysql.cj.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/kapplets?autoReconnect=true&amp;allowPublicKeyRetrieval=true&amp;useSSL=false&amp;useLegacyDatetimeCode=false&amp;serverTimezone=GMT%2B9"
  />
  <Environment name="spring.datasource.jndi-name" 
    value="jdbc/kapow/kapplets" 
    type="java.lang.String" override="false"
  />
  <Environment name="spring.jpa.database-platform" 
    value="org.hibernate.dialect.MySQL8Dialect" 
    type="java.lang.String" override="false"
  />
  <Environment name="kapplets.services.mc.connection.url" 
    value="http://public-bizrobo-server.com/mc" 
    type="java.lang.String" override="false"
  />
  <!-- url user can access with browser -->
  <Environment name="kapplets.services.mc.connection.oauth.kapplets-base-url"
    value="http://192.168.3.13:8080/kapplets" 
    type="java.lang.String" override="false"
  />
  <!-- url user can access with browser -->
  <Environment name="kapplets.services.mc.connection.oauth.mc-base-url" 
    value="http://public-bizrobo-server.com/mc" 
    type="java.lang.String" override="false"
  />
</Context>
```

- `useSSL=false&amp;allowPublicKeyRetrieval=true`：MySQL8 で推奨の caching_sha2_password という認証プラグインを使用する場合に必要な設定です。`useSSL` については本番環境では `true` にする必要がありますが、サッと作る検証環境では、`false` でいいでしょう。

<details><summary>v11.5 のパターン</summary>

```xml:kapplets.xml （v11.5）
<?xml version='1.0' encoding='utf-8'?>
<Context useHttpOnly="true">
  <!-- Default set of monitored resources -->
  <WatchedResource>WEB-INF/web.xml</WatchedResource>
  <Resource name="jdbc/kapow/kapplets"
    auth="Container"
    type="javax.sql.DataSource"
    initialSize="5"
    maxTotal="100"
    maxIdle="10"
    maxWaitMillis="-1"
    validationQuery="/* ping */"
    testOnBorrow="true"
    testWhileIdle="true"
    username="kapuser" password="kppassword"
    driverClassName="com.mysql.cj.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/kapplets?autoReconnect=true&amp;allowPublicKeyRetrieval=true&amp;useSSL=false&amp;useLegacyDatetimeCode=false&amp;serverTimezone=GMT%2B9"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    />
  <Environment name="spring.datasource.jndi-name"
               value="jdbc/kapow/kapplets"
               type="java.lang.String" override="false"
               />
  <Environment name="spring.jpa.database-platform"
               value="org.hibernate.dialect.MySQL8Dialect" 
               type="java.lang.String" override="false"
               />
  <Environment name="kapplets.services.mc.connection.url"
              value="http://localhost:50080"
               type="java.lang.String" override="false"
               />
  <Environment name="kapplets.services.mc.connection.service.kapplets-base-url"
               value="http://localhost:8080/kapplets" 
               type="java.lang.String" override="false"
               />
  <Environment name="kapplets.services.mc.connection.service.mc-base-url"
               value="http://localhost:50080"
               type="java.lang.String" override="false"
               />
  
  <Environment name="kapplets.app.default.language" 
               value="ja" type="java.lang.String" override="false"
               />
</Context>
```
</details>

***

### 3．Web Application aRchive（war）ファイルの配置

`📁 webapps` 配下に `📄 kapplets.war` を配置します。

***

### 4．jdbc ドライバーの配置

`📁 lib` 配下に `📄 mysql-connector-java-8.0.22.jar` を配置します。

***

### Tomcat の開始

Tomcat を起動して Kapplets へアクセスします。 MC のログイン画面へリダイレクトされれば環境の構築は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/badf3c76-8252-90e8-70e6-bef03c669783.png)
後で使用するので、画面は開いたままにしておきます。:frowning2:

## Kapplets の認証・認可設定

Kapplets は MC を Resource Server としてユーザーの認証・認可を行います。 Kapplets を MC の Client として認証するために以下では ~~クライアントクレデンシャルズ~~ 認可コードフロー[^3] 方式の OAuth2 認証設定を行います。

[^3]: MC側で認可し、結果アクセストークンの発行をしてもらっているので、認可コードフローでした。（2023.08.27）


### 認証の流れ

- `Client`：Kapplets
- `Authorization Server`：MC（認可サーバー機能）
- `User`：:grinning: （ログイン情報を入力する）
- `Resource Server`：MC（登録ユーザー情報）

```mermaid
sequenceDiagram
autonumber
Client->>Authorization Server: 認可リクエスト
Authorization Server->>User: ユーザ認証
User->>Authorization Server: ユーザ承認
Authorization Server->>Client: 認可レスポンス(コード)
Client->>Authorization Server: トークンリクエスト(コード)
Authorization Server->>Client: トークンレスポンス(アクセストークン)
Client->>Resource Server: リソースリクエスト(アクセストークン)
Resource Server->>Client: リソースレスポンス
```
:::note
`Client` は、`Authorization Server` にアクセストークンを要求するためにトークンリクエスト（⑤）を行います。トークンリクエストには、**クライアントシークレット**が含まれます。クライアントシークレットは、`Authorization Server` が `Client` を認証するために使用されます。`Authorization Server` が `Client` を認証すると、アクセストークンを `Client` に返します（⑥）。アクセストークンは、リソースサーバーへのリクエストに使用されます。

クライアントシークレットは、`Client` が `Authorization Server` と安全に通信するために使用される秘密鍵です。クライアントシークレットは、`Client` と `Authorization Server` の間で共有され、他の誰にも公開されるべきではありません。
:::

### クライアントシークレットの取得

1. ブラウザで別ウィンドウを開き、Kapplets と連携させたい MC を開きます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/3db878e9-fc62-906d-ace3-3783fd47d3af.png)
1.  admin でログインし、`管理` > `OAuth サーバー` からクライアントシークレットを取得しておきます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/d62058b7-c840-b47f-e782-d5b971cc925e.png)

### クライアントシークレットの設定

1. 前段の「Tomcat の開始」でアクセスしたリダイレクト後のログイン画面から admin で MC にログインします。
1. 以下のように「OAuth認証に失敗しました」という表示が出るので、再度画面中央のボタン「Management Console にログイン」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/27fbed3e-4c71-8452-5663-9d417fbceb3c.png)
1. 新たに表示される枠内をクリックし、先ほどコピーしたクライアントシークレットを登録します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/65e80ef2-9c52-7065-c20c-ed05fe2094fa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/9dfefad8-8244-e937-b846-54e730509a06.png)
1. 「更新」ボタンをクリックすると Kapplets の画面へリダイレクトされ、ログインが完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/cbc91ce2-0ecf-5a52-d941-ff89a83fc592.png)

## インストール・フリー な Kapplet を使った開発・検証

Kapplets の検証をするためだけに MC から一式作成する必要はなく、本件も会社内で実際に稼働させている別ネットワークの MC と認証しています。
なので、実質１台の MC に複数の Kapplets が接続している状態ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/30e776dc-897d-50b2-dddb-9ef8dc025e11.png)

BizRobo! は v11 で Kapplets が外部アプリケーションとして独立しました。それによりプロジェクトや部門ごとに独自の Kapplets を構築できるようになりました。構築自体も本稿のように手軽に実施可能で、v10系のように Kapplets が MC のリソースに負荷をかけることもないので応用の幅も大きいですね。

## まとめ

以前、「他部門の Kapplets も一緒に表示されてしまう。不具合だ！修正しろ！」という問い合わせがあったようです。もし v10系を利用されているようであれば、バージョンアップされることを強くお勧めしたいですね。（まぁ、そんな簡単な話ではないでしょうが。）