Dockerの–security-optオプション(AppArmor)
強制アクセス制御と組み合わせることが可能です。
今回は、OpenSUSE.Asia Summit 2015で発表した、DockerとAppArmorを組み合わせる方法を
解説します。
こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面です。
今回は、所々の事情で少し遅くなってしまいましたが、OpenSUSE.Asia Summit 2015で発表した、DockerをAppArmorを使って保護する話をします。
なお、発表資料に関してはこちらからダウンロードできます。
Docker
今更ながらの説明になりますが、Dockerはアプリケーションのユーザ空間を分けて(コンテナ化)複数のアプリケーション環境を一つのOS上で動かし、アプリケーションとユーザ空間のポータビリティ・管理を高めたものです。
アプリケーションのユーザ空間を分けるという考え方は古くからchrootを用いて行われていましたので、昔からのUnix/Linux利用者には意外に馴染みやすい考え方になります。
また、Dockerでは過去にLXCをコンテナ化のエンジンとして使用していたので、LXCをご存じの方はコンテナのイメージが湧きやすいと思います。
ここで注意して欲しいのが、Dockerはセキュリティを高めるために生まれてきた実装ではないということで、複数のアプリケーション環境を一つのOS上で管理するためのものであるという事です。
Dockerのセキュリティ
やはりDockerのセキュリティとして一番の問題点は、Dockerのプロセスをrootで動作させる必要があるということでしょう。dockerグループにユーザを入れて実行させるということも出来ますが、dockerグループ自体がかなり強い権限を持っていますので、そこのところが懸念点になります。
このようなプロセスを保護するのには、よくSELinuxやAppArmorなどの強制アクセス制御機構を用いますが、Dockerでも1.3以降でSELinuxやAppArmorなどのLinuxのアクセス制御と連携できるように
--security-opt
というオプションが導入されました。このオプションを用いて、例えばdocker上でapacheをPort8080で動作させる場合には
docker run --name web1 --security-opt=[SELinuxのラベル or AppArmorのDomain] -p 8080:80 -d [Dockerイメージ]
のように動作させることで、dockerのプロセスを指定したSELinuxのラベルやAppArmorのDomainを用いて動かす事が出来ます。
Docker+AppArmorを試してみる
OpenSUSE + AppArmorの環境で、Dockerの–security-optを試してみましょう。
- まず前提として、OpenSUSE leap 42.1上にDockerをインストールし、次のようなDockerfileで、Docker環境でOpenSUSE leap 42.1を利用してhttpdを起動できるような環境にしておきます。
- /etc/apparmor.d/local以下にapparmorのweb用のprofile(docker_httpd_web1, docker_httpd_web2)を作成します。実際には、/etc/apparmor.d/usr.sbin.apache2をコピーして若干修正したものです。
- apparmorでdocker_httpd_web1をcomplainモードにしてから、Port8080でdocker_httpd_web1ドメインでDockerのhttpdを起動します。
- apparmorでdocker_httpd_web1をenforcingモードにして、Port8080でdocker_httpd_web1ドメインでDockerのhttpdを再起動します。
- “ps axZ”で、dockerのhttpdが”docker_httpd_web1″で動作していることを確認します。
- 割愛しますが(PDFの中にはやり方が書いてあります)、AppArmorでドメイン遷移を使うことで、Docker中で親となるsupervisordと、子となるhttpdとで、それぞれ異なるドメインを付与することも出来ます(この方が、より安全でしょう)。
From opensuse MAINTAINER user1 ENV ROOT_USER_PASSWORD password ENV USER_NAME user1 ENV USER_PASSWORD password ENV ZYPP_ARIA2C 1 RUN zypper -n refresh RUN zypper -n update # for supervisor ADD http-download.opensuse.org-a513f771.repo /etc/zypp/repos.d/ RUN zypper -n --gpg-auto-import-keys install supervisor # apache RUN zypper -n install apache2 apache2-mod_nss # iproute RUN zypper -n install iproute2 # timezone #RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime # Configure apache RUN chmod 755 /var/log/apache2 RUN touch /etc/sysconfig/network ADD index.html /srv/www/htdocs/ # Configure and Run supervisor RUN mkdir -p /var/run/supervisord RUN mkdir -p /var/log/supervisord ADD supervisord.conf /etc/supervisord.conf # Open Port EXPOSE 80 443 CMD ["/usr/bin/supervisord"]
linux-6749:/etc/apparmor.d/local # ls docker_httpd_web* docker_httpd_web1 docker_httpd_web2 linux-6749:/etc/apparmor.d/local # cat docker_httpd_web1 |grep -v \# profile docker_httpd_web1 flags=(attach_disconnected,mediate_deleted,complain) { signal (send) peer=@{profile_name}//*, capability dac_override, capability kill, capability net_bind_service, capability setgid, capability setuid, capability sys_tty_config, / rw, /** mrwlkix, ^DEFAULT_URI flags=(attach_disconnected,mediate_deleted,complain) { / rw, /** mrwlkix, } ^HANDLING_UNTRUSTED_INPUT flags=(attach_disconnected,mediate_deleted,complain) { / rw, /** mrwlkix, } }
docker run --name web1 --security-opt=apparmor:docker_httpd_web1 -p 8080:80 -d "Docker名"
docker_httpd_web1 (enforce) 5352 root /usr/bin/python /usr/bin/supervisord docker_httpd_web1 (enforce) 5396 root /usr/sbin/httpd-prefork -D FOREGROUND docker_httpd_web1 (enforce) 5397 wwwrun /usr/sbin/httpd-prefork -D FOREGROUND
docker_test_parent_web1 (enforce) root 2545 /usr/bin/python /usr/bin/supervisord docker_httpd_web1 (enforce) root 2566 /usr/sbin/httpd-prefork -D FOREGROUND docker_httpd_web1 (enforce) wwwrun 2583 /usr/sbin/httpd-prefork -D FOREGROUND docker_httpd_web1 (enforce) wwwrun 2584 /usr/sbin/httpd-prefork -D FOREGROUND
まとめ
Dockerを用いた時に、–security-optオプションを用いて、AppArmorやSELinuxなどの強制アクセス制御を用いて更にDockerの安全性を確保することが出来ます。
今回はAppArmorにのみ触れましたが、SELinuxを用いて同様に安全性を高めることが可能です。