nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

OpenShiftでUID指定されているコンテナをデプロイする

OpenShift 全部俺 Advent Calendar 2017

OpenShift上で動作するコンテナにはOpenShift側で採番されたUIDが割り当てられて、そのUIDで動作します。そのため、rootや特定のUIDでファイルにアクセスしたりすることを期待しているコンテナは動作しません。

とはいえ、DockerfileでUSER指定されているふつうのコンテナを動かしたいときもあります。そんなときにはSCCのnonrootを利用します。

https://docs.openshift.org/latest/admin_guide/manage_scc.html

このOpenShiftのSCC (Security Context Constraints)はKubernetesのPSP (Pod Security Policies)のベースとなっています。何度見てもプレイステーションポータブルって読んでしまいます。

https://kubernetes.io/docs/concepts/policy/pod-security-policy/

sccのデフォルトは以下のようになっています。

$ oc get scc
NAME               PRIV      CAPS      SELINUX     RUNASUSER          FSGROUP     SUPGROUP    PRIORITY   READONLYROOTFS   VOLUMES
anyuid             false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    10         false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
hostaccess         false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath persistentVolumeClaim projected secret]
hostmount-anyuid   false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim projected secret]
hostnetwork        false     []        MustRunAs   MustRunAsRange     MustRunAs   MustRunAs   <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
nonroot            false     []        MustRunAs   MustRunAsNonRoot   RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
privileged         true      [*]       RunAsAny    RunAsAny           RunAsAny    RunAsAny    <none>     false            [*]
restricted         false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]

sccには適用順があります。nonrootにはpriorityがセットされていないので、まずpriorityをセットする必要があります。

https://docs.openshift.org/latest/architecture/additional_concepts/authorization.html#scc-prioritization

$ oc patch scc nonroot -p "priority: 2"

これで準備はOKです。まずはUSERを指定したコンテナをデプロイして、割り当てられたUIDで動作していることを確認します。

$ cat <<EOF | oc new-build --dockerfile=- --to=sleep
FROM registry.access.redhat.com/rhel
RUN useradd -u 1001 -g 0 -d / -s /sbin/nologin default
USER 1001
CMD tail -f /dev/null
EOF
$ oc new-app sleep

scc, UIDの割り当てとランタイムのUIDを確認してみます。

$ oc describe project test-nonroot | grep scc
            openshift.io/sa.scc.mcs=s0:c14,c4
            openshift.io/sa.scc.supplemental-groups=1000190000/10000
            openshift.io/sa.scc.uid-range=1000190000/10000
$ oc describe pod sleep-1-5hgvn | grep scc
        openshift.io/scc=restricted
$ oc rsh dc/sleep id
uid=1000190000 gid=0(root) groups=0(root),1000190000

USER指定の1001ではないUIDとなっています。

scc nonrootをdefaultサービスアカウントに与えて再デプロイしてみます。

$ oc adm policy add-scc-to-user nonroot -z default
$ oc rollout latest sleep
$ oc describe pod sleep-2-hhzfd | grep scc
        openshift.io/scc=nonroot
$ oc rsh dc/sleep id
uid=1001(default) gid=0(root) groups=0(root)

きちんとUIDが変更されていますね。

UIDの変更方法を紹介しましたが、基本的にはコンテナイメージガイドラインに沿って、割り当てられたUIDで動作するようコンテナを作成することが推奨されます。

https://docs.openshift.org/latest/creating_images/guidelines.html

sccの適用は基本的にはセキュリティリスクとなりますので、利用は最小限となるようにしましょう。nonrootは比較的安全なsccですが、NFS PVへのアクセスなど、UIDがキーとなるセキュリティコントロールがあるのでやはりデフォルトのrestrictedより劣ります。また、rootが許可されるprivilegedやanyuidはセキュリティ的には最低ですので、これらが適用されるコンテナのイメージは必ず信頼されるもののみとしてください。自社できちんとメンテナンスしているもの、Red Hatなどのベンダーから正式に提供されているもの、などです。