7.7. SELinux プロファイルの管理
SELinux プロファイルを作成および管理し、それらをワークロードにバインドします。
Security Profiles Operator は、Red Hat Enterprise Linux CoreOS (RHCOS) ワーカーノードのみをサポートします。Red Hat Enterprise Linux (RHEL) ノードはサポートされていません。
7.7.1. SELinux プロファイルの作成
SelinuxProfile
オブジェクトを使用してプロファイルを作成します。
SelinuxProfile
オブジェクトには、セキュリティー強化と読みやすさを向上させるいくつかの機能があります。
-
継承するプロファイルを現在の namespace またはシステム全体のプロファイルに制限します。通常、システムには多くのプロファイルがインストールされていますが、クラスターワークロードではサブセットのみを使用する必要があるため、継承可能なシステムプロファイルは、
spec.selinuxOptions.allowedSystemProfiles
のspod
インスタンスにリストされています。 - 権限、クラス、およびラベルの基本的な検証を実行します。
-
ポリシーを使用するプロセスを説明する新しいキーワード
@self
を追加します。これにより、ポリシーの使用は名前と namespace に基づいているため、ワークロードと namespace の間でポリシーを簡単に再利用できます。 - SELinux CIL 言語で直接プロファイルを作成する場合と比較して、セキュリティーを強化し、読みやすくするための機能を追加します。
手順
次のコマンドを実行してプロジェクトを作成します。
$ oc new-project nginx-deploy
次の
SelinuxProfile
オブジェクトを作成して、特権のないワークロードで使用できるポリシーを作成します。apiVersion: security-profiles-operator.x-k8s.io/v1alpha2 kind: SelinuxProfile metadata: name: nginx-secure namespace: nginx-deploy spec: allow: '@self': tcp_socket: - listen http_cache_port_t: tcp_socket: - name_bind node_t: tcp_socket: - node_bind inherit: - kind: System name: container
次のコマンドを実行して、
selinuxd
がポリシーをインストールするのを待ちます。$ oc wait --for=condition=ready -n nginx-deploy selinuxprofile nginx-secure
出力例
selinuxprofile.security-profiles-operator.x-k8s.io/nginx-secure condition met
ポリシーは、Security Profiles Operator が所有するコンテナー内の
emptyDir
に配置されます。ポリシーは Common Intermediate Language (CIL) 形式で/etc/selinux.d/<name>_<namespace>.cil
に保存されます。以下のコマンドを実行して Pod を作成します。
$ oc -n openshift-security-profiles rsh -c selinuxd ds/spod
検証
次のコマンドを実行して、
cat
でファイルの内容を表示します。$ cat /etc/selinux.d/nginx-secure_nginx-deploy.cil
出力例
(block nginx-secure_nginx-deploy (blockinherit container) (allow process nginx-secure_nginx-deploy.process ( tcp_socket ( listen ))) (allow process http_cache_port_t ( tcp_socket ( name_bind ))) (allow process node_t ( tcp_socket ( node_bind ))) )
次のコマンドを実行して、ポリシーがインストールされていることを確認します。
$ semodule -l | grep nginx-secure
出力例
nginx-secure_nginx-deploy
7.7.2. Pod への SELinux プロファイルの適用
Pod を作成して、作成したプロファイルの 1 つを適用します。
SELinux プロファイルの場合、namespace にラベルを付けて、特権 ワークロードを許可する必要があります。
手順
次のコマンドを実行して、
scc.podSecurityLabelSync=false
ラベルをnginx-deploy
namespace に適用します。$ oc label ns nginx-deploy security.openshift.io/scc.podSecurityLabelSync=false
次のコマンドを実行して、
privileged
ラベルをnginx-deploy
namespace に適用します。$ oc label ns nginx-deploy --overwrite=true pod-security.kubernetes.io/enforce=privileged
次のコマンドを実行して、SELinux プロファイルの使用文字列を取得します。
$ oc get selinuxprofile.security-profiles-operator.x-k8s.io/nginx-secure -n nginx-deploy -ojsonpath='{.status.usage}'
出力例
nginx-secure_nginx-deploy.process
ワークロードマニフェストの出力文字列を
.spec.containers[].securityContext.seLinuxOptions
属性に適用します。apiVersion: v1 kind: Pod metadata: name: nginx-secure namespace: nginx-deploy spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - image: nginxinc/nginx-unprivileged:1.21 name: nginx securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] seLinuxOptions: # NOTE: This uses an appropriate SELinux type type: nginx-secure_nginx-deploy.process
重要ワークロードを作成する前に、SELinux
type
が存在している必要があります。
7.7.2.1. SELinux ログポリシーの適用
ポリシー違反または AVC 拒否をログに記録するには、SElinuxProfile
プロファイルを permissive
に設定します。
この手順では、ロギングポリシーを定義します。施行ポリシーを設定しません。
手順
permissive: true
をSElinuxProfile
に追加します。apiVersion: security-profiles-operator.x-k8s.io/v1alpha2 kind: SelinuxProfile metadata: name: nginx-secure namespace: nginx-deploy spec: permissive: true
7.7.2.2. ProfileBindings を使用してワークロードをプロファイルにバインドする
ProfileBinding
リソースを使用して、セキュリティープロファイルをコンテナーの SecurityContext
にバインドできます。
手順
quay.io/security-profiles-operator/test-nginx-unprivileged:1.21
イメージを使用する Pod をサンプルのSelinuxProfile
プロファイルにバインドするには、Pod とSelinuxProfile
オブジェクトと同じ namespace にProfileBinding
オブジェクトを作成します。apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileBinding metadata: namespace: my-namespace name: nginx-binding spec: profileRef: kind: SelinuxProfile 1 name: profile 2 image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 3
重要image: "*"
ワイルドカード属性を使用すると、すべての新しい Pod が、指定された namespace 内のデフォルトのセキュリティープロファイルにバインドされます。次のコマンドを実行して、namespace に
enable-binding=true
のラベルを付けます。$ oc label ns my-namespace spo.x-k8s.io/enable-binding=true
test-pod.yaml
という名前の Pod を定義します。apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: test-container image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21
Pod を作成します。
$ oc create -f test-pod.yaml
注記Pod がすでに存在する場合、Pod を再作成しなければバインディングは適切に機能しません。
検証
次のコマンドを実行して、Pod が
ProfileBinding
を継承していることを確認します。$ oc get pod test-pod -o jsonpath='{.spec.containers[*].securityContext.seLinuxOptions.type}'
出力例
profile_nginx-binding.process
7.7.2.3. コントローラーと SecurityContextConstraints の複製
デプロイメントやデーモンセットなど、コントローラーをレプリケートするための SELinux ポリシーをデプロイする場合、コントローラーによって生成された Pod
オブジェクトは、ワークロードを作成するユーザーの ID で実行されないことに注意してください。ServiceAccount
が選択されていない場合、Pod は、カスタムセキュリティーポリシーの使用を許可しない、制限された SecurityContextConstraints
(SCC) の使用に戻る可能性があります。
手順
次のコマンドを実行してプロジェクトを作成します。
$ oc new-project nginx-secure
次の
RoleBinding
オブジェクトを作成して、SELinux ポリシーをnginx-secure
namespace で使用できるようにします。kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: spo-nginx namespace: nginx-secure subjects: - kind: ServiceAccount name: spo-deploy-test roleRef: kind: Role name: spo-nginx apiGroup: rbac.authorization.k8s.io
Role
オブジェクトを作成します。apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: creationTimestamp: null name: spo-nginx namespace: nginx-secure rules: - apiGroups: - security.openshift.io resources: - securitycontextconstraints resourceNames: - privileged verbs: - use
ServiceAccount
オブジェクトを作成します。apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: null name: spo-deploy-test namespace: nginx-secure
Deployment
オブジェクトを作成します。apiVersion: apps/v1 kind: Deployment metadata: name: selinux-test namespace: nginx-secure metadata: labels: app: selinux-test spec: replicas: 3 selector: matchLabels: app: selinux-test template: metadata: labels: app: selinux-test spec: serviceAccountName: spo-deploy-test securityContext: seLinuxOptions: type: nginx-secure_nginx-secure.process 1 containers: - name: nginx-unpriv image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080
- 1
- デプロイメントが作成される前に、
.seLinuxOptions.type
が存在している必要があります。
注記SELinux タイプはワークロードで指定されておらず、SCC によって処理されます。デプロイと
ReplicaSet
によって Pod が作成されると、Pod は適切なプロファイルで実行されます。
SCC が、正しいサービスアカウントのみで使用できることを確認してください。詳細は、その他のリソース を参照してください。
7.7.3. ワークロードからのプロファイルの記録
Security Profiles Operator は、ProfileRecording
オブジェクトを使用してシステムコールを記録できるため、アプリケーションのベースラインプロファイルを簡単に作成できます。
ログエンリッチャーを使用して SELinux プロファイルを記録する場合は、ログエンリッチャー機能が有効になっていることを確認します。詳細は、関連情報 を参照してください。
privileged: true
のセキュリティーコンテキスト制限を持つコンテナーにより、ログベースの記録が防止されます。特権コンテナーは SELinux ポリシーの対象ではなく、ログベースの記録では特別な SELinux プロファイルを使用してイベントを記録します。
手順
次のコマンドを実行してプロジェクトを作成します。
$ oc new-project my-namespace
次のコマンドを実行して、namespace に
enable-recording=true
のラベルを付けます。$ oc label ns my-namespace spo.x-k8s.io/enable-recording=true
recorder: logs
変数を含むProfileRecording
オブジェクトを作成します。apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileRecording metadata: namespace: my-namespace name: test-recording spec: kind: SelinuxProfile recorder: logs podSelector: matchLabels: app: my-app
記録するワークロードを作成します。
apiVersion: v1 kind: Pod metadata: namespace: my-namespace name: my-pod labels: app: my-app spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: nginx image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] - name: redis image: quay.io/security-profiles-operator/redis:6.2.1 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
次のコマンドを入力して、Pod が
Running
状態であることを確認します。$ oc -n my-namespace get pods
出力例
NAME READY STATUS RESTARTS AGE my-pod 2/2 Running 0 18s
エンリッチャーがそれらのコンテナーの監査ログを受信することを示していることを確認します。
$ oc -n openshift-security-profiles logs --since=1m --selector name=spod -c log-enricher
出力例
I0517 13:55:36.383187 348295 enricher.go:376] log-enricher "msg"="audit" "container"="redis" "namespace"="my-namespace" "node"="ip-10-0-189-53.us-east-2.compute.internal" "perm"="name_bind" "pod"="my-pod" "profile"="test-recording_redis_6kmrb_1684331729" "scontext"="system_u:system_r:selinuxrecording.process:s0:c4,c27" "tclass"="tcp_socket" "tcontext"="system_u:object_r:redis_port_t:s0" "timestamp"="1684331735.105:273965" "type"="selinux"
検証
Pod を削除します。
$ oc -n my-namepace delete pod my-pod
Security Profiles Operator が 2 つの SELinux プロファイルを調整することを確認します。
$ oc get selinuxprofiles -lspo.x-k8s.io/recording-id=test-recording -n my-namespace
selinuxprofile の出力例
NAME USAGE STATE test-recording-nginx test-recording-nginx_my-namespace.process Installed test-recording-redis test-recording-redis_my-namespace.process Installed
7.7.3.1. コンテナーごとのプロファイルインスタンスのマージ
デフォルトでは、各コンテナーインスタンスは個別のプロファイルに記録されます。Security Profiles Operator は、コンテナーごとのプロファイルを 1 つのプロファイルにマージできます。プロファイルのマージは、ReplicaSet
または Deployment
オブジェクトを使用してアプリケーションをデプロイメントするときに役立ちます。
手順
ProfileRecording
オブジェクトを編集して、mergeStrategy: containers
変数を含めます。apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileRecording metadata: # The name of the Recording is the same as the resulting SelinuxProfile CRD # after reconciliation. name: test-recording namespace: my-namespace spec: kind: SelinuxProfile recorder: logs mergeStrategy: containers podSelector: matchLabels: app: sp-record
以下のコマンドを実行して namespace にラベルを付けます。
$ oc label ns my-namespace security.openshift.io/scc.podSecurityLabelSync=false pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/audit=privileged pod-security.kubernetes.io/warn=privileged --overwrite=true
次の YAML を使用してワークロードを作成します。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy namespace: my-namespace spec: replicas: 3 selector: matchLabels: app: sp-record template: metadata: labels: app: sp-record spec: serviceAccountName: spo-record-sa containers: - name: nginx-record image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080
個々のプロファイルを記録するには、次のコマンドを実行してデプロイメントを削除します。
$ oc delete deployment nginx-deploy -n my-namespace
プロファイルをマージするには、次のコマンドを実行してプロファイルの記録を削除します。
$ oc delete profilerecording test-recording -n my-namespace
マージ操作を開始して結果プロファイルを生成するには、次のコマンドを実行します。
$ oc get selinuxprofiles -lspo.x-k8s.io/recording-id=test-recording -n my-namespace
selinuxprofile の出力例
NAME USAGE STATE test-recording-nginx-record test-recording-nginx-record_my-namespace.process Installed
いずれかのコンテナーで使用されている権限を表示するには、次のコマンドを実行します。
$ oc get selinuxprofiles test-recording-nginx-record -o yaml
7.7.3.2. About seLinuxContext: RunAsAny
SELinux ポリシーの記録は、記録される Pod に特別な SELinux タイプを挿入する Webhook で実装されます。SELinux タイプは、Pod を permissive
モードで実行し、すべての AVC 拒否を audit.log
に記録します。デフォルトでは、カスタム SELinux ポリシーを使用したワークロードの実行は許可されていませんが、自動生成されたタイプが使用されます。
ワークロードを記録するには、Webhook が許容された SELinux タイプを挿入できる SCC を使用する権限を持つサービスアカウントを使用する必要があります。privileged
SCC には、seLinuxContext: RunAsAny
が含まれています。
さらに、カスタム SELinux ポリシーの使用を許可するのは privileged
の Pod Security Standard のみであるため、クラスターで Pod Security Admission が有効になっている場合は、namespace に pod-security.kubernetes.io/enforce: privileged
付きのラベルを付ける必要があります。