🎃
istioを使って特定のエンドポイントにapi-key認証を組み込む
構成
- EKS 1.25
- istio 1.17
そもそも
- 認証されていないアプリケーションを公開することになる場合、なにがしかの認証をどこかで仕込む必要がある
- AWS環境にデプロイしているので、ずっとALBでできるものだと思っていたけどできないということが分かり、せっかくなのでKubernetesの方でやってしまおうというのでそうなった
- WAF入れていればそれで事足りるだろうし、Lambdaに飛ばすなどやり方はいろいろあるとは思う
- ちなみに、kubectl port-forwardしたら、api-keyがなくても通過した
- Pod直接、Service経由両方
- なので、ingressで試した
手順
インストール
リファレンスに従うと、コマンドラインツールをインストールして、それを使ってクラスタに展開して。ということみたいです。
コマンドライン
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.17.2
export PATH="$PATH:/home/yuta/istio-1.17.2/bin"
bashrcなどに追加してあげるといい
export PATH="$PATH:/home/yuta/istio-1.17.2/bin"
やってみる
リソースインストール
istioctl install --set profile=demo -y
タグ付け
指定したNamespaceにタグ付けをします。
そうすることで、このNamespace上で起動されるPodにサイドカーとして、envoyコンテナが注入されます。
このEnvoyコンテナは、ネットワーク的にサービス用コンテナに割り込む形でProxyとして配置されます。
kubectl label namespace httpbin istio-injection=enabled
サンプルアプリ起動
サンプルとして、簡単なAPIサーバhttpbinを起動するだけのもの
kubectl create ns httpbin
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: httpbin
spec:
selector:
app: httpbin
ports:
- protocol: TCP
port: 18080
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin-ingress
namespace: httpbin
annotations:
kubernetes.io/ingress.class: "alb"
alb.ingress.kubernetes.io/scheme: "internet-facing"
alb.ingress.kubernetes.io/target-type: "ip"
external-dns.alpha.kubernetes.io/hostname: httpbin.dev.vamemic.link
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:01111111111111:certificate/0a214c1e-7526-492b-9f4e-111111111111111
spec:
rules:
- host: httpbin.dev.vamdemic.link
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 18080
tls:
- hosts:
- httpbin.dev.vamdemic.link
見れること確認
# curl https://httpbin.dev.vamdemic.link/get -I
HTTP/2 200
date: Sun, 23 Apr 2023 01:13:42 GMT
content-type: application/json
content-length: 436
server: istio-envoy
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 2
x-envoy-decorator-operation: httpbin.httpbin.svc.cluster.local:18080/*
EnvoyFilterをインストール
envoy.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: x-api-key-filter
namespace: httpbin
spec:
workloadSelector:
labels:
app: httpbin
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle)
local api_key = request_handle:headers():get("x-api-key")
if api_key ~= "your_api_key" then
request_handle:respond({[":status"] = "403"}, "Invalid x-api-key")
end
end
ここで、api-keyの検証をしている
function envoy_on_request(request_handle)
local api_key = request_handle:headers():get("x-api-key")
if api_key ~= "your_api_key" then
request_handle:respond({[":status"] = "403"}, "Invalid x-api-key")
end
end
kubectl apply -f envoy.yaml
動作チェック
403で返ってくる
curl https://httpbin.dev.vamdemic.link/get
Invalid x-api-key
api-keyを指定してリクエストすると、無事見れるはず。
curl --header 'Accept: application/json' --header 'X-API-KEY:your_api_key' https://httpbin.dev.vamdemic.link/get
参考
Discussion