github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/docs/apache.md (about) 1 <!--[metadata]> 2 +++ 3 title = "Authenticating proxy with apache" 4 description = "Restricting access to your registry using an apache proxy" 5 keywords = ["registry, on-prem, images, tags, repository, distribution, authentication, proxy, apache, httpd, TLS, recipe, advanced"] 6 +++ 7 <![end-metadata]--> 8 9 # Authenticating proxy with apache 10 11 ## Use-case 12 13 People already relying on an apache proxy to authenticate their users to other services might want to leverage it and have Registry communications tunneled through the same pipeline. 14 15 Usually, that includes enterprise setups using LDAP/AD on the backend and a SSO mechanism fronting their internal http portal. 16 17 ### Alternatives 18 19 If you just want authentication for your registry, and are happy maintaining users access separately, you should really consider sticking with the native [basic auth registry feature](deploying.md#native-basic-auth). 20 21 ### Solution 22 23 With the method presented here, you implement basic authentication for docker engines in a reverse proxy that sits in front of your registry. 24 25 While we use a simple htpasswd file as an example, any other apache authentication backend should be fairly easy to implement once you are done with the exemple. 26 27 We also implement push restriction (to a limited user group) for the sake of the exemple. Again, you should modify this to fit your mileage. 28 29 ### Gotchas 30 31 While this model gives you the ability to use whatever authentication backend you want through the secondary authentication mechanism implemented inside your proxy, it also requires that you move TLS termination from the Registry to the proxy itself. 32 33 Furthermore, introducing an extra http layer in your communication pipeline will make it more complex to deploy, maintain, and debug, and will possibly create issues. 34 35 ## Setting things up 36 37 Read again [the requirements](recipes.md#requirements). 38 39 Ready? 40 41 Run the following script: 42 43 ``` 44 mkdir -p auth 45 mkdir -p data 46 47 # This is the main apache configuration you will use 48 cat <<EOF > auth/httpd.conf 49 LoadModule headers_module modules/mod_headers.so 50 51 LoadModule authn_file_module modules/mod_authn_file.so 52 LoadModule authn_core_module modules/mod_authn_core.so 53 LoadModule authz_groupfile_module modules/mod_authz_groupfile.so 54 LoadModule authz_user_module modules/mod_authz_user.so 55 LoadModule authz_core_module modules/mod_authz_core.so 56 LoadModule auth_basic_module modules/mod_auth_basic.so 57 LoadModule access_compat_module modules/mod_access_compat.so 58 59 LoadModule log_config_module modules/mod_log_config.so 60 61 LoadModule ssl_module modules/mod_ssl.so 62 63 LoadModule proxy_module modules/mod_proxy.so 64 LoadModule proxy_http_module modules/mod_proxy_http.so 65 66 LoadModule unixd_module modules/mod_unixd.so 67 68 <IfModule ssl_module> 69 SSLRandomSeed startup builtin 70 SSLRandomSeed connect builtin 71 </IfModule> 72 73 <IfModule unixd_module> 74 User daemon 75 Group daemon 76 </IfModule> 77 78 ServerAdmin you@example.com 79 80 ErrorLog /proc/self/fd/2 81 82 LogLevel warn 83 84 <IfModule log_config_module> 85 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 86 LogFormat "%h %l %u %t \"%r\" %>s %b" common 87 88 <IfModule logio_module> 89 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio 90 </IfModule> 91 92 CustomLog /proc/self/fd/1 common 93 </IfModule> 94 95 ServerRoot "/usr/local/apache2" 96 97 Listen 5043 98 99 <Directory /> 100 AllowOverride none 101 Require all denied 102 </Directory> 103 104 <VirtualHost *:5043> 105 106 ServerName myregistrydomain.com 107 108 SSLEngine on 109 SSLCertificateFile /usr/local/apache2/conf/domain.crt 110 SSLCertificateKeyFile /usr/local/apache2/conf/domain.key 111 112 ## SSL settings recommandation from: https://raymii.org/s/tutorials/Strong_SSL_Security_On_Apache2.html 113 # Anti CRIME 114 SSLCompression off 115 116 # POODLE and other stuff 117 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 118 119 # Secure cypher suites 120 SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH 121 SSLHonorCipherOrder on 122 123 Header always set "Docker-Distribution-Api-Version" "registry/2.0" 124 Header onsuccess set "Docker-Distribution-Api-Version" "registry/2.0" 125 RequestHeader set X-Forwarded-Proto "https" 126 127 ProxyRequests off 128 ProxyPreserveHost on 129 130 # no proxy for /error/ (Apache HTTPd errors messages) 131 ProxyPass /error/ ! 132 133 ProxyPass /v2 http://registry:5000/v2 134 ProxyPassReverse /v2 http://registry:5000/v2 135 136 <Location /v2> 137 Order deny,allow 138 Allow from all 139 AuthName "Registry Authentication" 140 AuthType basic 141 AuthUserFile "/usr/local/apache2/conf/httpd.htpasswd" 142 AuthGroupFile "/usr/local/apache2/conf/httpd.groups" 143 144 # Read access to authentified users 145 <Limit GET HEAD> 146 Require valid-user 147 </Limit> 148 149 # Write access to docker-deployer only 150 <Limit POST PUT DELETE PATCH> 151 Require group pusher 152 </Limit> 153 154 </Location> 155 156 </VirtualHost> 157 EOF 158 159 # Now, create a password file for "testuser" and "testpassword" 160 docker run --entrypoint htpasswd httpd:2.4 -Bbn testuser testpassword > auth/httpd.htpasswd 161 # Create another one for "testuserpush" and "testpasswordpush" 162 docker run --entrypoint htpasswd httpd:2.4 -Bbn testuserpush testpasswordpush >> auth/httpd.htpasswd 163 164 # Create your group file 165 echo "pusher: testuserpush" > auth/httpd.groups 166 167 # Copy over your certificate files 168 cp domain.crt auth 169 cp domain.key auth 170 171 # Now create your compose file 172 173 cat <<EOF > docker-compose.yml 174 apache: 175 image: "httpd:2.4" 176 hostname: myregistrydomain.com 177 ports: 178 - 5043:5043 179 links: 180 - registry:registry 181 volumes: 182 - `pwd`/auth:/usr/local/apache2/conf 183 184 registry: 185 image: registry:2 186 ports: 187 - 127.0.0.1:5000:5000 188 volumes: 189 - `pwd`/data:/var/lib/registry 190 191 EOF 192 ``` 193 194 ## Starting and stopping 195 196 Now, start your stack: 197 198 docker-compose up -d 199 200 Login with a "push" authorized user (using `testuserpush` and `testpasswordpush`), then tag and push your first image: 201 202 docker login myregistrydomain.com:5043 203 docker tag ubuntu myregistrydomain.com:5043/test 204 docker push myregistrydomain.com:5043/test 205 206 Now, login with a "pull-only" user (using `testuser` and `testpassword`), then pull back the image: 207 208 docker login myregistrydomain.com:5043 209 docker pull myregistrydomain.com:5043/test 210 211 Verify that the "pull-only" can NOT push: 212 213 docker push myregistrydomain.com:5043/test