PR

3scaleの基本的な使い方

2019年7月4日(木)
田畑 義之

Step 2. APIのセキュリティを高めよう

デフォルトではAPIキーによるクライアントアプリケーションの認証が有効になっていますが、APIキーは簡単に漏えいするリスクがあり、セキュリティレベルが低いです。エンタープライズ領域で利用できるようなAPIのセキュリティを担保するためには、別の手段を考える必要があります。

ここでは、公開するAPIのセキュリティを高める方法として、以下の2つの方法を紹介します。

  • OpenID Connectインテグレーション
    • サードパーティのアイデンティティプロバイダと連携し、OpenID Connectの仕様に基づいたAPIリクエストの認証を行う
    • OpenID ConnectはOAuth 2.0を拡張した仕様で、API認証フローを定めた仕様のデファクトスタンダード。そのフローの中で認証を司るアイデンティティプロバイダがアクセストークンやリフレッシュトークン、IDトークンを発行する
  • シークレットトークン
    • 3scaleを通るAPIリクエストに秘密のトークンを付与することで、APIリクエストが3scaleを通ったかをAPIバックエンドが判別できるようにする

OpenID Connectインテグレーション

OpenID Connectインテグレーションを試してみましょう。ここではサードパーティのアイデンティティプロバイダとして、Keycloakのバージョン3.4.3を利用します(Keycloakの構築に関しては、OpenStandiaで提供されている公式ドキュメントの日本語版を参照)。

まず、Keycloakを設定します。ここでは3scaleという名前のレルムを準備します。3scaleレルムに、3scale用のクライアントを設定します(図17)。

図17:3scaleクライアントの設定画面

ここで設定する項目を表に示します。

表:3scale用クライアントの設定

設定項目
クライアントID ※ここでは3scale
クライアントプロトコル openid-connect
アクセスタイプ confidential
Standard Flowの有効 オフ
Implicit Flowの有効 オフ
ダイレクトアクセスグラントの有効 オフ
サービスアカウントの有効 オン
付与するサービスアカウントロール realm-managementクライアントのmanage-clientsロール

[Credentials]タブで、作成したクライアントのクライアントシークレットを確認しておきましょう。

続いて、Keycloakとのデータ同期に使用する3scaleのコンポーネントであるZyncを設定します。Zync~ Keycloak間はSSL通信が必要なため、KeycloakのCA証明書をZyncにインポートします。

$ keytool -export -alias server -keystore /opt/keycloak-3.4.3.Final/standalone/configuration/application.keystore -file customCA.crt
$ openssl x509 -in customCA.crt -inform der -out customCA.pem -outform PEM
$ curl https://keycloak-server.oss.example.co.jp:8443/auth/realms/master --cacert customCA.pem
{
  "realm": "master",
  "public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm64KWQJHSK7JwmfVmXtVZ2V2KCA2hl2y9aRSTdazBnBVAfBoBcVvsNIDIuSTzgfKqh/RDgAPun39/BA7FXIn7rnoRHlq9MXWYq3zWzRtDet2nqUux8zBDQeBkvylQB59SC758605wKpTN0YHvt50i8lOTpQBkAeZ8mOKNLMO+GMK9nFlBQdt+FO+pWXYKfwqcr61Yoz5dHWE2BntmNOdyLcfK9UmXB/z3jvoowfRnx6M1EousUscLr4ErfUyZOWjWxt+X8buo3KDeOFbWXYCYoC7tPuGUcCbMv03D610NH1y9gX76h0bzh/UAzqdIGNtS+LoXZZdyxarp32CxIRvwwIDAQAB",
  "token-service": "https://keycloak-server.oss.example.co.jp:8443/auth/realms/master/protocol/openid-connect",
  "account-service": "https://keycloak-server.oss.example.co.jp:8443/auth/realms/master/account",
  "tokens-not-before": 0
}
$ oc exec zync-1-gfq2z cat /etc/pki/tls/cert.pem > zync.pem
$ cat customCA.pem >> zync.pem
$ oc create configmap zync-ca-bundle --from-file=./zync.pem
$ oc set volume dc/zync --add --name=zync-ca-bundle --mount-path /etc/pki/tls/zync/zync.pem --sub-path zync.pem --source='{"configMap":{"name":"zync-ca-bundle","items":[{"key":"zync.pem","path":"zync.pem"}]}}'
$ oc patch dc/zync --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/0/subPath", "value":"zync.pem"}]'
$ oc exec zync-2-zkpmp cat /etc/pki/tls/zync/zync.pem
~~省略:KeycloakのCA証明書が追加されていることを確認します~~
$ oc set env dc/zync SSL_CERT_FILE=/etc/pki/tls/zync/zync.pem

最後に、管理ポータルでOpenID Connectを有効にしましょう。Hello APIのコンフィギュレーション画面から[edit integration settings]を選択し、認証方法をOpenID Connectに変更します(図18)。

図18:Hello APIのコンフィギュレーション設定変更画面

Hello APIのインテグレーション画面で、[AUTHENTICATION SETTINGS]→[OpenID Connect Issuer]の欄に3scale用クライアントのクライアントクレデンシャルとKeycloakのURLを設定します(図19)。図中では、[OpenID Connect Issuer]の欄に“https://3scale:xxx@keycloak-server.oss.example.co.jp:8443/auth/realms/3scale”と指定していますが、”xxx”の部分には、3scale用クライアントのクライアントシークレットを指定します。

図19:Hello APIのインテグレーション画面(認証設定)

認証方法をOpenID Connectに変更すると、Hello APIのクライアントアプリケーションであるtest applicationのAPIクレデンシャルとして、APIキーの代わりにクライアントIDとクライアントシークレットが表示されます(図20)。[Add Random key]を押下し、クライアントシークレットを生成しましょう。

図20:test applicationの概要画面

クライアントシークレットを生成すると、3scaleはKeycloakの”OpenID Connect動的クライアント登録機能”により、動的にKeycloakのクライアントを登録します。Keycloakのクライアント一覧画面でtest application用のクライアントが作成されていることを確認しましょう(図21)。

図21:クライアント一覧画面

以上で設定は完了です。3scaleがサポートする4つのOAuth 2.0フロー(Authorization Code Grant、Resource Owner Password Credentials Grant、Implicit Grant、Client Credentials Grant)のいずれかを用いてアクセストークンを発行し、Hello APIをコールしてみましょう。ここではResource Owner Password Credentials Grantを使います。

$ export token=$(curl -X POST https://keycloak-server.oss.example.co.jp:8443/auth/realms/3scale/protocol/openid-connect/token -d "client_id=17df53c0&client_secret=***&username=tabata&password=***&grant_type=password&scope=openid" | jq -r '.access_token')
$ curl "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
{
  "your_user_key": null,
  "your_request_headers": {
    "Authorization": [
      "Bearer "
    ],
    "Accept": [
      "*/*"
    ],
    "User-Agent": [
      "curl/7.64.1"
    ],
    "X-Forwarded-Host": [
      "hello-3scale-apicast-production.192.168.99.113.nip.io"
    ],
    "X-Forwarded-Proto": [
      "https"
    ],
    "Forwarded": [
      "for=192.168.99.1;host=hello-3scale-apicast-production.192.168.99.113.nip.io;proto=https;proto-version="
    ],
    "X-Forwarded-For": [
      "192.168.99.1"
    ],
    "Host": [
      "api_backend.oss.example.co.jp:18080"
    ],
    "X-Real-IP": [
      "172.17.0.1"
    ],
    "X-3scale-proxy-secret-token": [
      "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969"
    ],
    "X-Forwarded-Port": [
      "443"
    ]
  }
}

Hello APIをコールすることに成功しました。ちなみにアクセストークンを付与しなかったり、無効なアクセストークンを付与したりすると、以下のように403エラーが返ってきます。

$ curl -v "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer invalid_token"
< HTTP/1.1 403 Forbidden
Authentication parameters missing

シークレットトークン

次に、シークレットトークンを試してみます。実はシークレットトークンはデフォルトで有効になっており、前述した確認結果にも、以下のように表示されていました(6~8行目)。

$ curl "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
{
  "your_user_key": null,
  "your_request_headers": {
~~省略~~
    "X-3scale-proxy-secret-token": [
      "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969"
    ],
~~省略~~
  }
}

デフォルトでは、”X-3scale-proxy-secret-token”というヘッダに、” Shared_secret_sent_from_proxy_to_API_backend_”という値が入ります。APIバックエンドで、この値をチェックする処理を作り込むことで、APIバックエンドが直接コールされるといったAPIの意図しない使われ方を防ぐことができます。

シークレットトークンに設定する値は、Hello APIのインテグレーション画面の[AUTHENTICATION SETTINGS]→[Secret Token]から変更できます(図22)。

図22:Hello APIのインテグレーション画面(シークレットトークン)

株式会社 日立製作所
OSSソリューションセンタにて、API管理や認証周りのOSSの開発/サポート/普及活動に従事。3scaleのapicastリポジトリのコントリビュータであり、流量制御ポリシーやスコープチェックポリシーを中心に多数のコードをコミットしている。

連載バックナンバー

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

他にもこの記事が読まれています