Apache を認証プロキシとして使う

使用例

皆さんの中には、サービスを使うユーザの認証のために Apache のプロキシ機能を利用しているケースもあるでしょう。そして、そうなら更に活用したいと思うかもしれません。Registry で同じ処理系(パイプライン)を通して通信させることができます。

エンタープライズの環境であれば、通常はバックエンドに LDAP やアクティブ・ディレクトリを使うか、内部の http ポータルで SSO (シングル・サインオン)の仕組みを使うでしょう。

あるいは

自分の Registry に認証が必要になったときや、ユーザのアクセスを分けてメンテナンスを楽にしたい場合は、内部実装されている ベーシック認証レジストリ機能 の利用を検討するでしょう。

解決策

この課題に対応するため、ここでは Docker Engine にリバース・プロキシを通したベーシック認証機能を実装します。これには Registry の前にリバース・プロキシをおきます。

今回のサンプルでは簡単な htpasswd ファイルを使います。もしも他の Apache 認証バックエンドの実装になれているのであれば、今回のサンプル同様、簡単に実装できるでしょう。

また、push を制限(ユーザやグループの制限)する実装も可能です。そのような場合も、このサンプルを目的に合わせて書き換えるだけで実現できるでしょう。

捕捉

このモデルは、自分が使いたい何らかのバックエンド機構をプロキシとして使えることをも意味します。また、その場合には自分自身で Registry をプロキシの TLS 末端に移動する必要があります。

それだけではありません。何らかの http 通信パイプラインを導入することで、更に複雑なデプロイ、メンテナンス、デバッグなど、様々な問題に対処できるでしょう。

セットアップ

必要条件 をもう一度お読みください。

準備はできましたか?

以下のスクリプトを実行します:

mkdir -p auth
mkdir -p data# This is the main apache configuration you will usecat <<EOF > auth/httpd.confLoadModule headers_module modules/mod_headers.soLoadModule authn_file_module modules/mod_authn_file.soLoadModule authn_core_module modules/mod_authn_core.soLoadModule authz_groupfile_module modules/mod_authz_groupfile.soLoadModule authz_user_module modules/mod_authz_user.soLoadModule authz_core_module modules/mod_authz_core.soLoadModule auth_basic_module modules/mod_auth_basic.soLoadModule access_compat_module modules/mod_access_compat.soLoadModule log_config_module modules/mod_log_config.soLoadModule ssl_module modules/mod_ssl.soLoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule unixd_module modules/mod_unixd.so<IfModule ssl_module> SSLRandomSeed startup builtin SSLRandomSeed connect builtin</IfModule><IfModule unixd_module> User daemon Group daemon</IfModule>ServerAdmin you@example.comErrorLog /proc/self/fd/2LogLevel warn<IfModule log_config_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog /proc/self/fd/1 common</IfModule>ServerRoot "/usr/local/apache2"Listen 5043<Directory /> AllowOverride none Require all denied</Directory><VirtualHost *:5043> ServerName myregistrydomain.com SSLEngine on SSLCertificateFile /usr/local/apache2/conf/domain.crt SSLCertificateKeyFile /usr/local/apache2/conf/domain.key ## SSL settings recommandation from: https://raymii.org/s/tutorials/Strong_SSL_Security_On_Apache2.html # Anti CRIME SSLCompression off # POODLE and other stuff SSLProtocol all -SSLv2 -SSLv3 -TLSv1 # Secure cypher suites SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH SSLHonorCipherOrder on Header always set "Docker-Distribution-Api-Version" "registry/2.0" Header onsuccess set "Docker-Distribution-Api-Version" "registry/2.0" RequestHeader set X-Forwarded-Proto "https" ProxyRequests off ProxyPreserveHost on # no proxy for /error/ (Apache HTTPd errors messages) ProxyPass /error/ ! ProxyPass /v2 http://registry:5000/v2 ProxyPassReverse /v2 http://registry:5000/v2 <Location /v2> Order deny,allow Allow from all AuthName "Registry Authentication" AuthType basic AuthUserFile "/usr/local/apache2/conf/httpd.htpasswd" AuthGroupFile "/usr/local/apache2/conf/httpd.groups" # Read access to authentified users <Limit GET HEAD> Require valid-user </Limit> # Write access to docker-deployer only <Limit POST PUT DELETE PATCH> Require group pusher </Limit> </Location></VirtualHost>EOF# Now, create a password file for "testuser" and "testpassword"docker run --entrypoint htpasswd httpd:2.4 -Bbn testuser testpassword > auth/httpd.htpasswd# Create another one for "testuserpush" and "testpasswordpush"docker run --entrypoint htpasswd httpd:2.4 -Bbn testuserpush testpasswordpush >> auth/httpd.htpasswd# Create your group fileecho"pusher: testuserpush" > auth/httpd.groups# Copy over your certificate filescp domain.crt auth
cp domain.key auth# Now create your compose filecat <<EOF > docker-compose.ymlapache: image: "httpd:2.4" hostname: myregistrydomain.com ports: - 5043:5043 links: - registry:registry volumes: - `pwd`/auth:/usr/local/apache2/confregistry: image: registry:2 ports: - 127.0.0.1:5000:5000 volumes: - `pwd`/data:/var/lib/registryEOF

開始と停止

それでは、スタックを起動しましょう。

docker-compose up -d

「push」するために認証されたユーザ( testuserpushtestpasswordpush を使います)でログインします。それから皆さんのイメージをタグ付けして push します。

docker login myregistrydomain.com:5043
docker tag ubuntu myregistrydomain.com:5043/test
docker push myregistrydomain.com:5043/test

次は「pull だけ」のユーザ( testusertestpassword を使います)でログインし、イメージを pull します。

docker login myregistrydomain.com:5043
docker pull myregistrydomain.com:5043/test

「pull だけ」のユーザは送信(push)できないことを確認します。

docker push myregistrydomain.com:5043/test

参考

Authenticating proxy with apache
https://docs.docker.com/registry/apache/