現在位置: ホーム / セキュリティ ブログ / Dockerの--security-optオプション(AppArmor)

Dockerの--security-optオプション(AppArmor)

Dockerの--security-optオプションを用いることで、DockerをSELinuxや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を試してみましょう。

  1. まず前提として、OpenSUSE leap 42.1上にDockerをインストールし、次のようなDockerfileで、Docker環境でOpenSUSE leap 42.1を利用してhttpdを起動できるような環境にしておきます。
  2. 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"]
    
  3. /etc/apparmor.d/local以下にapparmorのweb用のprofile(docker_httpd_web1, docker_httpd_web2)を作成します。実際には、/etc/apparmor.d/usr.sbin.apache2をコピーして若干修正したものです。
  4. 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,
      }
    }
    
  5. apparmorでdocker_httpd_web1をcomplainモードにしてから、Port8080でdocker_httpd_web1ドメインでDockerのhttpdを起動します。
  6. docker run --name web1 --security-opt=apparmor:docker_httpd_web1 -p 8080:80 -d "Docker名"
    
  7. apparmorでdocker_httpd_web1をenforcingモードにして、Port8080でdocker_httpd_web1ドメインでDockerのhttpdを再起動します。
  8. "ps axZ"で、dockerのhttpdが"docker_httpd_web1"で動作していることを確認します。
  9. 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
    
  10. 割愛しますが(PDFの中にはやり方が書いてあります)、AppArmorでドメイン遷移を使うことで、Docker中で親となるsupervisordと、子となるhttpdとで、それぞれ異なるドメインを付与することも出来ます(この方が、より安全でしょう)。
  11. 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を用いて同様に安全性を高めることが可能です。

OSSよろず相談室

サイオスOSSよろず相談室(2)

問い合わせボタン

最新の記事
linux kernelの脆弱性( CVE-2017-7277 ) 2017年03月29日
ntpに複数の脆弱性(CVE-2017-6451, CVE-2017-6452, CVE-2017-6455, CVE-2017-6458, CVE-2017-6459, CVE-2017-6460, CVE-2017-6462, CVE-2017-6463, CVE-2017-6464 ) 2017年03月28日
linux kernelの脆弱性( CVE-2017-7273 ) 2017年03月28日
AppArmorの脆弱性( CVE-2017-6507 ) 2017年03月26日
linux kernelの脆弱性( CVE-2017-7261 ) 2017年03月25日
Sambaに共有以外のファイルにアクセスされる脆弱性(CVE-2017-2619) 2017年03月24日
Subscription-managerの脆弱性( CVE-2017-2663 ) 2017年03月22日
binutilsに複数の脆弱性( CVE-2017-6965, CVE-2017-6966, CVE-2017-6969, CVE-2017-7209 , CVE-2017-7210 , CVE-2017-7223, CVE-2017-7224, CVE-2017-7225, CVE-2017-7226, CVE-2017-7227 ) 2017年03月22日
linux kernelの脆弱性( CVE-2017-7187 ) 2017年03月21日
linux kernelの脆弱性( CVE-2017-6353 , CVE-2017-5986 ) 2017年03月21日
Ubuntu 16.10のkernelの脆弱性( CVE-2017-7184 ) 2017年03月20日
pcreの脆弱性( CVE-2017-7186 ) 2017年03月20日
binutilsの脆弱性( CVE-2017-6965 , CVE-2017-6966 , CVE-2017-6969 ) 2017年03月19日
MySQL(MariaDB) 5.5/5.6のmysql clientの脆弱性( Riddle : CVE-2017-3305 ) 2017年03月18日
linux kernelの脆弱性( CVE-2017-6951 ) 2017年03月17日
Apache Struts2の脆弱性 ( CVE-2017-5638 ) 2017年03月15日
linux kernelの脆弱性( CVE-2017-6874 ) 2017年03月15日
tomcatに情報漏えいの脆弱性( CVE-2016-8747 ) 2017年03月14日
QEMUの脆弱性( CVE-2016-9603 ) (Xen: XSA-211) 2017年03月14日
lxcの脆弱性(CVE-2017-5985) 2017年03月10日
wgetの脆弱性(CVE-2017-6508) 2017年03月08日
linux kernelに特権昇格の脆弱性( CVE-2017-2636 ) 2017年03月08日
( PoC ) linux kernel特権昇格脆弱性( CVE-2017-6074 ) の暫定回避策の確認 2017年03月06日
linux kernelの脆弱性( CVE-2016-9083 , CVE-2016-9084 ) 2017年03月03日
linux kernelに複数の脆弱性( CVE-2017-6345 , CVE-2017-6346 , CVE-2017-6347 , CVE-2017-6348 ) 2017年03月01日
Katello/Foremanによる運用管理 (Part4) 2017年02月28日
util-linux / coreutils の脆弱性(CVE-2017-2616) 2017年02月24日
linux kernelの脆弱性( CVE-2017-6214 ) 2017年02月24日
linux kernelに特権昇格の脆弱性( CVE-2017-6074 ) 2017年02月23日
curlの脆弱性 ( CVE-2017-2629 ) 2017年02月22日
QEMUの脆弱性( CVE-2017-2620 ) (Xen: XSA-209) 2017年02月22日
Tomcatの脆弱性 ( CVE-2017-6056 ) 2017年02月21日
Katello/Foremanによる運用管理 (Part3) 2017年02月21日
OpenSSLの脆弱性 ( CVE-2017-3733 ) 2017年02月16日
linux kernelの脆弱性( CVE-2017-6001 , (was CVE-2016-6786) ) 2017年02月16日
QEMUの脆弱性( CVE-2017-2630 ) 2017年02月15日
glibcの脆弱性(CVE-2015-8982, CVE-2015-8983, CVE-2015-8984) 2017年02月15日
vimの脆弱性 ( CVE-2017-5953 ) 2017年02月14日
Oracle Javaの脆弱性(Oracle Critical Patch Update Advisory - January 2017) 2017年02月14日
libxml2の脆弱性(CVE-2017-5969) 2017年02月13日
「linux kernel-4.9」でのLSMモジュールについて 2017年02月13日
linux kernelの脆弱性( CVE-2017-5970 ) 2017年02月13日
linux kernelの脆弱性( CVE-2016-8636 ) 2017年02月12日
bind 9 に設定依存の脆弱性 ( CVE-2017-3135 ) 2017年02月09日
bashの自動補完機能の脆弱性( CVE-2017-5932 ) 2017年02月08日
spiceの脆弱性( CVE-2016-9577 , CVE-2016-9578 ) 2017年02月08日
QEMUの脆弱性( CVE-2017-5898 ) 2017年02月08日
linux kernelの脆弱性( CVE-2017-5897 ) 2017年02月08日
linux kernelの脆弱性( CVE-2016-10208 ) 2017年02月06日
ntfs-3gの脆弱性(CVE-2017-0358) 2017年02月02日
QEMUの脆弱性( CVE-2017-2615 ) 2017年02月02日
tcpdumpに複数の脆弱性(CVE-2016-7922 等) 2017年01月30日
libgdに複数の脆弱性情報 (CVE-2016-9317, CVE-2016-6912, CVE-2016-10167, CVE-2016-10168, CVE-2016-10169) 2017年01月29日
OpenSSLに複数の脆弱性 ( CVE-2017-3730 , CVE-2017-3731 , CVE-2017-3732 ) 2017年01月27日
RunCに関しての脆弱性( CVE-2016-9962 )のPoCとSELinuxによるリスクの軽減 2017年01月26日
systemdの重要な脆弱性( CVE-2016-10156 ) 2017年01月25日
linux kernelの複数の脆弱性( CVE-2016-10153, CVE-2016-10154, CVE-2017-5547, CVE-2017-5548, CVE-2017-5549, CVE-2017-5550, CVE-2017-5551) 2017年01月25日
Katello/Foremanによる運用管理 (Part2) 2017年01月24日
linux kernel(KVMを有効にしている場合)で複数の脆弱性( CVE-2016-10150, CVE-2017-2583 ) 2017年01月21日
OpenSCAP 1.2.13のリリース情報 2017年01月16日
最新の記事 - もっと...