Konnectで開発者ポータルを作成して公開する

社内のAPIが増えるにつれ、APIがサイロ化して車輪の再発明的なものが発生しやすくなる。
こういった問題を防ぐために、社内にAPIのポータルを用意して色んなチームでAPIを使い回すように進めるケースが増えている。
また、社内だけでなく社外にAPIのポータルを公開し、API経由でより自社のサービスを利用してもらうようなケースも増えている。
（例：[三菱UFJ銀行](https://developer.portal.bk.mufg.jp/)、[NTTコミュニケーションズ](https://developer.ntt.com/)）

こういったポータルを用意してAPIを利活用するのはやった方がいいのは間違いないが、用意するのがなかなか難しい。
幸いなことにKong GatewayのSaaS版であるKonnectにはAPI利用者向けに開発者ポータル(Dev Portal)を提供する機能があるので、今回はこの使い方を確認する。

ちなみにKong GatewayにもDev Portalは存在していたが、[3.5でなくなった](https://docs.konghq.com/gateway/latest/breaking-changes/35x/#dev-portal-and-vitals)。

# 基礎知識
Konnectでポータル機能を使う上で重要な2つの機能がある。
- API Products
- Dev Portal

ざっくり言うと、API ProductsはAPIのリストで、どういうAPIがあるか、どういう仕様か、どのようにアクセスできるか、などが定義されている。
Dev Portalは開発者向けポータルであり、API管理者に利用を許されたAPIを実際に選んで公開するためのポータルである。
絵にするとおそらく以下のような感じになる。
![20240614183339.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/e87e881a-af1d-4c3f-1e6e-aa908f2af903.png)  

カタログとは言っているが、実際には既にAPIのエンドポイントは全てデプロイ済みであり、開発者にAPIのエンドポイントを公開するための仕組みがDev Portalと言える。

なお、API Productの個々のAPIがどのような情報を管理しているかは以下となる。
![20240614183750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/759d87ce-5e73-6ab5-8443-1c3ed9e3fb50.png)
 
APIそのものの説明資料となるDocumentationがあり、またAPI Productはバージョンで管理され、各バージョンにはSpec(仕様書)、Service/Route、公開先Dev Portalの情報が含まれるようになる。

これを上手く使えば、本番環境専用のPortalには本番環境へのService/Routeが設定されたAPIを公開し、開発者向けには開発環境向けのService/Routeが設定されたAPIを公開する、みたいな感じで環境ごとの分離にも活用できる。

# 検証

今回は以下の手順でDev Portalの使い方を確認する。
1. 対象サービスへのService/Routeの作成
2. API Productの登録（API管理者作業）
   1. APIをAPI Productとして登録
   2. APIのドキュメントを登録
   3. APIの仕様書を登録
   4. APIをDev Portalへ公開
3. Dev Portalで利用（開発者作業）
   1. アプリケーションを定義
   2. アプリケーションにAPIを紐づけ
   3. 動作確認

なお、APIを投げる対象となるサービスは[httpbin](https://httpbin.org)を利用する。
手順は多いが、UIでポチポチやるのがほとんどなのでそれほど大変ではない。

また前提として、以下が揃ってるものとする。
- Konnectへアクセスできるアカウント
- Konnect上にControl Planeが作成済み
- Control Planeに対応するData Planeもデプロイ済み

自分の場合は[Dedicated Cloud Gateway](https://qiita.com/ipppppei/items/7b6e5bb936fa3b70e6bf)を使ってブラウザのみで検証した。

## 対象サービスへのService/Routeの作成
最初にServiceを作成する。
![20240614190022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/86fdc9b2-f792-0898-3ac5-56e7d7cf70b0.png)
 
httpbinを使うので、Upstream URLに`https://httpbin.org`を設定する。
次にRouteを作成する。
`Service`に作成したServiceを指定し、Pathsに`/httpbin`を設定、その他はデフォルトで作成する。

作成後、不安な人は動作確認しておく。Data Planeをローカルのポート8000に展開している場合は以下のような感じで確認できる。
```sh
curl localhost:8000/httpbin/ip
```
レスポンスコード200が返ってくればOK。

## API Productの登録（API管理者作業）
### APIをAPI Productとして登録
最初にAPI Productを作成する。
左サイドバーの`API Products`->`API Product`からAPI Productを作成する。
ここではProduct Nameを`httpbin`としてSaveした。

次に作成したProductを開いた状態で、左サイドバーの`Product Versions`->`New Version`でバージョンを作成する。
![20240614190712.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/93eb1c56-8aa7-9892-e409-c26ba0055c70.png)


名前はここでは`v1`としたが、文字列であれば何でもよい。
作成後、`v1`をクリックすると`Add New Version Spec`と表示されるのでUploadをクリックする。
![20240614190838.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/6468fae7-86dc-1522-3235-4c36109bfddc.png)

ここではAPIの仕様書としてOpenAPI Specification形式のファイルを選択してアップロードすることが出来る。
以下のファイルを作成してアップロードした。
```yaml:oas-httpbin.yaml
openapi: 3.0.0
info:
  title: httpbin
  version: "0.1"
paths:
  /get:
    get:
      operationId: /get
      responses:
        "200":
          description: "get: response 200"
  /post:
    post:
      operationId: /post
      responses:
        "200":
          description: "post: response 200"
servers:
  - url: https://httpbin.org
```

アップロードが完了すると、Swagger UIみたいなAPI Specのプレビュー画面が見れるようになる。

次にService/Routeを選択し、どのサービスを参照するものかを定義する。
`v1`の画面から`Routes`->`+ Link`をクリックする。

![20240614191143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/fa70a667-f52c-22a8-a177-0e903a76a5b1.png)
 
Control PlaneとServiceを選択する画面になるので、それぞれ選択すると、Routeが取り込まれる。

### APIのドキュメントを登録
次にAPIの補足資料となるようなドキュメントを登録する。
これはMarkdown形式で書かれたファイルを指定する事ができる。
Mermaidも指定できるようなので、確認のために以下のファイルを使う（動作確認のためだけなので、内容は適当）。
<details><summary>doc-sample.md (クリックして全表示) </summary><div>


<pre>
## Product xxxの概要
### 使い方
以下のように叩くとレスポンスが返る。
```
curl https://proxy/httpbin/ip
```
### 仕組み
以下のようにして動作する。
```mermaid
sequenceDiagram
    participant ブラウザ as ブラウザ
    participant サーバ as サーバ
    participant DB as データベース

    ブラウザ->>サーバ: HTTPリクエスト（GET /index.html）
    サーバ-->>ブラウザ: HTTPレスポンス（ステータスコード 200 OK, HTMLコンテンツ）

    ブラウザ->>サーバ: HTTPリクエスト（POST /login）
    サーバ->>DB: 認証情報の確認
    DB-->>サーバ: 認証情報の確認結果
    サーバ-->>ブラウザ: HTTPレスポンス（ステータスコード 200 OK, セッション情報）

    ブラウザ->>サーバ: HTTPリクエスト（GET /user/data）
    サーバ->>DB: データ取得
    DB-->>サーバ: データ返却
    サーバ-->>ブラウザ: HTTPレスポンス（ステータスコード 200 OK, ユーザーデータ）
```
</pre>

</div></details>

アップロードが終わると以下のようにドキュメントが確認できる。
![20240614191828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/97bf7861-47f5-c886-7dfa-b53713cdca06.png)


### APIをDev Portalへ公開
APIをDev Portalに公開するのだが、Dev PortalでAPIを利用する際に認証が必ず必要となっているため、その認証方法をDev Portalの設定から作成する。
左サイドバーの`Dev Portal`->`Application Auth`から`New Auth Strategy`を選択する。
作成用のウィンドウが出るので値を設定して認証方法を作成する。
ここでは以下で作成した。
- Name: `key`
- Display Name: `key auth`
- Auth Type: `Key-Auth`

作成が終わると以下のような感じで表示される。
![20240614192110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/8913eb0c-5b23-e892-54fa-bec98ee21d9f.png)

`Active`については実際にDev Portal側で認証を使う設定を行うまでNoのままとなる。

次にAPI Productで`v1`を選択するところまで戻って、`Dev Portals`のタブから`Browse Dev Portals`を選択する。
![20240614192430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/76890a95-f2fc-da9d-432c-30b22284a4de.png)

設定画面に遷移後、最初に`Require Authentication`をOnにする。
すると設定項目が増えるので以下の画像のように設定してSaveする。
![20240614192604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/b5286ff6-5fec-c854-61f5-272a562cf6f4.png)

なお、`Auto Approve`はデフォルトでOffになっているが、アプリケーションの利用時に認証を入れるかどうかの設定で、今回は手順を簡略化するためにOnとした。

最後にAPIを公開する。
API Productsの画面からAPI Productの`︙`をクリックし、`Publish`を選ぶとDev PortalからAPI Productが見えるようになる。
![20240614192754.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/04647a67-a911-2164-3036-ab3ed915f9e3.png)

## Dev Portalで利用（開発者作業）
ここでは開発者がカタログからAPIを選んで自身のアプリケーションに紐づけて公開するところを試す。
なお、先程API Productを公開したことにより、APIのSpecやDocumentationがDev Portal上から確認できるようになっている。
Specはこちら。
<img alt="picture 13" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/76ac514d-cc41-5d0a-2b00-6f2b4dd994c9.png" width=400 />  
  
Documentationはこちら。
<img alt="picture 13" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/59c99626-80a4-697e-375c-340082fcb9e0.png" width=400 /> 

バグなのかMermaidは現時点ではDev Portalから正しく表示できないが、Markdownの基本的な記述は表示できているようだ。
なお、API SpecやDocumentationの内容はAPI Product側を更新するとDev Portal側のものも即座に更新される。

### アプリケーションを定義
Dev Portalにログインすると登録したProductが見えるが、これは一旦置いておいて、`<アカウント名>`>`My Apps`でアカウントに紐づけられたアプリケーションの画面に遷移し、`New App`からアプリケーションを作成する。
ここでは以下のようにした。
<img alt="picture 13" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/58371e05-f60e-1a88-1be8-81ff15372ee5.png" width=300 />  
`Reference ID`は`Generate`をクリックして自動生成したものを使った。
これでアプリケーションの箱が出来た。
ただ、まだAPIは紐づけられていないため、この開発者が自由にAPI Productを使える状態にはなっていない。

### アプリケーションにAPIを紐づけ
Dev Portalのトップ画面から先程登録したProductを選択し`Register for v1`をクリックし、その先で先程作成したアプリケーション(`my-httpbin`)を選択して`Request Access`をクリックする。
![20240617101606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/aad25cb9-3ddb-7585-f995-149c64790591.png)

クリック後、アプリケーションの画面に遷移する。
ここで下にスクロールするとProductsのところでAPI Product `httpbin`が紐づけられていることが確認できる。

次にその上のAuthenticationのところにある`+ Generate Credential`をクリックしてAPI Productを利用するための鍵を生成する。名前はここでは`myhttpbin-key`とした。
鍵を生成すると以下のようにクレデンシャルが表示されるのでコピーして控える。

<img alt="picture 16" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/73afe22b-caab-44be-bbfd-8d51b3ac2cf3.png" width=350 />  


この値は再確認出来ないため、忘れてしまった場合は再発行が必要となる。


### 動作確認
アプリケーションで発行した鍵を使ってhttpbinにアクセスする。
まず、普通にアクセスしてみる。
```sh
$ curl -i localhost:8000/httpbin/ip
HTTP/2 401
date: Mon, 17 Jun 2024 01:25:16 GMT
content-type: application/json; charset=utf-8
content-length: 81
x-kong-response-latency: 1
server: kong/3.7.0.0-enterprise-edition
x-kong-request-id: 404b4675c5f08b41b624b4285ac5c119

{
  "message":"Unauthorized",
  "request_id":"404b4675c5f08b41b624b4285ac5c119"
}
```
401が返ってくる。
次に鍵を指定してアクセスしてみる。
鍵の名前はKey authの設定の際に`apikey`としたので、`apikey: <アプリケーションのクレデンシャル>`でアクセスできるはずだ。

```sh
$ curl -i localhost:8000/httpbin/ip -H "apikey: USJ0GYWoLHcI6CiW01XVUtRWOT4QUYGo"
HTTP/2 200
content-type: application/json
content-length: 50
date: Mon, 17 Jun 2024 01:26:39 GMT
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true
x-kong-upstream-latency: 576
x-kong-proxy-latency: 13
via: kong/3.7.0.0-enterprise-edition
x-kong-request-id: 00fc074ca99304410e7e74441b44ba72

{
  "origin": "xxx.xxx.xxx.xxx"
}
```
問題なくアクセスできた。
これにより、このアプリケーションはこの開発者が自由に鍵を発行して利用することが出来るようになったことが確認できた。

## まとめ
KonnectのAPI ProductとDev Portalを使えばAPIの一覧をカタログ化し開発者に公開することが出来、さらに開発者は自由に認証を設定して公開できることが確認できた。
またDev Portal上で仕様やドキュメントも確認できるため、APIの利活用やサイロ化防止に使えそうである。