(ヽ´ω`) < DockerのOperation not permittedとの戦争
(ヽ´ω`) < Operation not permitted…
Dockerをさわりだして1週間だけど、たまーに何かのタイミングでOperation not permitted
が出る。
どうもDockerのセキュリティ機能として、デフォルトでは特定の操作を制限するようになっているらしい。
(ヽ´ω`) < 具体的にはどんなこと?
例えばdate
とかntpdate
でコンテナの時間を変更するとか、
[root@localhost ~]# docker run -i -t --rm centos:centos6 /bin/bash bash-4.1# date -s "2000/01/01 00:00:00" date: cannot set date: Operation not permitted Sat Jan 1 00:00:00 GMT 2000 bash-4.1# date Sat Oct 4 12:28:08 BST 2014 bash-4.1#
ルーティングテーブルを操作したりとか
[root@localhost ~]# docker run -i -t --rm centos:centos6 /bin/bash bash-4.1# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.42.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 bash-4.1# route add -net 192.168.0.0/24 gw 172.17.254.254 eth0 SIOCADDRT: Operation not permitted bash-4.1#
(ヽ´ω`) < 無慈悲なnot permitted
(ヽ´ω`) < これ、なんで?
普通の使い方をするなら、上記のような事はあまりしないかもしれないけど、検証とか実験となるとこの辺りの制限が煩わしい。
Security - Docker Documentation
公式のドキュメントを読んでいくと、Linux Capabilitiesに基づいて権限を一部制限しているらしい。
(ヽ´ω`) < Linux Capabilities ??
以下のmanと@ITの記事に詳しく書いてある。 時刻の操作や、ネットワーク関連の操作などの、システムに重要な変更権限を分割することで、セキュリティを向上させる機能。
権限を最小化するLinuxカーネルケーパビリティ − @IT
(ヽ´ω`) < んで、Dockerのデフォルトは?
公式のドキュメントにはざっくりと
との記述があるが、Githubのソースにははっきりと書いてあって(2014/10/04時点)
docker/default_template.go at master · docker/docker · GitHub
Capabilities: []string{ "CHOWN", "DAC_OVERRIDE", "FSETID", "FOWNER", "MKNOD", "NET_RAW", "SETGID", "SETUID", "SETFCAP", "SETPCAP", "NET_BIND_SERVICE", "SYS_CHROOT", "KILL", "AUDIT_WRITE", },
となっている。
上記一覧にはSYS_TIME
やNET_ADMIN
が無いので、先の時刻変更やルーティングテーブル変更がOperation not permittedとなる。
(ヽ´ω`) < さて、どうする
man docker-run
や上記の公式ドキュメントにも書いてあるが、docker run
に--privileged
フラグを渡してやることで、起動するコンテナに権限を与えることができる。
実際にやってみる。
## 時刻の設定 [root@localhost ~]# docker run -i -t --rm --privileged centos:centos6 /bin/bash bash-4.1# date -s "2000/01/01 00:00:00" Sat Jan 1 00:00:00 GMT 2000 bash-4.1# date Sat Jan 1 00:00:01 GMT 2000 bash-4.1#
## ルーティングテーブルの変更 [root@localhost ~]# docker run -i -t --rm --privileged centos:centos6 /bin/bash bash-4.1# route add -net 192.168.0.0/24 gw 172.17.254.254 eth0 bash-4.1# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.42.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 192.168.0.0 172.17.254.254 255.255.255.0 UG 0 0 0 eth0 bash-4.1#
(ヽ´ω`) < …あれ?
(ヽ´ω`) < 何か違和感
Linux Capabilitiesに基いて、と書いたが--privileged
オプションだと権限の分割ができていないんじゃ…
と思ったら、新しいバージョンでは--cap-add
と--cap-drop
オプションで細かく指定ができるようになっているらしい。
In addition to --privileged, the operator can have fine grain control over the capabilities using --cap-add and --cap-drop. By default, Docker has a default list of capabilities that are kept. Both flags support the value all, so if the operator wants to have all capabilities but MKNOD they could use:
$ sudo docker run --cap-add=ALL --cap-drop=MKNOD ...
For interacting with the network stack, instead of using --privileged they should use --cap-add=NET_ADMIN to modify the network interfaces.
らしいというのは、またもやCentOS7の2014/10/04現在のリポジトリにおいてあるバージョンでは、未だ未対応っぽい。あとからUbuntuでも入れて確認してみるか…