現在位置: ホーム / セキュリティ ブログ / 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)

問い合わせボタン