Istio環境下で、cookieデータをもとにアクセス制限を設定する
はじめに
株式会社イエソドでインフラ管理を担当しています@Omasumasuです。
Istio は Envoy の機能を利用して、アクセス制限をかけることができます。
設定方法については公式ドキュメントに詳しく記載されているので確認してみてください。
Envoy を使用しているということは、Envoy の機能をフル活用してアクセス制限の条件を設定することが可能です。
今回はそれを利用して cookie データをもとにアクセス制限をかける設定を紹介します。
Istio と envoy のバージョンにはズレがあるので誤った設定を避けるためにも、まずは Istio が動作している環境の envoy proxy のバージョンを確認してから envoy のドキュメントを読むようにしましょう。
環境
Istio 1.13.2
envoy 1.21.2-dev
RateLimit.Action.HeaderValueMatch について
RateLimit.Action.HeaderValueMatchとは RateLimitAction のうちの一つであり、これを指定することによって一致する条件を持ったヘッダーがあるかによってアクセス制御を行うことができます。
例として actions に以下のような設定をした場合
header_value_match:
descriptor_value: "api-path"
expect_match: true
headers:
- name: ":path"
prefix_match: "/api/"
リクエストのパスの先頭が/api/
であるリクエストが来た際に、指定した descriptor_key(デフォルトは header_match)と descriptor_value を Ratelimit service に投げます。
これを利用すれば、cookie の値によってアクセス制御をかけることは可能ですが cookie 内の情報を正規表現一つで表現するのは管理が複雑になり現実的ではありません。
Dynamic Metadata について
Dynamic Metadataは動的なメタデータで、必要な情報を様々な filter においてリクエストやレスポンスに付与することができるものです。
記録されたメタデータはアクセスログに出力することができたり、他の filter によって取り出して利用したりすることも可能です。
Header-To-Metadata Filter について
Header-To-Metadata Filterはヘッダーの値を取り出し、Dynamic Metadata として情報を付与することができる http_filters の一種です。
これを指定することによって cookie が持つ情報を個別に metadata として付与することができます。
以下の例はリクエストに対して、x-user という cookie が存在したら envoy.lb という namespace に user という key で Dynamic Metadata を記録するという filter です。
name: envoy.header_metadata
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config
request_rules:
- cookie: x-user
on_header_present:
metadata_namespace: envoy.lb
key: user
type: STRING
remove: false
Dynamic metadata が正しく記録されているか確認をしたければIstio のアクセスログフォーマットを修正して出力して確認すると良いです。
RateLimit.Action.MetaData について
RateLimit.Action.MetaDataは RateLimitAction のうちの一つであり、これを指定することによって一致するメタデータを Ratelimit service に指定した key で送ることが可能です。
以下の例は user という Dynamic Metadata を user という descriptor_key で Ratelimit service へデータを転送するためのアクションです。
metadata:
metadata_key:
key: cookie
path:
- key: user
descriptor_key: user
source: "DYNAMIC"
組み合わせてアクセス制限をかける
ここまで紹介したものを組み合わせることによって Cookie にのっている情報を利用してアクセス制限をかけることができます。
以下の例では x-user というユニークなユーザー識別子 cookie を利用して 1 ユーザーあたりごとのアクセス制限を設定します。
まずは、Header-To-Metadata Filter をEnvoyFilter
リソースを使って GATEWAY に対して http_filters を追加してあげます。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: header-to-meta-filter
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.header_to_metadata
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config
request_rules:
- cookie: x-user
on_header_present:
metadata_namespace: cookie
key: user
type: STRING
remove: false
次に RateLimit.Actions をEnvoyFilter
リソースを使って VIRTUAL_HOST に対して rate limit action を設定します。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: filter-ratelimit-svc
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: VIRTUAL_HOST
match:
context: GATEWAY
routeConfiguration:
vhost:
name: "XXXX"
route:
action: ANY
patch:
operation: MERGE
value:
rate_limits:
- actions:
- metadata:
metadata_key:
key: cookie,
path:
- key: user
descriptor_key: user,
source: "DYNAMIC"
これによって cookie 内の x-user の情報が descriptor_key: user
として Ratelimit service に送られるようになります。
あとは Ratelimit service の ConfigMap を設定することによってアクセス制限が動作するようになります。
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
namespace: rate-limit
data:
config.yaml: |
domain: ratelimit
descriptors:
- key: USERID
rate_limit:
unit: minute
requests_per_unit: 100
この設定によって cookie 内のユーザ識別子データ x-user ごとに 1 分間 100 回までのリクエストしか受け付けないように設定ができます。
おわりに
cookie のデータを利用することでアクセス制限条件に柔軟性を持たせることができます。
今回の例では一つの cookie のみを使用して設定をしていますが、複数の cookie や cookie と別情報を組み合わせてアクセス制限を設定することも可能です。
株式会社イエソドはエンジニアを募集しています
Discussion