Google Cloudとコンテナの継続的なセキュリティ
本文の内容は、2020年11月17日にMateo Burilloが投稿したブログ(https://sysdig.com/blog/kubernetes-native-network-security/)を元に日本語に翻訳・再構成した内容となっております。
マイクロサービスとKubernetesは、ネットワークセキュリティにに関する考え方を完全に変えました。幸いなことに、Kubernetesネットワークセキュリティポリシー(KNP)は、この問題に正しい抽象度で対処するためのネイティブメカニズムです。
ネットワークポリシーの実装は、開発者と運用者が協力して適切なルールを定義する必要があるため、難しいものです。しかし、最良のアプローチは、Kubernetesネイティブコントロールを使用したネットワークセキュリティのためのゼロトラストフレームワークを採用することです。
SysdigがKubernetesネイティブのネットワーク可視性を提供する最新のSysdig Network Policy機能でこのギャップをどのように埋めているかをご覧ください。また、ネットワークのセグメンテーションを必要とするコンプライアンス要件(NIST、PCIなど)への対応にも役立ちます。
メタデータのエンリッチメントがないKubernetesの通信は意味不明です。
セキュリティやネットワークポリシーについて考え始める前に、まず、マイクロサービスがどのように相互に通信しているかを深く可視化する必要があります。
Kubernetesの世界では、ポッドは短命で、ホスト間を飛び回り、刹那的なIPアドレスを持ち、スケールアップしたりスケールダウンしたりします。これらはすべて素晴らしく、私たちが愛する柔軟性と反応性を与えてくれます。しかし、L3/L4 の物理的な通信層(IP とポートだけで見ると、以下のようになります)を見ると、以下のようになります。
つまり、すべての接続情報を持っているが、正しく集約されておらず、セグメント化されていないということです。さすがに、古典的なファイアウォールのルールを設定しようとしても、うまくいきません。イメージ名、イメージタグ、コンテナ名などの属性に応じて、異なるコンテナをグループ化することはできますが、これは手間がかかり、エラーが発生しやすく、情報はすべて動的で常に変化していることを覚えておいてください。
ネットワーク通信やセキュリティをKubernetesレベルで推論するために必要なメタデータはすでにすべて揃っているのに、なぜ車輪を再発明するのでしょうか?Kubernetes APIには、ネームスペース、サービス、デプロイメントなどに関するすべての最新情報が含まれています。また、それらのエンティティ(KNP)に割り当てられたラベルに基づいてポリシーを作成するツールも提供されています。
開発者チームは運用チームと会い、アプリの1つに究極のネットワークポリシーを作成しました。
1時間の会議の後、開発者はこのようにアプリを定義しました:
そして、これが彼らが考え出したネットワークポリシーです。
通常のメタデータでポリシーを開始します。これがNetworkPolicyです:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: generated-network-policy
namespace: example-java-app
次にネットワークルールです。"example-java-app"が8080番ポートでクライアントアプリからのリクエストを受け付けるように、ingressルールから始めます。
spec: ingress: - from: - namespaceSelector: matchLabels: app: raw chart: raw-0.2.3 heritage: Helm release: namespaces podSelector: matchLabels: app.kubernetes.io/instance: example-java-app app.kubernetes.io/name: example-java-app-jclient ports: - port: 8080
protocol: TCP
次に、アプリがデータベースに接続できるようにするためのegressルール: mongodbとredisです。
egress: - to: - namespaceSelector: matchLabels: app: raw chart: raw-0.2.3 heritage: Helm release: namespaces podSelector: matchLabels: app.kubernetes.io/instance: example-java-app app.kubernetes.io/name: example-java-app-mongo ports: - port: 27017 protocol: TCP - to: - namespaceSelector: matchLabels: app: raw chart: raw-0.2.3 heritage: Helm release: namespaces podSelector: matchLabels: app.kubernetes.io/instance: example-java-app app.kubernetes.io/name: example-java-app-redis ports: - port: 6379
protocol: TCP
最後に、example-java-app-javaappという名前のポッドに適用されることを指定して終わります:
podSelector: matchLabels: app.kubernetes.io/instance: example-java-app app.kubernetes.io/name: example-java-app-javaapp policyTypes: - Ingress
- Egress
うわー、こんなシンプルなアプリにしては長いYAMLですね。通常のアプリのネットワークポリシーは数千行にもなります。
そして、これはKubernetesのネットワークポリシーの最初の注意点です。あなたはそれらを作成するために、まだ別のドメイン固有の言語を学ぶ必要があります。すべての開発者ができるわけではありませんが、それらに喜んでいるわけではありませんし、OPSチームはそれらを作成するためにあなたのアプリについて十分に知っているわけではありません。彼らは一緒に働く必要があります。
このネットワーク ポリシーを本番環境に導入してみましょう!
ポリシーを適用したら、アプリが動かなくなる😱。
そして、これもKubernetesのネットワークポリシーを作成するプロセスの注意点です。トラブルシューティングには複数の関係者が関与する必要があり、プロセスが遅くなります。手作業でネットワークポリシーを作成する際に、いくつかのサービスやよくあるKNPの落とし穴を忘れてしまうことは本当に簡単です。
もちろん、チームが一斉に見つけたわけではありません。数時間に及ぶ試行錯誤でした。Cassandraの依存関係を完全に削除し、以下のようなEgressルールを追加することで解決しました。
外部IPへのトラフィックを許可するルール:
[...] spec: [...] egress: [...] - to: - ipBlock: cidr: 192.229.173.207/32 except: []
[...]
DNS解決のためのトラフィックを許可するルール。
[...] spec: [...] egress: [...] - to: - namespaceSelector: {} ports: - port: 53 protocol: UDP
[...]
そして最終的に、この更新されたポリシーを適用した後、すべてが期待通りに動作しています。そして、私たちのチームは、アプリネットワークが安全に保護されていることを安心しています。
なぜこの処理が人を喜ばせなかったのか、簡単に立ち止まって分析してみましょう。
OK、それはそれらの使用を開始するのは簡単です。あなたがCalicoのように、それらをサポートするCNIをデプロイしたと仮定して、KNPは、Kubernetesのボックスから出てくる。しかし、まだ、彼らは多くの実装の詳細と注意点があります。
それらは、学び、習得するためのもう1つのポリシー言語です。
開発者は通常、アプリケーションが機能レベルで何をすべきかを非常に正確に把握しています。データベースとの通信、外部フィードからのデータの取得などです。しかし、本番クラスターにKNPを適用して管理しているわけではありません。
運用チームは、Kubernetes を利用していますが、アプリケーションが内部でどのように振る舞っているのか、そして適切に機能するために実際に必要なネットワーク接続については、より限定的な可視性を持っています。
現実には、マイクロサービスに最適なネットワークポリシーを生成するためには、両方の利害関係者の意見が必要です。
KNP の学習曲線と、異なるスコープを持つチーム間での情報の行き来は、従来から痛手でした。一部の組織では、非常に広範なポリシー(マイクロサービスが同じネームスペース内にあれば相互に通信可能)に落ち着いていますが、これは何もないよりはマシで、誰もが従うことができるほどシンプルですが、間違いなく最も正確な施行ではありません。
自分のアプリケーションが何をしているかを自分の言語で記述するだけで、誰かがそれを KNP (または将来的に使用する他のポリシー言語) に翻訳してくれるとしたらどうでしょうか?
Sysdig がどのようにして正確なネットワークポリシーを作成するのに役立つのかを見てみましょう。
本日、Sysdigは新しいKubernetesネットワークポリシー機能を発表しました。
Sysdigの新しいKubernetesネットワークポリシー機能を使ってexample-java-app用の正確なポリシーを数分で作成する方法を見てみましょう。
ネットワークポリシーを作成するには、Sysdigのインターフェイス -> ポリシー -> ネットワークセキュリティポリシーにジャンプしてください。
まず、ポリシーを作成するポッドのセットを選択します。最初に、クラスタ、およびアプリが存在するネームスペースから始めます。
次に、ポリシーを適用するポッドの所有者、またはポッドのグループを選択します。ポッドは、Service、Deployment、StatefulSet、DaemonSet、またはJobでグループ化できます。
ここでは、Deploymentの観点からインフラストラクチャーを見てみます。
Sysdigがexample-java-appからネットワーク接続を理解するには、3時間分のデータがあれば十分です。
Sysdigが実際にネットワークデータを収集するのを待つ必要はありません。Sysdigエージェントはしばらくの間、このクラスターにデプロイされているので、Sysdigはアクティビティ監査から既存のデータを使用することができます。
これらのパラメータを選択した直後に、Sysdigは私たちのアプリデプロイのために観測されたネットワークトポロジーマップを表示します。
ここにはいくつかの興味深いキーがあります。
このマップには、現在のすべての通信(コネクターとポート)が表示されています。cassandraデータベースや外部IPのように、最初のアプローチで見逃したものも含まれています。
通信はKubernetesのメタデータレベルで表示されていることに注意してください。クライアントアプリケーションがサービスにリクエストをプッシュし、それがデプロイメントポッドに転送されているのがわかります。
色分けされたセキュリティポリシーを提案しています。未解決のIP、Kubernetesエンティティと照合できないエンティティはデフォルトで除外され、赤で表示されます。
すっきりとしていてシンプルで、必要な関連情報がすべて含まれています。
さて、アプリケーションの知識を持った開発者としては、いじりたくなるような細かい部分がいくつかあります。
これは、インターフェイスのIngressとEgressタブから行います。
Ingress / Egressテーブルは、トポロジー・マップで見つかった情報を拡張して詳細に表示します。
追加情報は、個々の通信を識別するのに役立ちます。例えば、以下のようになります。例えば、"どのプロセスがegress接続を開始しているか?"など。
これらは実行可能です:
信頼できるサービスに属しているため、外部IPを許可するためにIP/マスクの組み合わせを追加しました。
私たちは、その通信を必要としなくなったので、cassandraデプロイメントの行のチェックを外しました。
Sysdigは、私たちのIPがクラスタの外部にあるネットワークに属していることを自動的に検出し、そのようにフラグを立てます。
ネットワーク・トポロジー・マップは自動的に更新され、変更が反映されます:
外部IPへの接続は赤色ではなくなりましたが、cassandraへの接続は赤色になっていることに注意してください。
これでポリシーの見た目が思い通りになったので、Kubernetes Network PolicyのYAMLを生成します。
"Generated Policy"タブをクリックするだけで、その場で生成されます:
これで、このポリシーの成果物をDevOpsチームのための私のアプリケーションと一緒に添付することができるようになりました。
上のワークフローを見ればわかるように、Sysdigは観測されたネットワークの挙動とユーザーの調整を集約して最適なポリシーを生成するのを支援しています。
しかし、実際にこのポリシーを適用しているわけではありません。
それはKubernetesのコントロールプレーンとCNIプラグインに任せています。そして、これにはいくつかの利点があります。
まず、KNPがどのように動作するのかという低レベルの詳細を理解する必要がありませんでした。視覚的なフローを使ってアプリケーションのネットワークの挙動を記述することができれば、Sysdigが翻訳をしてくれます。
トポロジーマップは、サービス/アプリ/ネームスペース/タグをまたいだ全ての通信にネットワークの可視性を提供してくれました。そのため、任意のサービスを含めることを忘れることはありません。
また、ゼロから始める必要はありません。ネットワークポリシーをベースライン化することで、時間を節約できる10%のリフトを実行するだけです。その後、SysdigがYAMLを自動生成します。
Devopsチームとセキュリティチームは、サインオフしてポリシーをチェックするだけで済みます。
Kubernetesのネイティブコントロールを活用し、ポリシーの定義と適用を切り離します。 そのため、邪魔にならず、パフォーマンスへの影響を意味するものではありません。 また、Sysdigへの接続が失われた場合でも、ポリシーは有効であり、ネットワーク通信は維持されます。
最後に、これらのネットワークポリシーはKubernetesのネイティブポリシーなので、Istioや他のサービスメッシュにも拡張することができます。
Kubernetesネットワークのセキュリティ要件に対応するために、Sysdig SecureはSysdig Network Policy機能を実現しました。
この機能を使用すると、以下のことが可能になります:
この機能を今日、確認することができます、無料トライアルを開始してください。