Amazon Web Services ブログ

Amazon VPC Lattice と Amazon EKS における AWS IAM 認証の実装

イントロダクション

Amazon VPC Lattice は、AWS ネットワークインフラストラクチャに直接組み込まれた、フルマネージドなアプリケーションネットワーキングサービスです。複数のアカウント、複数の仮想プライベートクラウド (VPC) にまたがる全てのサービスの接続、セキュア化、監視に使用できます。

Amazon Elastic Kubernetes Service (Amazon EKS) では、Kubernetes Gateway API の実装である AWS Gateway API コントローラーを通じて、Amazon VPC Lattice を使用できます。Amazon EKS のお客様は、Amazon VPC Lattice を用いることで、シンプルかつ一貫性のある方法で、標準的な Kubernetes のセマンティクスによりクラスターをまたいだ接続を設定できます。

一方で、特定のお客様ではアプリケーションレイヤーのセキュリティを強化したいという要望がありました。Amazon VPC Lattice のデザインはセキュアバイデフォルトです。これは、どのサービスを共有したいのか、どの VPC にアクセスを提供したいのかを、明確にする必要があるためです。

Amazon VPC Lattice は 3 レイヤーのフレームワークを提供しており、ネットワークの複数のレイヤーで多層防御戦略を実装できます。これらのレイヤーには、サービスネットワークと VPC の関連付け、セキュリティグループ、ネットワークアクセスコントロールリスト (ACL)、AWS Identity and Access Management (AWS IAM) 認証ポリシーが含まれ、Amazon VPC Lattice を構成することでセキュリティとコンプライアンスの目標を達成することができます。

VPC 内のセキュリティグループのサービスネットワークへの関連付けと認証ポリシーは、どちらもオプションです。セキュリティグループを設定せずに、サービスネットワークを VPC に関連付けることができます。また、認証タイプを NONE に設定して、認証ポリシーを使用しないこともできます。

本記事では、3 つ目のレイヤー、すなわちサービスネットワークと各々のサービスに適用できる、VPC Lattice の認証ポリシーに焦点を当てます。通常、サービスネットワークの認証ポリシーはネットワーク管理者あるいはクラウド管理者によって運用され、粗い粒度での認証を実装します。例えば、AWS Organizations の指定した組織からの認証済みリクエストのみ許可します。一方、サービスの認証ポリシーでは、サービスのオーナーはネットワーク管理者やクラウド管理者がサービスネットワークのレベルで適用した粗い粒度での認証ルールよりも制限の厳しい、きめ細やかな制御を設定できます。認証ポリシーを使用することで、お客様はアプリケーションのコードを変更することなく、誰が、どのサービスに対して、どのアクションを実行できるかを定義することができます。

我々の実装では、以下の方法を示します。

  • Amazon VPC Lattice サービスネットワークと Amazon EKS を構築し、Amazon VPC Lattice サービスの認証ポリシーを有効にします。
  • Amazon EKS と Amazon VPC Lattice でのサイドカーパターンと Init コンテナパターンを用いて、サービスの呼び出し元が AWS IAM 認証で Amazon VPC Lattice サービスに対しての HTTP リクエストの生成を自動的におこなえるようにするソリューションを構築します。呼び出し元のアプリケーションのソースコードの変更は必要ありません。
  • サービスの呼び出し元が Amazon VPC Lattice サービスネットワーク内の複数のサービスに接続できることを確認します。

ソリューション概要

Amazon VPC Lattice は AWS IAM と統合され、お客様独自のサービス間通信のために、現在 AWS サービスとやり取りする時に慣れ親しんでいるのと同様の認証・認可の機能を提供します。

サービスのアクセス制御を設定するために、アクセスポリシーを使用できます。アクセスポリシーは、サービスネットワークと個々のサービスに関連付けることができる AWS IAM リソースポリシーです。アクセスポリシーでは、PARC (Principal、Action、Resource、Condition) モデルを使用して、サービスのコンテキスト固有のアクセス制御を適用できます。例えば、所有するサービスに対してアクセス可能なサービスを定義するために、アクセスポリシーを使用できます。

Amazon VPC Lattice はクライアント認証に AWS Signature Version 4 (SigV4) を使用します。Amazon VPC Lattice のサービスで認証ポリシーを有効化した後に、署名付き Authorization ヘッダー、x-amz-content-sha256x-amz-datex-amz-security-token が HTTP リクエストに含まれるよう、サービスを呼び出す側を変更する必要があります。AWS SigV4 の詳細はこちらを参照してください。

Amazon VPC Lattice サービスへのリクエストに署名するために、お客様には以下の選択肢があります。

  • AWS SDK を用いて、対応するプログラミング言語でリクエストに署名します。このソリューションはパフォーマンスが最適化されますが、アプリケーション開発者によるコードの変更を必要とします。実装については Amazon VPC Lattice のドキュメントを参照してください。
  • AWS SIGv4 プロキシアドミッションコントローラーを活用し、AWS SIGv4 プロキシを用いて HTTP リクエストをフォワードし、AWS Sigv4 ヘッダーを追加します。詳細については、こちらのを参照してください。しかし、上記のソリューションには 1 つの制限があります。AWS SIGv4 プロキシアドミッションコントローラーを使用する場合、単一のホストしかサポートされません。サンプルのマニフェストでは、フロントエンドのコンテナは localhost:8005 にリクエストをしていて、Host ヘッダーは sidecar.aws.signing-proxy/host Annotations で静的に定義された datastore-lambda.sarathy.io に置き換えられていることがわかります。言い換えると、呼び出し元のサービスは単一の Amazon VPC Lattice サービスにのみ接続できます。クライアントが複数の Amazon VPC Lattice サービスに接続する場合に、課題となります。

この記事では、完全に透過的に複数の Amazon VPC Lattice サービスに対する接続をサポートする、最適化されたソリューションを紹介します。

はじめに、Kubernetes の Pod に Init コンテナとサイドカーコンテナを導入します。

  • Init コンテナ:iptables を実行し、ポート 8080 をリッスンする AWS SigV4 プロキシから Amazon VPC Lattice サービスへのトラフィックをインターセプトします。
  • SigV4 プロキシ:--name vpc-lattice-svcs, --unsigned-payload フラグとロギングのオプションを含む args を指定して実行します。プロキシコンテナは AWS IAM roles for service accounts (IRSA) によって取得された認証情報を使用して、自動的にリクエストに署名します。

次に、Init コンテナとサイドカーコンテナを自動的に注入します。開発チームが既存の Kubernetes マニフェストに変更を加えないようにするためです。ポリシーエンジンとして Kyverno を使用します。Kyverno は Kubernetes のために設計されており、Kubernetes クラスター内で Dynamic Admission Controller として動作します。この場合、Kyverno は Kubernetes API サーバーから Mutating Admission Webhook の HTTP コールバックを受け取り、マッチするポリシーを適用して、Admission Policy を強制する結果を返します。言い換えると、Kyverno は Init コンテナとサイドカーコンテナをコーディングを必須とせずに自動的に注入することができます。

ウォークスルー

Amazon EKS における Amazon VPC Lattice と認証ポリシー

前提条件

  • 管理者権限を持つ AWS アカウント
  • AWS Command Line Interface (AWS CLI)、kubectleksctlGit のインストール

Amazon EKS クラスターと Amazon VPC Lattice サービスの準備

ソリューションをテストするための環境を準備する必要があります。

サンプル httpbin アプリケーションを Amazon VPC Lattice サービスとしてデプロイする

以下のコマンドを使用して、httpbin を Amazon VPC Lattice サービスとしてデプロイします。

git clone https://github.com/aws/aws-application-networking-k8s.git
cd aws-application-networking-k8s/examples
## Create the GatewayClass, Gateway, HTTPRoute, Service and Deployment objects
kubectl apply -f gatewayclass.yaml
kubectl apply -f my-hotel-gateway.yaml
kubectl apply -f httpbin.yaml
kubectl apply -f httpbin-route.yaml

## Create another VPC Lattice Service (HTTPRoute), Service and Deployment object 
cat << EOF > another-httpbin.yaml apiVersion: apps/v1 kind: Deployment metadata: name: another-httpbin labels: app: another-httpbin spec: replicas: 1 selector: matchLabels: app: another-httpbin template: metadata: labels: app: another-httpbin spec: containers: - name: httpbin image: mccutchen/go-httpbin --- apiVersion: v1 kind: Service metadata: name: another-httpbin spec: selector: app: another-httpbin ports: - protocol: TCP port: 80 targetPort: 8080 EOF

cat << EOF > another-httpbin-route.yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: another-httpbin spec: parentRefs: - name: my-hotel sectionName: http rules: - backendRefs: - name: another-httpbin kind: Service port: 80 EOF

## Another VPC Lattice Service
kubectl apply -f another-httpbin.yaml
kubectl apply -f another-httpbin-route.yaml
Bash

サービスネットワークの保護

この機能を実証するために、httpbin サービスに認証ポリシーを適用し、認証されたアクセスのみを許可します。ドキュメントを参照することで、粒度の細かいポリシーを定義できます。

  • AWS コンソールの VPC セクションに移動し、VPC Lattice の下の Services、右ペインの httpbin-default サービスを選択します。
  • 次のページで Access タブの Edit access settings を選択します。
  • 表示される Service access 画面で、AWS IAM から Apply policy template > Allow only authenticated access を選択します。次に Save changes を選択します。

ここで、サービスが AWS IAM 認証を必要とし、そうでなければ HTTP 403 Forbidden エラーを返すかを示すテストを実施します。

kubectl run curl --image alpine/curl -ti -- /bin/sh

curl -v http://httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws
*  Trying 169.254.171.32:80...
* Connected to httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws (169.254.171.32) port 80 (#0)
> GET / HTTP/1.1
> Host: httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws
> User-Agent: curl/8.0.1
> Accept: /

< HTTP/1.1 403 Forbidden
< content-length: 253
< content-type: text/plain
< date: Mon, 31 Jul 2023 07:24:10 GMT
< 
* Connection #0 to host httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws left intact
AccessDeniedException: User: anonymous is not authorized to perform: vpc-lattice-svcs:Invoke on resource: arn:aws:vpc-lattice:us-west-2:091550601287:service/svc-09ff9bb5d43b72048/ because no service-based policy allows the vpc-lattice-svcs:Invoke action#
Bash

呼び出し元のアプリケーションのデプロイ

ここで、AWS IAM roles for service accounts (IRSA) を使用するようプロキシを構成し、プロキシがリクエストに署名するために AWS IAM ロールの認証情報を使用できるようにします。アイデンティティベースのポリシーである VPCLatticeServicesInvokeAccess を AWS IAM ロールにアタッチすることで、Amazon VPC Lattice サービスを呼び出す権限をロールに付与できます。

Service Account 用の IAM ロールの作成

export CLUSTER_NAME=my-cluster
export NAMESPACE=default
export SERVICE_ACCOUNT=default

eksctl create iamserviceaccount \
  --cluster=$CLUSTER_NAME \
  --namespace=$NAMESPACE \
  --name=$SERVICE_ACCOUNT \
  --attach-policy-arn=arn:aws:iam::aws:policy/VPCLatticeServicesInvokeAccess \
  --override-existing-serviceaccounts \
  --approve 
Bash

準備が完了したら、プロキシコンテナと一緒にサービスを呼び出すアプリケーションを準備します。プロキシコンテナはポート 8080 をリッスンし、ユーザー ID 101 として実行します。YAML スニペットは以下のとおりです。

      - name: sigv4proxy
        image: public.ecr.aws/aws-observability/aws-sigv4-proxy:latest
        args: [
          "--unsigned-payload",
          "--log-failed-requests",
          "-v", "--log-signing-process",
          "--name", "vpc-lattice-svcs",
          "--region", "us-west-2",
          "--upstream-url-scheme", "http"
        ]
        ports:
        - containerPort: 8080
          name: proxy
          protocol: TCP
        securityContext:
          runAsUser: 101 
YAML

ここでは、メインのアプリケーションからのトラフィックをインターセプトし、iptables ユーテリティを使って Amazon VPC Lattice CIDR 169.254.171.0/24 に接続するトラフィックを EGRESS_PROXY チェーンにルーティングし、ローカルのポート 8080 にリダイレクトしています。プロキシコンテナによってトラフィックが送信される際の無限ループを避けるため、UID が 101 かどうかをチェックすることで識別し、再度リダイレクトされないようにしています。

      initContainers: # IPTables rules are updated in init container
      - image: public.ecr.aws/d2c6w7a3/iptables
        name: iptables-init
        securityContext:
          capabilities:
            add:
            - NET_ADMIN
        command: # Adding --uid-owner 101 here to prevent traffic from envoy proxy itself from being redirected, which prevents an infinite loop
        - /bin/sh
        - -c
        - > iptables -t nat -N EGRESS_PROXY; iptables -t nat -A OUTPUT -p tcp -d 169.254.171.0/24 -j EGRESS_PROXY; iptables -t nat -A EGRESS_PROXY -m owner --uid-owner 101 -j RETURN; iptables -t nat -A EGRESS_PROXY -p tcp -j REDIRECT --to-ports 8080;
YAML

コンテナイメージ public.ecr.aws/d2c6w7a3/iptables は、シンプルに iptables がインストールされた Ubuntu Linux ディストリビューションのベースイメージです。

FROM ubuntu:focal
RUN apt update && apt install -y iptables
Bash

完全な YAML マニフェストは以下のようになります。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-app
  labels:
    app: client-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: client-app
  template:
    metadata:
      labels:
        app: client-app
    spec:
      serviceAccountName: default
      initContainers: # IPTables rules are updated in init container
      - image: public.ecr.aws/d2c6w7a3/iptables
        name: iptables-init
        securityContext:
          capabilities:
            add:
            - NET_ADMIN
        command: # Adding --uid-owner 101 here to prevent traffic from aws-sigv4-proxy proxy itself from being redirected, which prevents an infinite loop
        - /bin/sh
        - -c
        - >
          iptables -t nat -N EGRESS_PROXY;
          iptables -t nat -A OUTPUT -p tcp -d 169.254.171.0/24 -j EGRESS_PROXY;
          iptables -t nat -A EGRESS_PROXY -m owner --uid-owner 101 -j RETURN;
          iptables -t nat -A EGRESS_PROXY -p tcp -j REDIRECT --to-ports 8080;
      containers:
      - name: app
        image: alpine/curl
        command: ["/bin/sh", "-c", "sleep infinity"]
      - name: sigv4proxy
        image: public.ecr.aws/aws-observability/aws-sigv4-proxy:latest
        args: [
          "--unsigned-payload",
          "--log-failed-requests",
          "-v", "--log-signing-process",
          "--name", "vpc-lattice-svcs",
          "--region", "us-west-2",
          "--upstream-url-scheme", "http"
        ]
        ports:
        - containerPort: 8080
          name: proxy
          protocol: TCP
        securityContext:
          runAsUser: 101
Bash

curl を実行することで、/get のレスポンスが表示されます。レスポンスは HTTP 200 OK です。

➜  kubectl get gateway -o yaml | yq '.items[0].status.addresses[].value'
another-httpbin-default-03422a15c25e5fca4.7d67968.vpc-lattice-svcs.us-west-2.on.aws
httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws

➜ VPC_LATTICE_SERVICE_ENDPOINT=http://httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get
➜ kubectl exec -c app -ti deploy/client-app -- curl $VPC_LATTICE_SERVICE_ENDPOINT

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip", 
    "Host": "httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws", 
    "User-Agent": "curl/8.0.1", 
    "X-Amz-Content-Sha256": "UNSIGNED-PAYLOAD", 
    "X-Amzn-Source-Vpc": "vpc-027db8599a32b83e2"
  }, 
  "origin": "192.168.46.245", 
  "url": "http://httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get"
}
Bash

プロキシコンテナのログを確認することで、ヘッダーがプロキシによって追加されたことを確認できます。Authorization ヘッダーと、x-amz-content-sha256x-amz-datex-amz-security-token といったヘッダーがリクエストに追加されています。

➜ kubectl logs deploy/vpc-lattice-client -c sigv4proxy
time="2023-08-07T10:14:59Z" level=debug msg="signed request" region=us-west-2 service=vpc-lattice-svcs
time="2023-08-07T10:14:59Z" level=debug msg="proxying request" request="GET /get HTTP/1.1\r\nHost: httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws\r\nAccept: */*\r\nAuthorization: AWS4-HMAC-SHA256 Credential=ASIARKUGXKBDQVWU6BFX/20230807/us-west-2/vpc-lattice-svcs/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=<redacted>\r\nUser-Agent: curl/8.0.1\r\nX-Amz-Content-Sha256: UNSIGNED-PAYLOAD\r\nX-Amz-Date: 20230807T101459Z\r\nX-Amz-Security-Token: IQoJb3JpZ2luX2VjEMr//////////<redacted>==\r\n\r\n"
Bash

ここでは、VPC_LATTICE_SERVICE_ENDPOINT を 2 つ目のホスト名に置き換えることができます。アプリケーションコードの変更は必要としないので、複数の Amazon VPC Lattice サービスに接続することができます。

VPC_LATTICE_SERVICE_ENDPOINT=http://another-httpbin-default-03422a15c25e5fca4.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get
➜ kubectl exec -c app -ti deploy/client-app -- curl $VPC_LATTICE_SERVICE_ENDPOINT

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip", 
    "Host": "another-httpbin-default-03422a15c25e5fca4.7d67968.vpc-lattice-svcs.us-west-2.on.aws", 
    "User-Agent": "curl/8.0.1", 
    "X-Amz-Content-Sha256": "UNSIGNED-PAYLOAD", 
    "X-Amzn-Source-Vpc": "vpc-027db8599a32b83e2"
  }, 
  "origin": "192.168.32.152", 
  "url": "http://another-httpbin-default-03422a15c25e5fca4.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get"
}
Bash

Kyverno を使って、Init コンテナとサイドカーコンテナを自動で注入する

ここで、Kyverno を活用して、Init コンテナとサイドカーコンテナを自動で注入するようにします。Kyverno がインストールされたクラスターでは、注入するための ClusterPolicy を書くことができます。Deployment オブジェクトに vpc-lattices-svcs.amazonaws.com/agent-injecttrue であるアノテーションが設定されると、Deployment に Init コンテナとサイドカーコンテナが注入されます。

環境変数 AWS_REGION を指定する必要もあります。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: inject-sidecar
  annotations:
    policies.kyverno.io/title: Inject Sidecar Container
spec:
  rules:
  - name: inject-sidecar
    match:
      any:
      - resources:
          kinds:
          - Deployment
    mutate:
      patchStrategicMerge:
        spec:
          template:
            metadata:
              annotations:
                (vpc-lattices-svcs.amazonaws.com/agent-inject): "true"
            spec:
              initContainers: # IPTables rules are updated in init container
              - image: public.ecr.aws/d2c6w7a3/iptables
                name: iptables-init
                securityContext:
                  capabilities:
                    add:
                    - NET_ADMIN
                command: # Adding --uid-owner 101 here to prevent traffic from envoy proxy itself from being redirected, which prevents an infinite loop
                - /bin/sh
                - -c
                - >
                  iptables -t nat -N EGRESS_PROXY;
                  iptables -t nat -A OUTPUT -p tcp -d 169.254.171.0/24 -j EGRESS_PROXY;
                  iptables -t nat -A EGRESS_PROXY -m owner --uid-owner 101 -j RETURN;
                  iptables -t nat -A EGRESS_PROXY -p tcp -j REDIRECT --to-ports 8080;
              containers: 
              - name: sigv4proxy
                env:
                 - name: AWS_REGION
                   value: "us-west-2"
                image: public.ecr.aws/aws-observability/aws-sigv4-proxy:latest
                args: [
                  "--unsigned-payload",
                  "--log-failed-requests",
                  "-v", "--log-signing-process",
                  "--name", "vpc-lattice-svcs",
                  "--region", \$(AWS_REGION),
                  "--upstream-url-scheme", "http"
                ]
                ports:
                - containerPort: 8080
                  name: proxy
                  protocol: TCP
                securityContext:
                  runAsUser: 101
Bash

このアプローチでは、Kubernetes Deployment の YAML に vpc-lattices-svcs.amazonaws.com/agent-inject: "true" を指定すると、Deployment に Init コンテナとサイドカーコンテナが注入されます。

クライアントの YAML は以下です。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vpc-lattice-client
  labels:
    app: vpc-lattice-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vpc-lattice-client
  template:
    metadata:
      labels:
        app: vpc-lattice-client
      annotations:
       vpc-lattices-svcs.amazonaws.com/agent-inject: "true"
    spec:
      serviceAccountName: default
      containers:
      - name: app
        image: alpine:curl
        command: ["/bin/sh", "-c", "sleep infinity"]
Bash

サイドカーは自動的に注入されます。

➜ kubectl describe deploy vpc-lattice-client

Name: vpc-lattice-client
Namespace: default
CreationTimestamp: Thu, 20 Jul 2023 11:01:32 +0800
Labels: app=vpc-lattice-client
Annotations: deployment.kubernetes.io/revision: 1
policies.kyverno.io/last-applied-patches: inject-sidecar.inject-sidecar.kyverno.io: added /spec/template/spec/containers/0
...
Bash

パッチが当たった YAML マニフェストは以下のようになります。

➜ kubectl get deploy vpc-lattice-client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"vpc-lattice-client"},"name":"vpc-lattice-client","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"vpc-lattice-client"}},"template":{"metadata":{"annotations":{"vpc-lattices-svcs.amazonaws.com/agent-inject":"true"},"labels":{"app":"vpc-lattice-client"}},"spec":{"containers":[{"command":["/bin/sh","-c","sleep infinity"],"env":[{"name":"HTTP_PROXY","value":"localhost:8080"}],"image":"nicolaka/netshoot","name":"app"}],"serviceAccountName":"default"}}}}
    policies.kyverno.io/last-applied-patches: |
      inject-sidecar.inject-sidecar.kyverno.io: added /spec/template/spec/containers/0
  creationTimestamp: "2023-07-20T03:01: labels: app: vpc-lattice-client name: vpc-lattice-client namespace: default spec: selector: matchLabels: app: vpc-lattice-client template: metadata: annotations: vpc-lattices-svcs.amazonaws.com/agent-inject: "true"
      creationTimestamp: null
      labels:
        app: vpc-lattice-client
    spec:
      containers:
      - args:
        - --unsigned-payload
        - --log-failed-requests
        - -v
        - --log-signing-process
        - --name
        - vpc-lattice-svcs
        - --region
        - $(AWS_REGION)
        - --upstream-url-scheme
        - http
        env:
        - name: AWS_REGION
          value: us-west-2
        image: public.ecr.aws/aws-observability/aws-sigv4-proxy:latest
        imagePullPolicy: Always
        name: sigv4proxy
        ports:
        - containerPort: 8080
          name: proxy
          protocol: TCP
        resources: {}
        securityContext:
          runAsUser: 101
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      - command:
        - /bin/sh
        - -c
        - sleep infinity
        image: alpine:curl
        imagePullPolicy: Always
        name: app
      initContainers:
      - command:
        - /bin/sh
        - -c
        - |
          iptables -t nat -N EGRESS_PROXY; iptables -t nat -A OUTPUT -p tcp -d 169.254.171.0/24 -j EGRESS_PROXY; iptables -t nat -A EGRESS_PROXY -m owner --uid-owner 101 -j RETURN; iptables -t nat -A EGRESS_PROXY -p tcp -j REDIRECT --to-ports 8080;
        image: public.ecr.aws/d2c6w7a3/iptables
        name: iptables-init
        securityContext:
          capabilities:
            add:
            - NET_ADMIN

  ...
Bash

また、クライアントが Amazon VPC Lattice サービスに正常にアクセスできることも確認できます。

VPC_LATTICE_SERVICE_ENDPOINT=http://httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get
kubectl exec -c app -ti deploy/vpc-lattice-client -- curl $VPC_LATTICE_SERVICE_ENDPOINT

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip", 
    "Host": "httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws", 
    "User-Agent": "curl/8.0.1", 
    "X-Amz-Content-Sha256": "UNSIGNED-PAYLOAD", 
    "X-Amzn-Source-Vpc": "vpc-027db8599a32b83e2"
  }, 
  "origin": "192.168.32.152", 
  "url": "http://httpbin-default-09ff9bb5d43b72048.7d67968.vpc-lattice-svcs.us-west-2.on.aws/get"
}
Bash

クリーンアップ

将来的な課金を避けるため、以下のコマンドを使用して Amazon VPC Lattice リソースと Amazon EKS クラスターを含む、全てのリソースを削除します。

kubectl delete -f httpbin.yaml
kubectl delete -f httpbin-route.yaml
kubectl delete -f another-httpbin.yaml
kubectl delete -f another-httpbin-route.yaml
kubectl delete -f my-hotel-gateway.yaml
kubectl delete -f gatewayclass.yaml

eksctl delete cluster -f $CLUSTER_CONFIG
Bash

まとめ

この記事では、Amazon VPC Lattice に AWS IAM 認証を実装する方法を、以下のようなソリューションを用いて紹介しました。

  • Init コンテナを使って iptables コマンドを実行し、VPC Lattice へのトラフィックをインターセプトする。
  • Kyverno を用いて Init コンテナとサイドカーコンテナを自動的に注入する。
  • 呼び出し元のサービスは、VPC Lattice サービスネットワーク内の IAM 認証で複数のサービスに接続できるようになる。

VPC Lattice をベースにソリューションを構築し、VPC Lattice の IAM 認証を活用してセキュリティ体制を強化したい場合に、本ブログで共有した内容がお役に立てば嬉しいです。Amazon VPC Lattice の詳細については、ドキュメントやその他のブログを参照してください。

翻訳はソリューションアーキテクトの後藤が担当しました。原文はこちらです。