この記事はkintone Advent Calendar 2021 4日目の記事です。
先月「いいね!(簡易アンケート)プラグイン EX」にセキュアアクセス環境から利用できる機能を追加しました。今年のAdvent Calendarでは今回の対応で得た学びを共有します。
前提
いいね!(簡易アンケート)プラグイン EXにはAPIトークンで更新する機能があります。これは利用者にはレコード更新権限を付与したくない、でもいいねは利用したい、という場合を想定しています。例えば、全社員に重要な案内を出す場合にレコードは更新させたくないけど、「案内を確認したよ」としていいねを利用する場合です。
今回はこの「APIトークンで更新する」という機能が前提となります。セッション認証で良い場合は特に必要のない知識になります。
また、Basic認証は考慮していません。
対応前の状況
対応前のプラグインの利用可否とリクエストに利用している関数は以下のとおりです。
セキュアアクセスが不要な環境 | セキュアアクセスが必要な環境 | |
---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() |
APIトークンを利用する | ◯:kintone.plugin.app.proxy() | ×:kintone.plugin.app.proxy() |
セキュアアクセスが不要な環境というのはIPアドレス制限がかかっていない環境もしくはIPアドレス制限がかかっているが、許可されたIPアドレスからのアクセスを意味します。セキュアアクセスが必要な環境は許可されていないIPアドレスからのアクセスを意味します。
kintone.plugin.app.proxy()を利用しているのはAPIトークンを隠匿するためです。詳細は以下のURLを参考にしてください。
実際にはIPアドレス制限をかけた通常環境からも利用できていなかった
前述の通りセキュアアクセスが必要な環境でAPIトークンを利用する場合にのみ問題があると考えていましたが、実際は通常環境からも利用できていませんでした。kintone.plugin.app.proxy()を利用するとkintoneサーバー経由のリクエストとなり、セキュアアクセスが必要な環境からのアクセスと同じ扱いになるからです。
セキュアアクセスが不要な環境 | セキュアアクセスが必要な環境 | |
---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() |
APIトークンを利用する | ×:kintone.plugin.app.proxy() | ×:kintone.plugin.app.proxy() |
以降はkintone.plugin.app.proxy()をkintone.proxy()を表記します
まとめると以下の通りです。
IPアドレス制限なし | IPアドレス制限あり 許可されたIP | IPアドレス制限あり 許可されていないIP | |
---|---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() | ◯:kintone.api() |
APIトークンを利用する | ◯:kintone.proxy() | ×:kintone.proxy() | ×:kintone.proxy() |
没案 APIトークン認証を利用する場合はクライアント証明書も利用する
最初に考えたのはAPIトークンを利用する場合はクライアント証明書も利用する案です。
IPアドレス制限なし | IPアドレス制限あり 許可されたIP | IPアドレス制限あり 許可されていないIP | |
---|---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() | ◯:kintone.api() |
APIトークン& クライアント証明書 | ? | ? | ? |
IPアドレス制限なしの場合であってもクライアント証明書を必要とする、という矛盾した状態です。別ドメインへのリクエスト扱いになるということを伝えたくて記載しています。
クライアント証明書を利用する場合はリクエスト先のURLをxxx.s.cybozu.comにする必要があります。IPアドレス制限なしの場合はブラウザが別ドメインへのリクエストと判断して以下のエラーが発生しました。
Preflight response is not successful
XMLHttpRequest cannot load https://xxx.s.cybozu.com/k/v1/record.json due to access control checks.
IPアドレス制限なし | IPアドレス制限あり 許可されたIP | IPアドレス制限あり 許可されていないIP | |
---|---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() | ◯:kintone.api() |
APIトークン& クライアント証明書 | ×:rest-api-client | ×:rest-api-client | ◯:rest-api-client |
そのためこの案は利用できませんでした。
リクエストにはクライアント証明書に対応している@kintone/rest-api-clientを利用しました。
まとめ
APIトークンとAPIトークン&クライアント証明書を使い分けるしかないということがわかりました。まとめると以下のとおりです。
IPアドレス制限なし | IPアドレス制限あり 許可されたIP | IPアドレス制限あり 許可されていないIP | |
---|---|---|---|
APIトークンを利用しない | ◯:kintone.api() | ◯:kintone.api() | ◯:kintone.api() |
APIトークンを利用する | ◯:rest-api-client ※1 | ◯:rest-api-client | – |
APIトークン& クライアント証明書 | – | – | ◯:rest-api-client |
※1 この枠のみ、kintone.proxy()を利用できるのですが、いいね!(簡易アンケート)プラグイン EXではkintone.proxy()を利用せずにrest-api-clientを利用しています。
内容もまとめておきます。
- クライアント証明書を利用する場合はxxx.s.cybozu.comにリクエストする必要がある
- xxx.cybozu.comからxxx.s.cybozu.comへのリクエストは通らない(Preflight response is not successful)
- IPアドレス制限利用&APIトークンでkintoneにリクエストする場合
- 許可されていないIPアドレスからは認証情報(APIトークン)を隠匿できない
隠匿にはkintone.plugin.app.proxy()を利用する必要があるが、kintone.plugin.app.proxy()にはクライアント証明書を含むリクエストを設定できない - 許可されたIPアドレスからも認証情報(APIトークン)を隠匿できない
隠匿にはkintone.plugin.app.proxy()を利用する必要があるが、kintone.plugin.app.proxy()を利用するとkintone経由のアクセスとなり、許可されていないIPアドレスからのリクエストとなる
kintoneのIPアドレスを許可すると全サブドメインからアクセス可能になる
- 許可されていないIPアドレスからは認証情報(APIトークン)を隠匿できない