CIS ハードニングガイド
このドキュメントは、K3s の本番インストールをハードニングするための指針を提供します。これは、Center for Internet Security (CIS) の Kubernetes ベンチマークコントロールに対応するために必要な設定とコントロールを概説しています。
K3s には多くのセキュリティ緩和策がデフォルトで適用されており、変更なしで多くの Kubernetes CIS コントロールに合格します。ただし、CIS ベンチマークに完全に準拠するためには手動での介入が必要な例外もいくつかあります。
- K3s はホストオペレーティングシステムを変更しません。ホストレベルの変更は手動で行う必要があります。
NetworkPolicies
およびPodSecurityStandards
(v1.24
以前ではPodSecurityPolicies
) に関する特定の CIS ポリシーコントロールは、クラスターの機能を制限します。これらを設定するには、コマンドラインフラグまたは設定ファイルに適切なオプション(アドミッションプラグインの有効化)を追加し、適切なポリシーを手動で適用する必要があります。詳細は以下のセクションに記載されています。
CIS ベンチマークの最初のセクション (1.1) は主にポッドマニフェストの権限と所有権に関するものです。K3s はコアコンポーネントにこれらを使用しません。すべてが単一のバイナリにパッケージ化されているためです。
ホストレベルの要件
ホストレベルの要件には、カーネルパラメータと etcd プロセス/ディレクトリの設定の2つの領域があります。これらはこのセクションで概説されています。
protect-kernel-defaults
が設定されていることを確認する
これは、必要なカーネルパラメータが未設定または kubelet のデフォルト値と異なる値に設定されている場合に kubelet が終了するようにする kubelet フラグです。
注:
protect-kernel-defaults
は K3s のトップレベルフラグとして公開されています。
カーネルパラメータを設定する
/etc/sysctl.d/90-kubelet.conf
というファイルを作成し、以下のスニペットを追加します。その後、sysctl -p /etc/sysctl.d/90-kubelet.conf
を実行します。
vm.panic_on_oom=0
vm.overcommit_memory=1
kernel.panic=10
kernel.panic_on_oops=1
Kubernetes ランタイム要件
CIS ベンチマークに準拠するためのランタイム要件は、ポッドセキュリティ(PSP または PSA 経由)、ネットワークポリシー、および API サーバーの監査ログに集中しています。これらはこのセクションで概説されています。
デフォルトでは、K3s にはポッドセキ ュリティやネットワークポリシーは含まれていません。ただし、K3s にはネットワークポリシーを強制するコントローラーが付属しており、作成された場合に適用されます。K3s はデフォルトで監査を有効にしていないため、監査ログの設定と監査ポリシーを手動で作成する必要があります。デフォルトでは、K3s は PodSecurity
および NodeRestriction
アドミッションコントローラーを含む複数のアドミッションコントローラーを有効にして実行されます。
ポッドセキュリティ
- v1.25 and Newer
- v1.24 and Older
K3s v1.25 以降は、ポッドセキュリティを制御するための Pod Security Admissions (PSAs) をサポートしています。PSA は以下のフラグを K3s サーバーに渡すことで有効になります。
--kube-apiserver-arg="admission-control-config-file=/var/lib/rancher/k3s/server/psa.yaml"
ポリシーは /var/lib/rancher/k3s/server
ディレクトリに psa.yaml
という名前のファイルに書き込む必要があります。
以下は準拠した PSA の例です。
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1beta1
kind: PodSecurityConfiguration
defaults:
enforce: "restricted"
enforce-version: "latest"
audit: "restricted"
audit-version: "latest"
warn: "restricted"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces: [kube-system, cis-operator-system]
K3s v1.24 以前は、ポッドセキュリティを制御するための Pod Security Policies (PSPs) をサポートしています。PSP は以下のフラグを K3s サーバーに渡すことで有効になります。
--kube-apiserver-arg="enable-admission-plugins=NodeRestriction,PodSecurityPolicy"
これにより、NodeRestriction
プラグインを維持しつつ、PodSecurityPolicy
を有効にします。
PSP が有効になると、CIS ベンチマークのセクション 5.2 で説明されている必 要なコントロールを満たすためのポリシーを適用できます。
以下は準拠した PSP の例です。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted-psp
spec:
privileged: false # CIS - 5.2.1
allowPrivilegeEscalation: false # CIS - 5.2.5
requiredDropCapabilities: # CIS - 5.2.7/8/9
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'csi'
- 'persistentVolumeClaim'
- 'ephemeral'
hostNetwork: false # CIS - 5.2.4
hostIPC: false # CIS - 5.2.3
hostPID: false # CIS - 5.2.2
runAsUser:
rule: 'MustRunAsNonRoot' # CIS - 5.2.6
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: false
上記の PSP を有効にするためには、ClusterRole と ClusterRoleBinding を作成する必要があります。また、追加の特権を必要とするシステムレベルのポッドに必要な「システム無制限ポリシー」と、servicelb が正常に機能するために必要な sysctl を許可する追加のポリシーも含める必要があります。
上記の設定を次のセクションで説明する ネットワークポリシー と組み合わせて、単一のファイルを /var/lib/rancher/k3s/server/manifests
ディレクトリに配置できます。以下は policy.yaml
ファイルの例です。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted-psp
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'csi'
- 'persistentVolumeClaim'
- 'ephemeral'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: false
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: system-unrestricted-psp
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
allowPrivilegeEscalation: true
allowedCapabilities:
- '*'
fsGroup:
rule: RunAsAny
hostIPC: true
hostNetwork: true
hostPID: true
hostPorts:
- max: 65535
min: 0
privileged: true
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: svclb-psp
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
allowPrivilegeEscalation: false
allowedCapabilities:
- NET_ADMIN
allowedUnsafeSysctls:
- net.ipv4.ip_forward
- net.ipv6.conf.all.forwarding
fsGroup:
rule: RunAsAny
hostPorts:
- max: 65535
min: 0
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: psp:restricted-psp
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
verbs:
- use
resourceNames:
- restricted-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: psp:system-unrestricted-psp
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
resourceNames:
- system-unrestricted-psp
verbs:
- use
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: psp:svclb-psp
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
resourceNames:
- svclb-psp
verbs:
- use
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: default:restricted-psp
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:restricted-psp
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system-unrestricted-node-psp-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:system-unrestricted-psp
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:nodes
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: system-unrestricted-svc-acct-psp-rolebinding
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:system-unrestricted-psp
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: svclb-psp-rolebinding
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:svclb-psp
subjects:
- kind: ServiceAccount
name: svclb
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: intra-namespace
namespace: kube-system
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: intra-namespace
namespace: default
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: default
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: intra-namespace
namespace: kube-public
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-public
注意: Kubernetes の重要な追加機能である CNI、DNS、および Ingress は
kube-system
ネームスペースでポッドとして実行されます。したがって、これらのコンポーネントが適切に動作するために、このネームスペースには制限が少ないポリシーが適用されます。
NetworkPolicies
CIS は、すべてのネームスペースに対して、ネームスペースおよびポッドへのトラフィックを合理的に制限するネットワークポリシーが適用されることを要求しています。
ネットワークポリシーは /var/lib/rancher/k3s/server/manifests
ディレクトリに配置する必要があり、起動時に自動的にデプロイされます。
以下は、準拠したネットワークポリシーの例です。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: intra-namespace
namespace: kube-system
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
適用された制限により、DNS は意図的に許可されない限りブロックされます。以下は、DNS のトラフィックを許可するネットワークポリシーです。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-network-dns-policy
namespace: <NAMESPACE>
spec:
ingress:
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Ingress
メトリクスサーバーおよび Traefik Ingress コントローラーは、アクセスを許可するネットワークポリシーが作成されない限り、デフォルトでブロックされます。K3s バージョン 1.20 およびそれ以前にパッケージ化された Traefik v1 は、Traefik v2 とは異なるラベルを使用します。クラスターに存在する Traefik のバージョンに関連するサンプル YAML のみを使用するようにしてください。
- v1.21 and Newer
- v1.20 and Older
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-metrics-server
namespace: kube-system
spec:
podSelector:
matchLabels:
k8s-app: metrics-server
ingress:
- {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-svclbtraefik-ingress
namespace: kube-system
spec:
podSelector:
matchLabels:
svccontroller.k3s.cattle.io/svcname: traefik
ingress:
- {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-traefik-v121-ingress
namespace: kube-system
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: traefik
ingress:
- {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-metrics-server
namespace: kube-system
spec:
podSelector:
matchLabels:
k8s-app: metrics-server
ingress:
- {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-svclbtraefik-ingress
namespace: kube-system
spec:
podSelector:
matchLabels:
svccontroller.k3s.cattle.io/svcname: traefik
ingress:
- {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-traefik-v120-ingress
namespace: kube-system
spec:
podSelector:
matchLabels:
app: traefik
ingress:
- {}
policyTypes:
- Ingress
---