Istioによるマイクロサービスセキュリティの強化

こんにちは!私の名前はイリヤです。開発チームでDevOpsエンジニアとして働いています。私たちは積極的にマイクロサービスアプローチを使用しており、私たちの仕事の詳細により、サービス間通信のセキュリティは私たちにとって重要です。この記事では、Istioがどのように機能するかを説明し、そのセキュリティ機能の使用方法を例を挙げて説明します。これが問題解決に役立つことを願っています。読書を楽しむ!







サービスネットワークとは何ですか?



サービスメッシュ(この場合はIstio)は、サービス間通信を管理および構成するために必要なすべてのもの(ルーティング、認証、承認、トレース、アクセス制御など)のバインディングです。また、これらの関数をサービスコードに直接実装するオープンソースライブラリは多数ありますが、Istioを使用すると、サービス自体に何も追加しなくても同じことができます。



部品 



istio 1.6向けに書かれた記事


変更について
Istio , . , , - , , . , , Istio 1.4   v1beta1 , Istio RBAC. 1.5 , Pilot, Galley Citadel istiod. - . .



Istioは論理的にデータプレーンとコントロールプレーンに分かれています。

データプレーンは、サイドカーの形でポッドに追加されたプロキシサーバー(Envoy)のコレクションです。これらのプロキシは、マイクロサービス間のすべてのネットワーク通信を提供および制御し、コントロールプレーンから構成されます。



管理プレーン(istiod)は、証明書のサービス検出、構成、および管理を提供します。 IstioオブジェクトをEnvoyフレンドリーな構成に変換し、データプレーンに配布します。







Istioサービスメッシュコンポーネント



手動で、またはIstioがインストール中に追加するMutating Admission Webhookを使用して自動追加を設定することにより、アプリケーションポッドに特使を追加できます。これを行うには、必要な名前空間にistio-injection = enabledタグを配置します。



envoyを使用するプロキシサイドカーに加えて、Istioは特別なinitコンテナーをポッドに追加します。これにより、戦闘トラフィックがenvoyを使用するコンテナーにリダイレクトされます。しかし、これはどのように達成されますか?この場合、魔法はありません。これは、ポッドのネットワーク名前空間に追加のiptablesルールを設定することで実装されます。



リソース消費について
, 100 Istio ~2-3 , envoy 40 , CPU 5%-7% pod.



実際にサイドカーがコンテナーからの着信トラフィックと発信トラフィックをキャプチャする方法を見てみましょう。これを行うには、Istioによってサイドカーが追加されたポッドのネットワークスペースをさらに詳しく見てみましょう。 



デモスタンド
Kubernetes Istio. 

Kubernetes minikube:



Linux:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/

minikube start --driver=<driver_name> // --driver=none        .




MacOS:
brew install minikube
minikube start --driver=<driver_name>






Istio demo :



curl -L https://istio.io/downloadIstio | sh -
cd istio-1.6.3
export PATH=$PWD/bin:$PATH
istioctl install --set profile=demo


: productpage details. Istio .



kubectl label namespace default istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml








productpageアプリケーションのコンテナのリストを見てみましょう:



kubectl -n default get pods productpage-v1-7df7cb7f86-ntwzz -o jsonpath="{.spec['containers','initContainers'][*].name}"
productpage 
istio-proxy 
istio-init


製品ページ自体に加えて、サイドカーistio-proxy(同じ特使)とinitコンテナーistio-initがポッドで機能します。



nsenterユーティリティを使用して、ポッドスペースで構成されたiptablesルールを確認できます。これを行うには、コンテナープロセスのpidを見つける必要があります。



docker inspect k8s_productpage --format '{{ .State.Pid }}'
16286


これで、このコンテナーに設定されたiptablesルールを確認できます。







ほぼすべての着信および発信トラフィックが傍受され、使者がすでに待機しているポートにリダイレクトされていることがわかります。 



相互トラフィック暗号化を有効にする



PolicyおよびMeshPolicyオブジェクトは、istio 1.6から削除されました。代わりに、PeerAuthenticationオブジェクトの使用を提案しています。


Istioでは、コンテナー間のすべてのトラフィックを暗号化できます。アプリケーション自体は、tlsを介して通信していることさえわかりません。これは、クライアント証明書がサイドカープロキシに既にマウントされているため、マニフェストが1つしかないIstio自身ですぐに実行できます。 



アルゴリズムは次のとおりです。 



  1. クライアント側およびサーバー側の特使プロキシは、リクエストを送信する前に相互に認証します。

  2. チェックが成功すると、クライアントプロキシはトラフィックを暗号化してサーバープロキシに送信します。

  3. プロキシサーバー側はトラフィックを復号化し、ローカルで実際の宛先サービスにリダイレクトします。



さまざまなレベルでmTLSを有効にできます。



  • ネットワーク全体のレベルで。

  • 名前空間レベル;

  • 特定のポッドのレベル。 



動作モード:



  • PERMISSIVE:暗号化されたトラフィックとプレーンテキストのトラフィックの両方が許可されます。

  • STRICT:TLSのみが許可されます。

  • DISABLE:プレーンテキストのみが許可されます。



TLSなしでカールを使用してみましょうproductpageポッドからのアクセスの詳細サービスを有効にし、詳細については、tcpdumpを思い付くものを参照してくださいすることは:



リクエスト:







トラフィックをダンプ:







すべてのボディとヘッダは平文で完全に読みやすいです。



tlsをオンにしましょう。これを行うには、ポッドを使用して名前空間にPeerAuthenticationタイプのオブジェクトを作成します。



apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT


レッツは再び詳細に製品ページからの要求を実行し、私たちが何を得るを参照してください。







トラフィックが暗号化されています



ログインする



ClusterRbacConfig、ServiceRole、ServiceRoleBindingオブジェクトは、新しい承認ポリシーの実装とともに削除されました。代わりにAuthorizationPolicyオブジェクトを使用することをお勧めします。


Istioは承認ポリシーを使用して、1つのアプリケーションから別のアプリケーションへのアクセスを構成します。さらに、純粋なKubernetesネットワークポリシーとは異なり、これはL7レベルで機能します。たとえば、httpトラフィックの場合、リクエストのメソッドとパスを細かく制御できます。



前の例で見たように、デフォルトでは、クラスター全体のすべてのポッドにアクセスできます。



次のyamlファイルを使用して、デフォルトの名前空間のすべてのアクティビティを無効にします。



apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  {}


そして、詳細サービスにアクセスしてみましょう:



curl details:9080
RBAC: access denied


すばらしい、今私たちの要求は失敗しています。



次に、GETリクエストのみが通過し、/詳細パスに沿ってのみ通過し、他のすべてのリクエストが拒否されるようにアクセスを設定してみましょう。これにはいくつかのオプションがあります。



  • 特定のヘッダーが渡される要求を渡すように構成できます。

  • アプリケーションのサービスアカウント。

  • 発信IPアドレス。

  • 発信ネームスペース。

  • JWTトークンのクレームによると。



最も簡単に維持できるのは、アプリケーションのサービスアカウントへのアクセスを構成することです。bookinfoデモアプリケーションには、サービスアカウントがすでに作成およびマウントされているため、事前構成は必要ありません。



サービスアカウントに基づく承認ポリシーを使用するには、TLS相互認証を有効にする必要があります。


新しいアクセスポリシーの設定:



apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "details-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: details
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
    to:
    - operation:
        methods: ["GET"]
        paths: ["/details/*"]


そしてもう一度手を差し伸べてみてください:



root@productpage-v1-6b64c44d7c-2fpkc:/# curl details:9080/details/0
{"id":0,"author":"William Shakespeare","year":1595,"type":"paperback","pages":200,"publisher":"PublisherA","language":"English","ISBN-10":"1234567890","ISBN-13":"123-1234567890"}


すべてが機能しています。他の方法と方法を試してみましょう:



root@productpage-v1-6b64c44d7c-2fpkc:/# curl -XPOST details:9080/details/0
RBAC: access denied
root@productpage-v1-6b64c44d7c-2fpkc:/# 
root@productpage-v1-6b64c44d7c-2fpkc:/# curl -XGET details:9080/ping
RBAC: access denied


結論



結論として、検討される機会はIstioが実行できることのほんの一部にすぎないことに注意します。すぐに使用可能な状態で、サービス間トラフィックの暗号化と承認を受け取り、構成しました。ただし、追加のコンポーネントを追加し、その結果、リソースの消費も増加します。 



ありがとうございます!



All Articles