このドキュメントは、ソース OpenShift クラスタで定義された OpenShift セキュリティ コンテキスト制約(SCC)からターゲット GKE クラスタへのセキュリティ ポリシーの移行を計画する際に役立ちます。この実装では、Policy Controller の制約を使用して、移行したポリシーをターゲット クラスタに定義します。
このドキュメントは、Google Cloud へのコンテナの移行: OpenShift から GKE Enterprise への移行を理解していることを前提としています。OpenShift とセキュリティ コンテキストの制約を理解し、ソース OpenShift クラスタとターゲット GKE クラスタにアクセスできることを前提としています。
このドキュメントは、Google Cloud への移行に関する複数のパートからなるシリーズの一部です。シリーズの概要については、Google Cloud への移行: 移行パスの選択をご覧ください。
このドキュメントは、コンテナを Google Cloud に移行する方法を説明するシリーズの一部です。
- Google Cloud へのコンテナの移行: Kubernetes から Google Kubernetes Engine(GKE)への移行
- Google Cloud へのコンテナの移行: OpenShift から GKE Enterprise への移行
- Google Cloud へのコンテナの移行: OpenShift プロジェクトを GKE Enterprise に移行する
- OpenShift から GKE Enterprise への移行: OpenShift SSC から Policy Controller 制約への移行(このドキュメント)
このドキュメントは、OpenShift SCC を GKE Enterprise に移行する場合に役立ちます。また、移行について検討している場合、その概要を把握するうえでも、このドキュメントが役立ちます。
このドキュメントは、Google Cloud への移行: スタートガイド、Google Cloud へのコンテナの移行: Kubernetes から GKE への移���、Google Cloud へのコンテナの移行: OpenShift から GKE Enterprise への移行、GKE ネットワーキングのベスト プラクティスで説明されているコンセプトに基づいています。必要に応じてそれらのドキュメントへのリンクも掲載しています。
OpenShift SCC
SCC は OpenShift 固有のリソースであり、Pod が実行できるアクションや Pod がノードでアクセスできるリソースを指定する Pod のポリシーを定義するために使用されます。Pod を作成する API リクエストを行うと、SCC は SCC によって定義された一連のポリシーに対するプロセス権限に照らし合わせて Pod リクエストを評価します。SCC は、構成されたポリシーに従って Pod の実行を許可または拒否するリクエストを評価します。OpenShift SCC の詳細については、セキュリティ コンテキスト制約の管理をご覧ください。
デフォルトの OpenShift SCC
OpenShift 4.x クラスタには、一連のデフォルトの SCC が含まれています。詳しくは、Red Hat による OpenShift での SCC の管理に関するブログ投稿をご覧ください。
Config Sync と Policy Controller
このセクションでは、Config Sync と Policy Controller について説明します。このドキュメントで後述する移行タスクを実行するため、Policy Controller の設定に関連するドキュメントとガイダンスへのリンクを示します。
Config Sync
Config Sync を使用すると、共通の Git 準拠リポジトリを使って、GKE Enterprise が管理する Kubernetes クラスタに適用されるあらゆるリソースの構成を一元的に定義できます。その構成を複数のクラスタに適用してください。
Policy Controller
Policy Controller は Kubernetes の動的アドミッション コントローラであり、中央で定義されたポリシーに照合してクラスタのコンプライアンスをチェック、監査、適用します。Policy Controller は、オープンソース プロジェクトである Open Policy Agent(OPA)Gatekeeper をベースにしています。
Config Sync と Policy Controller の設定
OpenShift SCC をミラーリングするセキュリティ ポリシーの実装を準備するには、各ターゲット クラスタに対して Config Sync と Policy Controller コンポーネントを有効にします。このセクションでは、これらのコンポーネントを設定する方法について説明します。このドキュメントの後半の OpenShift SCC を移行するセクションでは、Policy Controller の制約テンプレートを使用してセキュリティ ポリシーを実装する方法について説明します。
Policy Controller を設定する場合は、アプリケーション Pod を実行しないシステム関連の Namespace を [名前空間の除外] フィールドに入力することをおすすめします。システム関連の Namespace を除外すると、権限昇格を必要とするシステム Pod がブロックされてしまうリスクを回避できます。GKE クラスタのシステム関連の Namespace には次のものが含まれます。
kube-system
kube-public
gke-connect
gke-system
config-management-system
config-management-monitoring
gatekeeper-system
istio-system
cnrm-system
knative-serving
monitoring-system
上記の例外を除いて Policy Controller を設定後、Namespace ごとに admission.gatekeeper.sh/ignore=true
ラベルを追加して、制約の適用から Namespace を除外します。各 Namespace にラベルを追加しないと、システム Pod(つまりクラスタ全体)が制限の厳しいポリシーの影響を受ける可能性があります。
OpenShift SCC を Policy Controller の制約に移行する
このセクションでは、OpenShift クラスタから SCC をエクスポートし、必要なポリシーに一致するようにターゲット GKE Enterprise Policy Controller の制約を構成する方法について説明します。また、SCC と Policy Controller の制約の違いについて説明し、それに応じて移行を計画できるようにします。
OpenShift SCC を評価する
OpenShift クラスタにインストールされている SCC のリストと構成をエクスポートするには、次のコマンドを使用します。
すべての SCC のリストを取得します。
oc get scc
各 SCC の構成をエクスポートします。
oc get scc SCC_NAME > SCC_NAME.yaml
SCC_NAME
は、構成をエクスポートする SCC の名前に置き換えます。
構成のエクスポート後、分析を行い、次の OpenShift SCC のマッピング セクションの表を使用して、アプリケーションのセキュリティ要件に一致する Policy Controller の制約を構成できます。
OpenShift SCC を Policy Controller 制約テンプレートにマッピングする
次の表に、OpenShift SCC フィールドとその有効な値に対応する Policy Controller の制約と設定を示します。次の表を使用して、移行元の環境の OpenShift SCC によって実装されたアプリケーションのセキュリティ要件に一致するターゲット Policy Controller の制約を構成できます。このドキュメントで後述するエンドツーエンドの移行の例のセクションには、次の表の情報の使用方法の例が記載されています。
OpenShift SCC フィールド | 型 / 取り得る値 | Policy Controller の制約テンプレート | Policy Controller の制約仕様 |
---|---|---|---|
allowPrivilegedContainer: |
ブール値 | K8sPSPPrivilegedContainer | 適用された場合、特権コンテナをブロックします。 |
allowHostIPC: |
ブール値 | K8sPSPHostNamespace | 適用された場合、ホスト pid および ipc の名前空間へのアクセスを阻止します。 |
allowHostPID: |
ブール値 | K8sPSPHostNamespace | 適用された場合、ホスト pid および ipc の名前空間へのアクセスを阻止します。 |
allowHostNetwork: |
ブール値 | K8sPSPHostNetworkingPorts | ホスト ネットワークへのアクセスを阻止するブール値パラメータを持ち、アクセス可能なホストのポートの範囲を定義できます。 |
allowHostPorts: |
ブール値 | K8sPSPHostNetworkingPorts | ホスト ネットワークへのアクセスを阻止するブール値パラメータを持ち、アクセス可能なホストのポートの範囲を定義できます。 |
readOnlyRootFilesystem: |
ブール値 | K8sPSPReadOnlyRootFilesystem | 適用された場合、コンテナのルートファイル システムを読み取り専用としてのみマウントできます。 |
allowPrivilegeEscalation: true |
ブール値 | K8sPSPAllowPrivilegeEscalationContainer | 適用された場合、AllowPrivilegeEscalation セキュリティ コンテキストが true に設定された Pod をブロックします。 |
allowHostDirVolumePlugin: |
ブール値 | K8sPSPVolumeTypes | (SCC と同様に)ホスト ディレクトリを含む許可されたボリュームの種類のリストを定義するパラメータを持ちます。 |
volumes: |
許可されたボリュームの種類の配列リスト | K8sPSPVolumeTypes | (SCC と同様に)ホスト ディレクトリを含む許可されたボリュームの種類のリストを定義するパラメータを持ちます。 |
allowedCapabilities: |
リクエストできる Linux 機能の配列リスト | K8sPSPCapabilities | リクエストできる Linux 機能(allowedCapabilities)と禁止されている Linux 機能(requiredDropCapabilites )を定義するパラメータを持ちます。OpenShift SCC の |
defaultAddCapabilities: |
各コンテナに追加する必要のある Linux 機能の配列リスト | K8sPSPCapabilities | リクエストできる Linux 機能(allowedCapabilities)と禁止されている Linux 機能(requiredDropCapabilites )を定義するパラメータを持ちます。OpenShift SCC の |
requiredDropCapabilities: |
Pod またはコンテナから自動的に削除される Linux 機能の配列リスト | K8sPSPCapabilities | リクエストできる Linux 機能(allowedCapabilities)と禁止されている Linux 機能(requiredDropCapabilites )を定義するパラメータを持ちます。OpenShift SCC の |
fsGroup: |
次のいずれかに設定可能な type: key を持ちます。
|
K8sPSPAllowedUsers | SCC の type: key とrunAsUser 、runAsGroup 、supplementalGroups 、fsGroup の各パラメータの id 範囲に対して類似した機能を有するルールを定義できます。User、Groups、Supplemental Groups、FS Groups に許可される範囲を定義できるが、OpenShift SCC とは異なり、Pod で直接ユーザー ID を設定するために使用することはできません。 |
runAsUser: |
次のいずれかに設定可能な type: key を持ちます。
|
K8sPSPAllowedUsers | SCC の type: key とrunAsUser 、runAsGroup 、supplementalGroups 、fsGroup の各パラメータの id 範囲に対して類似した機能を有するルールを定義できます。User、Groups、Supplemental Groups、FS Groups に許可される範囲を定義できるが、OpenShift SCC とは異なり、Pod で直接ユーザー ID を設定するために使用することはできません。 |
supplementalGroups: |
次のいずれかに設定可能な type: key を持ちます。
|
K8sPSPAllowedUsers | SCC の type: key とrunAsUser 、runAsGroup 、supplementalGroups 、fsGroup の各パラメータの id 範囲に対して類似した機能を有するルールを定義できます。User、Groups、Supplemental Groups、FS Groups に許可される範囲を定義できるが、OpenShift SCC とは異なり、Pod で直接ユーザー ID を設定するために使用することはできません。 |
seLinuxContext: |
次のいずれかに設定可能な type: key を持ちます。
|
K8sPSPSELinuxV2 | 許可されるレベル、ロール、タイプ、ユーザー seLinuxOptions を設定できる allowedSELinuxOptions ���ラメータ������有��ます。 |
OpenShift SCC と Policy Controller の制約の違い
このセクションでは、Policy Controller の制約と OpenShift SCC の違いについて説明します。上記の表を使用して移行先の環境に制約をデプロイする前に、これらの違いを考慮してください。
リソースに制約を適用する方法
SCC オブジェクトにある users:
仕様または group:
仕様を使用して、OpenShift SCC をユーザーとグループに割り当てることができます。OpenShift 4.x 以降のバージョンでは、ロールベース アクセス制御(RBAC)を使用してユーザーまたはグループに SCC を割り当てることもできます。SCC には、Pod に適用される SCC を並べ替えるための priority:
フィールドもあります。
Policy Controller の制約は、ユーザーまたはサービス アカウントをターゲットにするのではなく、制約の特定のリソース セレクタを使用するターゲット クラスタ、Namespace、Pod に適用されます。詳細については、Policy Controller のドキュメントをご覧ください。特定のリソース セレクタを使用すると、権限の限られたユーザーがデプロイツールを使用して Pod を実行するか、クラスタ管理者がコマンドラインから Pod を起動するかにかかわらず、Pod の動作を同じにできます。
Policy Controller の制約は、ドライラン モードもサポートしています。このモードでは、ポリシーを実際に適用する前にテストを行い、違反を監査できます。このモードを使用すると、既存のワークロードへの影響が生じることを回避できます。また、ユーザーが SCC の適用対象である場合は、常に適用されます。
OpenShift 名前空間に事前に割り当てられた値を使用した SCC Pod ミューテーション
OpenShift SCC では、SCC が適用される各 Pod の関連するセキュリティ コンテキストを、名前空間のアノテーションによって提供される事前に割り当てられた範囲からの特定の ID で変更できます。そのためには、戦略タイプ MustRunAs
または MustRunAsRange
で RunAsUser
、fsGroup
、supplementalGroups
、seLinuxContext
の各フィールドを使用します。
たとえば、restricted
SCC に RunAsUser
フィールドがあり、戦略タイプが MustRunAsRange
で、SCC で範囲が定義されていないとします。このシナリオでは、SCC が適用される各 Pod は、Pod の Namespace の openshift.io/sa.scc.uid-range
アノテーションで指定された範囲から RunAsUser
ID を取得します。
Policy Controller の制約とミューテーション機能により、Pod の検証とミューテーションの両方を実現できます。ただし、この制約では、Pod セキュリティ コンテキストの値を提供するために Namespace のアノテーションを使用しません。次のセクションエンドツーエンドの移行の例は、アプリケーション配信チームが前述の制約と同様の制限を実装する制約に従うように Pod のセキュリティ コンテキストを明示的に構成する方法の例を示しています。
エンドツーエンドの移行の例
このセクションでは、次の OpenShift デフォルト SCC をターゲット GKE クラスタにマッピングするために必要な Policy Controller のすべての制約とミューテータを含む、ターゲット マニフェスト ファイルの例を示します。
privileged
anyuid
nonroot
restricted
ソース OpenShift 環境で定義されている SCC ポリシーをマッピングするときに、Pod が実行される Namespace に応じて、異なるポリシー コントローラ制約が適用されます。
特権モードでの実行やホストリソースへのアクセスなど、最も高い特権アクセスを必要とするワークロードは、Policy Controller の構成で定義されている除外 Namespace のいずれかで行う必要があります。
Namespace の除外に適用される制約はありません。通常、この最も高い特権アクセスを持つワークロードは、ソース OpenShift 環境で特権 SCC が適用されたシステム コンポーネントまたはワークロードです。
免除対象外の名前空間で作成されたすべての Pod には、最も制限の厳しい制約が適用されます。これらの制約により、すべてのホスト機能へのアクセスが拒否されるため、Pod は特定の範囲内の UID で実行する必要があります。この構成は、OpenShift
restricted
SCC によって適用されるポリシーと一致します。この構成には次のような例外があります。security=anyuid
ラベルを持つ名前空間に作成された Pod は、上記の制限の厳しい制約を受けますが、UID と GID のどちらでも実行できます。これは OpenShift に対するanyuid
SCC の制約と一致します。security=nonroot
ラベルを持つ名前空間に作成された Pod は、上記の制限の厳しい制約を受けます。ただし、Pod は root 以外の UID を指定して実行できます。これは OpenShift に対するnonroot
SCC の制約と一致します。
ターゲット マニフェストの例
以下は、前のエンドツーエンドの移行例で説明した動作に一致する Policy Controller の制約とミューテータのセットを含む、単一マニフェストの例です。この例の制約または範囲は、組織のニーズに応じて確認、調整することをおすすめします。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNamespace
metadata:
name: psp-host-namespace
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNetworkingPorts
metadata:
name: psp-host-network-ports
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
hostNetwork: false
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: psp-privileged-container
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
---
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: restricted-capabilities
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
match:
scope: Namespaced
kinds:
- apiGroups: ["*"]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: NotIn
key: security
values: ["anyuid"]
location: "spec.containers[name:*].securityContext.capabilities.drop"
parameters:
assign:
value: ["KILL","MKNOD","SYS_CHROOT"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
name: restricted-capabilities
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: NotIn
key: security
values: ["anyuid"]
parameters:
requiredDropCapabilities: ["KILL","MKNOD","SYS_CHROOT"]
---
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: anyuid-capabilities
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
match:
scope: Namespaced
kinds:
- apiGroups: ["*"]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: In
key: security
values: ["anyuid"]
location: "spec.containers[name:*].securityContext.capabilities.drop"
parameters:
assign:
value: ["MKNOD"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
name: anyuid-capabilities
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: In
key: security
values: ["anyuid"]
parameters:
requiredDropCapabilities: ["MKNOD"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowedUsers
metadata:
name: restricted-users-and-groups
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: NotIn
key: security
values: ["anyuid","nonroot"]
parameters:
runAsUser:
rule: MustRunAs # MustRunAsNonRoot # RunAsAny
ranges:
- min: 1000
max: 2000
fsGroup:
rule: MustRunAs # MayRunAs # RunAsAny
ranges:
- min: 1000
max: 2000
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowedUsers
metadata:
name: nonroot-users-and-groups
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaceSelector:
matchExpressions:
- operator: In
key: security
values: ["nonroot"]
parameters:
runAsUser:
rule: MustRunAsNonRoot
fsGroup:
rule: MustRunAsNonRoot
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPVolumeTypes
metadata:
name: psp-volume-types
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
volumes:
- configMap
- downwardAPI
- emptyDir
- nfs
- persistentVolumeClaim
- projected
- secret
サンプル マニフェストの restricted-users-and-groups
制約では、K8sPSPAllowedUsers
テンプレートを使用して、runAsUser:
パラメータと fsGroup:
パラメータに 1,000~2,000 のサンプル範囲が明示的に設定されます。runAsUser:
と fsGroup:
についてその範囲内の ID を使用するように設定されていない Pod はブロックされます。
GKE Enterprise と Kubernetes では、特定のユーザー ID またはグループ ID の Pod を自動的に変更するために Namespace アノテーションは使用されません。したがって、前の例のように UID 範囲を制限するには、アプリケーション配信チームは、作成した Pod で準拠する UID を明示的に設定する、または任意の ID を許可するために制約を完全に削除する必要があります。
作成した名前空間内の上記の制約を遵守している Pod マニフェストの例を次に示します(マニフェストは restricted
SCC に準拠しています)。
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod-example
spec:
securityContext:
runAsUser: 1000
fsGroup: 1100
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
次のステップ
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud アーキテクチャ センターをご覧ください。