落とし穴に立て札を立てるが如く

ハマりどころの解決が少しでも早くなることを願って書いていきます

Emissary-Ingressで疑似的にIPを条件にルーティングを行う

こちらの記事はcloud.config tech blogにもマルチポストします。

はじめに

Emissary-IngressKubernetesで動作するオープンソースAPI Gatewayの仕組みの実装です。
CNCFのプロジェクトとしても登録されていて、2021年には成熟度としてIncubatingの認定を受けたみたいですね。
これを用いると様々な条件でリクエストのルーティングが行えるのですが、API Gatewayで行いたいこととしてIP制限があると思います。
特に、特定のパスにのみIP制限を設けたい、でもそれを行えるレイヤーがAPI Gatewayの前にも後にもない・・・なんてことありませんか?
なければいいのですが。可能であればWAFなどのAPI Gatewayより手前のレイヤーで行うに越したことはありません。
ただ、不幸にもそのようなパターンにぶち当たった場合には条件さえ合えばこのような手段が取れるよという解決パターンを紹介します。

概要

Emissary-Ingressには様々な条件でリクエストのルーティングができるのですが、リクエスト元IPを条件にしてルーティングを行うことは直接行うことはできません。
しかし、インターネットからのアクセスに対してKubernetesより手前にロードバランサーなどのレイヤーが挟まっていて、そこでアクセス元IPをリクエストヘッダーに追記してくれている場合、Emissary-Ingressでヘッダーを条件にルーティングすることで疑似的にIP制限を行うことができます。
Emissary-Ingressはヘッダーを条件にルーティングを行う機能があるので、こちらを利用します。
https://www.getambassador.io/docs/emissary/latest/topics/using/headers/headers

前提

  • Emissary-IngressKubernetes上で動作している
  • インターネットからKubernetesクラスターまでの通信経路上にヘッダーにアクセス元IPを付与するハードウェアがあること

実装方法

例として、X-Forwarded-Forヘッダーにリクエスト元IPが追加されている場合、以下のようなMappingリソースを作成することで同じパスへのリクエストに対するリクエストが特定IPからのものの場合はsvc-route-1サービスにルーティングされます。
precedenceパラメータは判断の優先順位を示しています。値が大きいほど先に判断され、最初に合致した条件でルーティングされます。
regex_headersパラメータではルーティングの条件にリクエストのヘッダーを指定します。
例えば、X-Forwarded-Forヘッダーにアクセス元のクライアントIP、通信経路上のロードバランサー等のIPが追加されていく場合X-Forwarded-Forの一番最初のIPはクライアントIPになります。
これを正規表現で最初のIPだけ条件とすることでリクエスト元のIPでルーティングできます。
実際に使用する場合は***の部分を適切なIPに書き換えてご利用ください。

apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
  name: sample-mapping-1
spec:
  precedence: 100
  hostname: "*"
  service: svc-route-1
  prefix: /sample/
  regex_headers:
    X-Forwarded-For: '^(***\.***\.***\.***|***\.***\.***\.***).*$'
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
  name: sample-mapping-2
spec:
  precedence: 50 # 特定IP以外の場合、アクセス禁止のページなどを表示する用
  hostname: "*"
  service: svc-sample-2
  prefix: /sample/

おわりに

Emissary-Ingressは既存の機能としてはIPを条件にリクエストのルーティングを行うことができないのですが、周辺のハードウェアの条件によってはヘッダーを条件にルーティングする機能を用いて疑似的にIPを条件にルーティングできます。
お手元のアーキテクチャと相談して、可能そうであればご利用ください。

参考