Zendeskアプリ開発でAPIキー等のシークレットを安全に扱う方法

2023.05.06

こんにちは、ゲームソリューショングループの入井です。

Zendeskのアプリ開発時、外部Web APIとの連携が必要になることがあります。Zendeskアプリは一般的なWebフロントエンドアプリと同様、HTTPリクエストで外部Web APIとの連携を行います。

ほとんどのWeb APIでは、HTTPリクエストを送信する際に認証処理が必要になります。

HTTPリクエストの認証のためのお手軽な方法として、AuthorizationヘッダにAPIキーを入れてリクエストを飛ばす方法がありますが、一般的なWebフロントエンドでこの方法を取り入れるのはセキュリティ的に危険です。ブラウザからの通信内容はユーザーに筒抜けのため、どの通信にどのキーを使用しているかがユーザーに全てバレてしまいます。そのため、フロントエンドとAPIの間に中継サーバーを挟み、APIキーは中継サーバーで管理するというような、各種シークレットをユーザーから隠蔽する仕組みが必要となってきます。

しかし、中継サーバー環境を用意するのは手間がかかり、面倒です。

実は、Zendeskアプリの実行環境には、簡単に中継サーバーを利用できる機能が用意されています。今回は、その方法について解説していきます。

Zendeskアプリの特殊な実行環境

Zendeskアプリは、一般的なWebフロントエンドアプリ同様HTML/CSS/JSコードで動いています。しかし、実行環境については特殊です。一般的なWebフロントエンドのように単体で実行できる仕組みは用意されておらず、必ず本家Zendesk操作画面に用意されている

<

iframe> タグの中で実行させるようになっています。

この実行環境のおかげで、Zendeskアプリは本家Zendeskサーバーの様々な機能に手軽にアクセスできるようになっています。今回紹介する機能についても、その一つです。

Secure Settings機能

Zendeskアプリ開発のベストプラクティスとして、HTTPリクエストを行う際はZAF(Zendesk Apps Framework)のrequest()メソッドを使うことが推奨されています。このメソッドを使うことで、通常のHTTPリクエストと違いZendeskの用意しているProxyサーバーを経由してリクエストを送信することができます。これにより、CORS関連のエラーを回避したり、Cookieの認証情報を利用してZendesk APIの認証処理を簡略化したり、今回取り上げているシークレット情報を隠蔽してHTTPリクエストを行うSecure Settings機能が使用可能となります。

Secure Settingsを利用するには、以下のような設定が必要です。以下の設定例は、実際に私がZendeskをSendgridと連携させるアプリの開発で使用している設定を引用しています。

  1. manifest.jsonで設定を有効化

    使用したいシークレットの情報をmanifest.jsonに記載します。secureプロパティをtrueにすることで、アプリの利用者がパラメーターの実際の値を見られなくなります。

"parameters": [
    {
      "name": "sendgridApiKey",
      "type": "text",
      "secure": true
    }
  ]
  1. manifest.jsonで使用するAPIエンドポイントのURL情報を記載

    アクセスしたいAPIエドポイントのURLをdomainWhitelistに登録することで、request()メソッドがそのURLにアクセスできるようになります。

    "domainWhitelist": [
        "https://api.sendgrid.com"
      ],
  2. request()メソッドに渡すoption内で、Secure Settingsをどのように使用するか指定

    以下のようにsecureにtrueをつけ、ユーザーから隠したいパラメーターを使用する箇所に{{setting.apiKey}}という形で指定します。この時のパラメーター名は、1.でmanifest.jsonに記載した名前に合わせる必要があります。

const options = {
        url: "https://api.sendgrid.com/v3/mail/send",
    type: "POST",
    headers: {
      Authorization: "Bearer {{setting.sendgridApiKey}}",
    },
    contentType: "application/json",
    data: //省略,
    secure: true,
};

client.request(options).then((response) => {
  console.log(response);
});
  1. zcli apps:createによるデプロイ時に実際の値を入力

    デプロイ完了時にmanifest.jsonで定義した各パラメーターについて、実際に使用する値の入力が求められます。ここで入力した値が、request()のoptionで指定した箇所で使用されます。

動作の実態

アプリの実行時、request()でどのようにHTTPリクエストが実行されるのかを見ていきます。

以下の例は、Zendeskアプリから送信されたSendGrid APIへのリクエストをGoogle ChromeのDevToolsで確認したものです。

Request URLとして、zendesk.comのproxyサーバーが指定されています。一番右のパスにSendGrid APIのURL情報が入っています。

SendGrid APIへはAuthorizationヘッダにAPIキーを付けてリクエストを行うようコードを書きましたが、その情報はDevToolsでは見られないようになっています。恐らく、デプロイの際に入力したパラメーターの値はZendeskのサーバーに保管され、request()の際にそれを付与したHTTPリクエストを改めてProxyサーバーから送信しているのでしょう。

注意点: Secure Settingsは本番稼働時しか利用できない

簡単に安全なリクエストを行える便利な機能ですが、デバッグ時等でzcli apps:serverでアプリを実行している際は、Secure Settings機能は使用できないという制限があります。

zcli apps:create等で本番環境にデプロイして実行している時のみ、使用することができます。

まとめ

ZendeskアプリでAPIキー等のシークレットを扱う方法について書きました。

外部APIとの連携は便利ではありますが、そのための認証は適切な方法で行わなければAPIの不正利用につながってしまうため、今回紹介した方法等を活用し、安全な利用を心がけていきたいと思います。