Azure Policy を使用して Azure Kubernetes Service (AKS) クラスターをセキュリティで保護する

Azure Policyを使用して、Azure Kubernetes Service (AKS) クラスターに組み込みのセキュリティ ポリシーを適用して適用できます。 Azure Policy は、組織の標準を適用してコンプライアンスを大規模に評価するのに役立ちます。 AKS 用の Azure Policy アドオンをインストールした後、個々のポリシー定義またはイニシアチブ (policysets と呼ばれることもあります) と呼ばれるポリシー定義のグループをクラスターに適用できます。 AKS ポリシーとイニシアティブ定義の完全な一覧については、AKS の組み込み定義Azure Policy参照してください。

この記事では、クラスターにポリシー定義を適用し、割り当てが適用されていることを確認する方法について説明します。

前提条件

開始する前に、次のリソースをインストールして構成する必要があります。

組み込みポリシー定義またはイニシアチブの割り当て

次の手順を使用して、Azure ポータルでポリシー定義またはイニシアティブを適用できます。

  1. Azure ポータルの [ポリシー] というAzure Policy サービスに移動します。
  2. Azure Policy ページの左側のウィンドウで、 [定義] を選択します。
  3. [カテゴリ] で Kubernetes を選択します。
  4. 適用するポリシー定義またはイニシアチブを選択します。 この例では、[Linux ベースのワークロード用の Kubernetes クラスター ポッド セキュリティ ベースライン標準] イニシアチブを選択します。
  5. [割り当て] を選択します。
  6. [スコープ] には、Azure Policy アドオンが有効な AKS クラスターのリソース グループを設定します。
  7. [パラメーター] ページを選択し、ベースライン イニシアチブに違反する新しいデプロイをブロックするために、のauditをdenyに更新します。 評価から除外する名前空間を追加することもできます。 この例では、規定値のままにしておきます。
  8. [確認と作成]>[作成] の順に選択して、ポリシーの割り当てを送信します。

Terraform 構成のディレクトリを作成します。

mkdir aks-use-azure-policy
cd aks-use-azure-policy

Terraform 構成を作成する

main.tf ファイルを作成し、次のテスト済みのサンプル構成をコピーします。 サンプルは、Azure Terraform GitHub リポジトリに保持されます。 構成:

  • Terraform (azurerm) のAzure プロバイダーを構成します。
  • 既存のリソース グループと AKS クラスターの入力変数を定義します。
  • 既存のリソース グループと組み込みのポッド セキュリティ ベースライン イニシアチブを取得します。
  • ポリシー効果を Deny に設定して、イニシアチブをリソース グループに割り当てます。
terraform {
  required_version = ">= 1.6.0"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}
provider "azurerm" {
  features {}
}
variable "resource_group_name" {
  description = "Name of the resource group that contains the existing AKS cluster."
  type = string
}
variable "aks_cluster_name" {
  description = "Name of the existing AKS cluster."
  type = string
}
data "azurerm_resource_group" "aks" {
  name = var.resource_group_name
}
data "azurerm_policy_set_definition" "aks_pod_security_baseline" {
  display_name = "Kubernetes cluster pod security baseline standards for Linux-based workloads"
}
resource "azurerm_resource_group_policy_assignment" "aks_pod_security_baseline" {
  name = "aks-pod-security-baseline"
  display_name = "Kubernetes cluster pod security baseline standards for Linux-based workloads"
  resource_group_id = data.azurerm_resource_group.aks.id
  policy_definition_id = data.azurerm_policy_set_definition.aks_pod_security_baseline.id
  parameters = jsonencode({
    effect = {
      value = "Deny"
    }
  })
}
output "aks_cluster_name" {
  description = "Name of the AKS cluster targeted by this policy assignment."
  value = var.aks_cluster_name
}

省略可能: カスタム ポリシー定義を作成して割り当てる

カスタム ポリシー定義セクションは情報であり、この記事の範囲外です。 カスタム ポリシーを使用すると、Azure を使用する際の規則を定義することができます。 たとえば、次の種類のルールを適用できます。

  • セキュリティ プラクティス。
  • コスト管理。
  • 名前付け規則や場所などの組織固有の規則。

カスタム ポリシーを作成する前に、一般的なパターンとサンプルの一覧を確認して、該当するケースがすでにカバーされていないかどうかを確認してください。

カスタム ポリシー定義は JSON で記述されます。 カスタム ポリシーの作成について詳しくは、「Azure Policy の定義の構造」と「カスタム ポリシー定義の作成」を参照してください。

注

Azure Policyは templateInfo という名前のプロパティを使用します。このプロパティを使用して、制約テンプレートのソース型を定義できます。 ポリシー定義で templateInfo を定義する場合、 constraintTemplate プロパティまたは 制約 プロパティを使用することはできません。 その場合でも、apiGroups と kinds の定義は必要です。 詳細については、「Azure Policy効果について」を参照してください。

カスタム ポリシー定義を作成したら、「ポリシー 定義を割り当てる 」を参照して、クラスターにポリシーを割り当てる手順を説明します。

Azure Policy が実行されていることを検証する

次の kubectl get コマンドを使用して、ポリシーの割り当てがクラスターに適用されていることを確認します。

kubectl get constrainttemplates

注

ポリシーの割り当てが各クラスターに同期されるまでに最大 20 分かかる場合があります。

出力は次の出力例のようになります。

NAME                                     AGE
k8sazureallowedcapabilities              23m
k8sazureallowedusersgroups               23m
k8sazureblockhostnamespace               23m
k8sazurecontainerallowedimages           23m
k8sazurecontainerallowedports            23m
k8sazurecontainerlimits                  23m
k8sazurecontainernoprivilege             23m
k8sazurecontainernoprivilegeescalation   23m
k8sazureenforceapparmor                  23m
k8sazurehostfilesystem                   23m
k8sazurehostnetworkingports              23m
k8sazurereadonlyrootfilesystem           23m
k8sazureserviceallowedports              23m

特権のあるポッドの拒否を検証する

privileged: trueのセキュリティ コンテキストを使用してポッドをスケジュールするとどうなるかをテストします。 このセキュリティコンテキストは、ポッドの特権を昇格させます。 イニシアチブでは特権のあるポッドが禁止されているため、要求は拒否されます。その結果、デプロイが拒否されます。

  1. nginx-privileged.yaml という名前のファイルを作成し、次の YAML マニフェストを貼り付けます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-privileged
    spec:
      containers:
        - name: nginx-privileged
          image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
          securityContext:
            privileged: true
    
  2. kubectl apply コマンドを使用してポッドを作成し、YAML マニフェストの名前を指定します。

    kubectl apply -f nginx-privileged.yaml
    

    次の出力例に示すように、このポッドは想定どおりスケジュールできません。

    Error from server ([denied by azurepolicy-container-no-privilege-00edd87bf80f443fa51d10910255adbc4013d590bec3d290b4f48725d4dfbdf9] Privileged container is not allowed: nginx-privileged, securityContext: {"privileged": true}): error when creating "privileged.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [denied by azurepolicy-container-no-privilege-00edd87bf80f443fa51d10910255adbc4013d590bec3d290b4f48725d4dfbdf9] Privileged container is not allowed: nginx-privileged, securityContext: {"privileged": true}
    

    ポッドはスケジューリング段階に達しないため、続行する前に削除するリソースはありません。

特権のないポッドの作成をテストする

前の例では、コンテナー イメージは root を使用してポート 80 に NGINX をバインドしようとしました。 ポリシー イニシアチブによりこの要求が拒否されるので、ポッドの起動が失敗します。 次に、特権アクセスなしで同じ NGINX ポッドを実行してみてください。

  1. nginx-unprivileged.yamlという名前のファイルを作成し、次の YAML マニフェストを貼り付けます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-unprivileged
    spec:
      containers:
        - name: nginx-unprivileged
          image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
    
  2. kubectl apply コマンドを使用してポッドを作成し、YAML マニフェストの名前を指定します。

    kubectl apply -f nginx-unprivileged.yaml
    
  3. kubectl get pods コマンドを使用して、ポッドの状態を確認します。

    kubectl get pods
    

    出力は次の出力例のようになります。ここには、ポッドが正常にスケジュールされ、状態が [実行中] であることが示されています。

    NAME                 READY   STATUS    RESTARTS   AGE
    nginx-unprivileged   1/1     Running   0          18s
    

    この例は、コレクション内のポリシーに違反するデプロイのみに影響するベースライン イニシアチブを示しています。 許可されたデプロイは引き続き機能します。

  4. NGINX コマンドを使用して、特権のないポッドkubectl deleteを削除し、YAML マニフェストの名前を指定します。

    kubectl delete -f nginx-unprivileged.yaml
    

Terraform を使用して、組み込みのAzure Policy イニシアチブを AKS クラスターに割り当てるには、次の手順に従います。

前に示した Terraform 構成は、組み込みのイニシアチブを取得し、AKS クラスターを含むリソース グループに割り当てます。

Terraform 構成を初期化する

terraform initを実行して Terraform 作業ディレクトリを初期化し、必要なプロバイダー プラグインをダウンロードします。

terraform init

構成の書式設定と検証

terraform fmtを実行して Terraform 構成の書式を設定します。

terraform fmt

terraform validateを実行して、Terraform 構成構文を検証します。

terraform validate

Terraform 構成を適用する

構成をデプロイする前に、次の変数の値を指定します。

  • resource_group_name
  • aks_cluster_name

terraform applyを実行して、Azure Policy割り当てをデプロイします。

terraform apply

メッセージが表示されたら、「 yes 」と入力してデプロイを確認します。

Azure Policyのインストールを確認する

デプロイが完了したら、Azure Policy コンポーネントが AKS クラスターで実行されていることを確認します。

kubectl get pods -n kube-system

Gatekeeper 制約テンプレートが正常にインストールされたことを確認します。

kubectl get constrainttemplates

Azure Policy割り当てをテストする

privileged-pod.yaml という名前でファイルを作成します。

apiVersion: v1
kind: Pod
metadata:
 name: privileged-pod
spec:
 containers:
 - name: nginx
   image: nginx
   securityContext:
     privileged: true

マニフェストをクラスターに適用します。

kubectl apply -f privileged-pod.yaml

Azure Policy割り当てによって、構成済みのポッド セキュリティ ベースライン標準に違反する特権コンテナーが拒否されるため、デプロイは失敗します。

ポリシーまたはイニシアチブを無効にする

次の手順を使用して、Azure ポータルでベースライン イニシアチブを削除します。

  1. Azure ポータルの [ポリシー] ウィンドウに移動します。
  2. [割り当て] を選択します。
  3. ...の行の末尾にある省略記号 () を選択します。
  4. [割り当ての削除] を選択します。

Azure Policy アドオンを AKS クラスターから削除するには、「アドオンの削除」を参照してください。

ポリシーまたはイニシアチブを無効にする

Terraform 構成を含むディレクトリから terraform destroy を実行して、サンプルによって作成されたポリシー割り当てを削除します。

terraform destroy

Azure Policy アドオンを AKS クラスターから削除するには、「アドオンの削除」を参照してください。

次のステップ

Azure Policy のしくみについて詳しくは、次の記事をご覧ください。