Yuvipanda has submitted this change and it was merged.
Change subject: docker: Add nginx frontend for registry
......................................................................
docker: Add nginx frontend for registry
- Limits PUT, POST, etc behind auth
- Allows anonymous GET access
- Put in a nginx hack to make it work
Change-Id: I7b9e3b5ff2e9821a7b1da9f4c981efab515dd8bb
---
M modules/docker/manifests/registry.pp
A modules/docker/templates/registry-nginx.conf.erb
M modules/role/manifests/toollabs/docker/registry.pp
3 files changed, 119 insertions(+), 15 deletions(-)
Approvals:
Yuvipanda: Verified; Looks good to me, approved
jenkins-bot: Verified
diff --git a/modules/docker/manifests/registry.pp
b/modules/docker/manifests/registry.pp
index c45d0d4..aba26ad 100644
--- a/modules/docker/manifests/registry.pp
+++ b/modules/docker/manifests/registry.pp
@@ -1,5 +1,8 @@
class docker::registry(
$datapath = '/srv/registry',
+ $allow_push_from,
+ $ssl_certificate_name,
+ $ssl_settings,
){
require_package('docker-registry')
@@ -23,20 +26,9 @@
},
},
'http' => {
- 'addr' => ':443',
+ 'addr' => '127.0.0.1:5000',
'host' => $::fqdn,
- 'tls' => {
- # FIXME: YOU SHOULD FEEL BAD ABOUT HARDCODING
- 'certificate' => '/var/lib/docker-registry/ssl/certs/cert.pem',
- 'key' =>
'/var/lib/docker-registry/ssl/private_keys/server.key'
- },
},
- 'auth' => {
- 'htpasswd' => {
- 'realm' => 'docker-auth',
- 'path' => '/etc/docker/registry/htpasswd',
- }
- }
}
file { $datapath:
@@ -57,8 +49,8 @@
$docker_password_hash = hiera('docker::password_hash')
file { '/etc/docker/registry/htpasswd':
content => "${docker_username}:${docker_password_hash}",
- owner => 'docker-registry',
- group => 'docker-registry',
+ owner => 'www-data',
+ group => 'www-data',
mode => '0440',
notify => Service['docker-registry'],
}
@@ -86,4 +78,7 @@
'/etc/docker/registry/config.yml'
]
}
+ nginx::site { 'registry':
+ content => template('docker/registry-nginx.conf.erb'),
+ }
}
diff --git a/modules/docker/templates/registry-nginx.conf.erb
b/modules/docker/templates/registry-nginx.conf.erb
new file mode 100644
index 0000000..8a87839
--- /dev/null
+++ b/modules/docker/templates/registry-nginx.conf.erb
@@ -0,0 +1,99 @@
+upstream registry {
+ server 127.0.0.1:5000;
+}
+
+map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+}
+
+server {
+ listen 443 default_server ssl;
+ ssl_certificate /etc/ssl/localcerts/<%= @ssl_certificate_name
%>.chained.crt;
+ ssl_certificate_key /etc/ssl/private/<%= @ssl_certificate_name %>.key;
+
+ # Copied from modules/tlsproxy/templates/nginx.conf.erb. Eugh
+ # Enable a shared cache, since it is defined at this level
+ # it will be used for all virtual hosts. 1m = 4000 active sessions,
+ # so we are allowing 200,000 active sessions.
+ ssl_session_cache shared:SSL:50m;
+ ssl_session_timeout 5m;
+
+ <%= @ssl_settings.join("\n") %>
+
+ # Images can be pretty large!
+ client_max_body_size 0;
+
+ # Avoids 411 errors!
+ chunked_transfer_encoding on;
+
+ # Tell everyone we're v2, not v1!
+ add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
+
+ # Let me prefix by saying that the Docker v2 registry protocol apparently
+ # is much better than the v1 protocol. I have not read enough about both
+ # to make a comparative analysis, but I can tell that the auth design for
+ # v2 is just terribly done!
+ #
+ # So for a v2 to client to decide if it needs to authenticate or not, it
+ # first makes a GET request to /v2/, and based on wether it gets back a 2xx
+ # or a 401, decides to authenticate for all other requests in that session.
+ # This practically means it is really hard to do something like restrict
+ # write access to only a certain group while allowing read access to other
+ # groups - since it categorizes the whole registry based on the response
+ # code of one endpoint....
+ #
+ # I have hacked around this in the following manner:
+ # - Tell nginx that you can be whitelisted by IP or by specifying a
password
+ # - Whitelist the whole world!
+ # - Blacklist the one IP that needs to specify password (to push)
+ #
+ # This causes nginx to return a 401 only to the IP that I want to push, and
+ # since this IP will have the password it'll be able to authenticate. The
+ # rest of the world will just be allowed via IP, and hence not be asked for
+ # passwords.
+ #
+ # This special case handling is only for the root endpoint - all other
endpoints
+ # are handled in the location stanza below this, and require
authentication for
+ # POST/PUT/DELETE etc. We're only doing this special hack to convince the
+ # docker client to send/not send basic auth credentials depending on what
we
+ # want them to do.
+ #
+ # Fuck you docker.
+ location = /v2/ {
+ satisfy any;
+
+ deny <%= @allow_push_from %>;
+ allow all;
+
+ auth_basic "docker-registry";
+ auth_basic_user_file /etc/docker/registry/htpasswd;
+
+ proxy_pass http://registry;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ }
+
+ location /v2 {
+ # Require auth for POST, PUT, DELETE, ... requests
+ limit_except GET HEAD OPTIONS {
+ auth_basic "docker-registry";
+ auth_basic_user_file /etc/docker/registry/htpasswd;
+ }
+
+ add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
+
+ proxy_pass http://registry;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Proxy-Connection "Keep-Alive";
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Host $host;
+ }
+}
diff --git a/modules/role/manifests/toollabs/docker/registry.pp
b/modules/role/manifests/toollabs/docker/registry.pp
index c8a71ed..1c7fa45 100644
--- a/modules/role/manifests/toollabs/docker/registry.pp
+++ b/modules/role/manifests/toollabs/docker/registry.pp
@@ -3,7 +3,17 @@
require role::labs::lvm::srv
+ sslcert::certificate { 'star.tools.wmflabs.org':
+ skip_private => true,
+ before => Class['::docker::registry'],
+ }
+
+ $builder = ipresolve(hiera('docker::builder_host'), 4, $::nameservers[0])
+
class { '::docker::registry':
- datapath => '/srv/registry',
+ datapath => '/srv/registry',
+ allow_push_from => $builder,
+ ssl_certificate_name => 'star.tools.wmflabs.org',
+ ssl_settings => ssl_ciphersuite('nginx', 'compat'),
}
}
--
To view, visit https://gerrit.wikimedia.org/r/281998
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I7b9e3b5ff2e9821a7b1da9f4c981efab515dd8bb
Gerrit-PatchSet: 10
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Yuvipanda <[email protected]>
Gerrit-Reviewer: Yuvipanda <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits