體驗了一下Docker的root用戶映射

###2016/07/01:要想限制容器裏用戶的權限,有兩種方法:linux

  1. 讓你在容器裏作個凡人(這個方法對於有些須要root的容器是不適合的)

具體的就是,指定容器裏用戶的uid:gid,使得容器裏壓根不存在root用戶。docker

$ docker run -it -u 1000:1000 ubuntu
groups: cannot find name for group ID 1000   #這個錯誤不要緊
I have no name!@fcaadb40ddd0:/$ id     #執行id命令看看結果。
uid=1000 gid=1000 groups=1000

(這裏的uid:gid和主機的不同,具體的怎麼關聯的不太清楚。通常來講這個就足夠了,可是也許會有什麼應用須要root權限,這時就須要下一步要說的方法來限制權限了)json

  1. 讓你在容器裏作玉皇大帝, 可是這個玉皇大帝和全部凡人,都只是被映射到茫茫宇宙中一片卑微甚至虛空的身份上

就算容器裏有個孫悟空突破了限制作了玉皇大帝,那也翻不出如來佛的手掌。 具體的就是,把容器裏的root等用戶映射成主機那邊的指定的一片uid:gid。ubuntu


###2017/01/20:突然想起來看看,容器裏以root運行的進程,在外面看來究竟是什麼?是一個進程。那是什麼用戶身份呢?也是root,只是capabilities受到不少限制,理論上依然危險。app

在docker裏以root身份運行sleep 12345ssh

docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345

在容器外面查看這個sleep是什麼進程,什麼用戶身份?也是root。tcp

docker@somehost:~$ ps -ef |grep 12345
root      1997  1980  0 09:44 pts/1    00:00:00 sleep 12345

查看該進程的權限信息,就可以發現capabilities是受限制的,可是理論上仍是能夠鑽漏洞影響到容器外的。ide

docker@somehost:~$ cat /proc/1997/status |grep Cap
...
CapEff:	00000000a80425fb
...

用capsh工具查看00000000a80425fb就明白意思。這個root收到了限制。工具

最近用的docker-machine版本是0.8.2,docker 1.12.5。發現docker-machine裏面已經默認建立好了dockremap這個用戶了,連/etc/subuid /etc/subgid裏都準備好了。結果,只要修改活着建立/etc/docker/daemon.json,加上{"userns-remap":"default"}就能夠了,重啓動docker-machine就能夠生效。ui

確認

docker@somehost:~$ cat /etc/subuid 
dockremap:165536:65536
docker@somehost:~$ cat /etc/subgid 
dockremap:165536:65536

準備

docker@somehost:~$ cat /etc/docker/daemon.json
{
  "userns-remap": "default"
}

若是還不存在dockremap用戶,那麼就運行這個命令生成用戶dockremap:

sudo adduser --system dockremap

重啓動

docker-machine restart somehost
docker-machine ssh somehost

在docker裏以root身份運行sleep 12345

docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345

在容器外面查看這個sleep是什麼進程,什麼用戶身份

docker@somehost:~$ ps -ef |grep 12345
165536    2360  2344  0 09:36 ?        00:00:00 sleep 12345

就是這個165536,說明生效了,用戶身份不是之前的0(root)了。


####2016/?/?: 我要體驗的就是第2種功能,剛出來半年,由於uid映射只能手動作,並且是針對docker daemon設定的,因此默認是不開啓的,也沒法從普通的docker run命令裏指定。

參照了docker-for-your-users-introducing-user-namespace

主要是docker daemon加個選項 --userns-remap=test_user:test_group and add /etc/subuid /etc/subgid

若是按照docker官方文檔說的--userns-remap=default(就是讓docker daemon建立dockremap用戶),也會報錯說找不到用戶,據有的用戶反映是tiny core linux裏的adduser和普通的linux發行版不同,我沒仔細查。

$ docker-machine ssh rethink   # rethink is my vm name, please change it to yours.
...
docker@rethink:~$ sudo vi /var/lib/boot2docker/profile 
...
EXTRA_ARGS='
--label provider=virtualbox
--userns-remap=test_user:test_group            #####this is what i add#####
'
...
docker@rethink:~$ exit

then restart by docker-machine restart rethink, cause same error Maximum number of retries (10) exceeded (看/var/lib/boot2docker/docker.log能看到錯誤是說用戶找不到), docker daemon is not started,

then add user/group,

docker@rethink:~$ sudo addgroup -g 20 test_group
docker@rethink:~$ sudo adduser -G test_group -SDHu 501 test_user

then prepare uid/gid range for container

docker@rethink:~$ sudo -c "echo test_user:100000:65536 > /etc/subuid"
docker@rethink:~$ sudo  -c "echo test_group:200000:65536 > /etc/subgid"

then start docker daemon

docker@rethink:~$ sudo /usr/local/bin/docker daemon -D -g "/var/lib/docker" -H unix:// -H tcp://0.0.0.0:2376 --label provider=virtualbox \
--userns-remap=test_user:test_group --tlsverify --tlscacert=/var/lib/boot2docker/ca.pem --tlscert=/var/lib/boot2docker/server.pem --tlskey=/var/lib/boot2docker/server-key.pem -s aufs

...
INFO[0000] User namespaces: ID ranges will be mapped to subuid/subgid ranges of: test_user:test_group 
DEBU[0000] Creating user namespaced daemon root: /mnt/sda1/var/lib/docker/100000.200000 
...

Then i run docker container. There are strange thing here: previously used docker image will be treated as "not exist", get downloaded again.

$ docker run -it -v /bin:/xxx busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
8ddc19f16526: Pull complete 
Digest: sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6
Status: Downloaded newer image for busybox:latest
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # ls /xxx
VBoxClient     cat            dd             echo           gunzip         ln             mount          printenv       ...
...
/ # echo hi > /xxx/a
sh: can't create /xxx/a: Permission denied

很好, container裏的root只能老老實實的以host os裏的test_user身份運行了。

不過一旦重啓動就泡湯了(仍是老錯誤說用戶找不到), 出現問題後,請進去把/var/lib/boot2docker/profile裏的改動給恢復就好了。

重啓動致使的問題很好理解,八成是由於docker-machine的VM是從關盤(boot2docker.iso)裏啓動的,我作的修改大部分都是在iso的內存盤裏作的,並沒保存到iso裏,這是docker-machine的一個問題,有人提了建議了。

相關文章
相關標籤/搜索