OSDN Git Service

adds a reverse proxy (nginx) service with SSL setup feature to the `apt_utils::aptly... apt_utils-0.2.3
authorwhitestar <whitestar@users.osdn.me>
Wed, 26 Jul 2017 12:47:35 +0000 (21:47 +0900)
committerwhitestar <whitestar@users.osdn.me>
Wed, 26 Jul 2017 12:47:35 +0000 (21:47 +0900)
cookbooks/apt_utils/CHANGELOG.md
cookbooks/apt_utils/README.md
cookbooks/apt_utils/attributes/default.rb
cookbooks/apt_utils/recipes/aptly-docker-compose.rb
cookbooks/apt_utils/templates/default/opt/docker-compose/app/aptly/etc/nginx/nginx.conf [new file with mode: 0644]
cookbooks/apt_utils/version

index 938c6be..81ed379 100644 (file)
@@ -1,6 +1,10 @@
 apt_utils CHANGELOG
 ===================
 
+0.2.3
+-----
+- adds a reverse proxy (nginx) service with SSL setup feature to the `apt_utils::aptly-docker-compose` recipe.
+
 0.2.2
 -----
 - adds the `apt_utils::aptly-docker-compose` recipe.
index e337a43..c6a1626 100644 (file)
@@ -14,6 +14,7 @@ This cookbook includes apt utility (apt-cacher-ng, apt mirroring site setup and
         - [apt_utils::apt](#apt_utilsapt)
         - [apt_utils::aptly](#apt_utilsaptly)
         - [apt_utils::aptly-docker-compose](#apt_utilsaptly-docker-compose)
+            - [SSL server keys and certificates management by the `ssl_cert` cookbook](#ssl-server-keys-and-certificates-management-by-the-ssl_cert-cookbook)
         - [apt_utils::conf](#apt_utilsconf)
         - [apt_utils::apt-cacher-ng](#apt_utilsapt-cacher-ng)
         - [apt_utils::mirror](#apt_utilsmirror)
@@ -44,7 +45,10 @@ This cookbook includes apt utility (apt-cacher-ng, apt mirroring site setup and
 |`['apt_utils']['aptly']['apt_repo']['recv-keys']`|String||`'9E3E53F19C7DE460'`|
 |`['apt_utils']['aptly']['user']`|String||`'root'`|
 |`['apt_utils']['aptly']['conf']`|Hash|`aptly.conf` configurations.|See `attributes/default.rb`|
+|`['apt_utils']['aptly']['with_ssl_cert_cookbook']`|Boolean|Activates TLS configurations by the `ssl_cert` cookbook. See `attributes/default.rb`|`false`|
+|`['apt_utils']['aptly']['ssl_cert']['common_name']`|String|Server common name for TLS|`node['fqdn']`|
 |`['apt_utils']['aptly']['docker-compose']['app_dir']`|String|aptly app. root directory for docker-compose.|`"#{node['docker-grid']['compose']['app_dir']}/aptly"`|
+|`['apt_utils']['aptly']['docker-compose']['etc_dir']`|String||`"#{node['apt_utils']['aptly']['docker-compose']['app_dir']}/etc"`|
 |`['apt_utils']['aptly']['docker-compose']['data_dir']`|String|Persistent volume path or nil (unset).|`"#{node['apt_utils']['aptly']['docker-compose']['app_dir']}/data"`|
 |`['apt_utils']['aptly']['docker-compose']['config']`|Hash|`docker-compose.yml` configurations.|See `attributes/default.rb`|
 |`['apt_utils']['apt-cacher-ng']['CacheDir']`|String|path to cache directory|`'/var/cache/apt-cacher-ng'`|
@@ -110,14 +114,81 @@ override_attributes(
         'config' => {
           'version' => '2',
           'services' => {
+            'reverseproxy' => {
+              'ports' => [
+                "#{aptly_port}:8080",
+                "#{aptly_api_port}:8081",
+              ],
+              'volumes' => [
+                # This volume will be set by the apt_utils::aptly-docker-compose recipe automatically.
+                #"#{node['apt_utils']['aptly']['docker-compose']['etc_dir']}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
+              ],
+            },
             'aptly' => {
               'restart' => 'always',
               'image' => 'whitestar/aptly',
+              'volumes' => [
+                # This volume will be set by the apt_utils::aptly-docker-compose recipe automatically.
+                #"#{node['apt_utils']['aptly']['docker-compose']['data_dir']}:/aptly-data:rw",
+              ],
+              'environment' => {
+              },
+            },
+          },
+        },
+      },
+    },
+  },
+)
+```
+
+- `roles/aptly-with-ssl-docker-compose.rb`: SSL setup role example.
+
+```ruby
+name 'aptly-with-ssl-docker-compose'
+description 'aptly with SSL by docker-compose'
+
+run_list(
+  'recipe[ssl_cert::server_key_pairs]',
+  'role[docker]',
+  'recipe[apt_utils::aptly-docker-compose]',
+)
+
+aptly_port = '8080'
+aptly_api_port = '8081'
+cn = 'aptly.io.example.com'
+
+override_attributes(
+  'ssl_cert' => {
+    'common_names' => [
+      cn,
+    ],
+  },
+  'apt_utils' => {
+    'aptly' => {
+      'with_ssl_cert_cookbook' => true,
+      'ssl_cert' => {
+        'common_name' => cn,
+      },
+      'docker-compose' => {
+        'config' => {
+          'version' => '2',
+          'services' => {
+            'reverseproxy' => {
               'ports' => [
                 "#{aptly_port}:8080",
                 "#{aptly_api_port}:8081",
               ],
               'volumes' => [
+                # These volumes will be set by the apt_utils::aptly-docker-compose recipe automatically.
+                #"#{node['apt_utils']['aptly']['docker-compose']['etc_dir']}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
+                # and server key pair volume conf.
+              ],
+            },
+            'aptly' => {
+              'restart' => 'always',
+              'image' => 'whitestar/aptly',
+              'volumes' => [
                 # This volume will be set by the apt_utils::aptly-docker-compose recipe automatically.
                 #"#{node['apt_utils']['aptly']['docker-compose']['data_dir']}:/aptly-data:rw",
               ],
@@ -132,6 +203,57 @@ override_attributes(
 )
 ```
 
+##### SSL server keys and certificates management by the `ssl_cert` cookbook
+
+- create vault items.
+
+```text
+$ ruby -rjson -e 'puts JSON.generate({"private" => File.read("aptly.io.example.com.prod.key")})' \
+> > ~/tmp/aptly.io.example.com.prod.key.json
+
+$ ruby -rjson -e 'puts JSON.generate({"public" => File.read("aptly.io.example.com.prod.crt")})' \
+> > ~/tmp/aptly.io.example.com.prod.crt.json
+
+$ cd $CHEF_REPO_PATH
+
+$ knife vault create ssl_server_keys aptly.io.example.com.prod \
+> --json ~/tmp/aptly.io.example.com.prod.key.json
+
+$ knife vault create ssl_server_certs aptly.io.example.com.prod \
+> --json ~/tmp/aptly.io.example.com.prod.crt.json
+```
+
+- grant reference permission to the Concourse host
+
+```text
+$ knife vault update ssl_server_keys  aptly.io.example.com.prod -S 'name:aptly-host.example.com'
+$ knife vault update ssl_server_certs aptly.io.example.com.prod -S 'name:aptly-host.example.com'
+```
+
+- modify run_list and attributes
+
+```ruby
+run_list(
+  'recipe[ssl_cert::server_key_pairs]',
+  'recipe[apt_utils::aptly-docker-compose]',
+)
+
+override_attributes(
+  'ssl_cert' => {
+    'common_names' => [
+      'aptly.io.example.com',
+    ],
+  },
+  'aptly-grid' => {
+    'with_ssl_cert_cookbook' => true,
+    'ssl_cert' => {
+      'common_name' => 'nexus.io.example.com',
+    },
+    # ...
+  },
+)
+```
+
 #### apt_utils::conf
 
 - deploys apt configuration files to the `/etc/apt/apt.conf.d` directory.
index 734a02a..fe6dd59 100644 (file)
@@ -38,6 +38,12 @@ default['apt_utils']['source']['apt_lines'] = [
   #'deb http://ftp.grid.example.com:3142/security.debian.org/ wheezy/updates main contrib non-free'
 ]
 
+default['apt_utils']['aptly']['with_ssl_cert_cookbook'] = false
+# If ['apt_utils']['aptly']['with_ssl_cert_cookbook'] is true,
+# node['apt_utils']['aptly']['docker-compose']['config']
+# are overridden by the following 'common_name' attributes.
+default['apt_utils']['aptly']['ssl_cert']['ca_names'] = []
+default['apt_utils']['aptly']['ssl_cert']['common_name'] = node['fqdn']
 default['apt_utils']['aptly']['apt_repo'] = {
   'keyserver' => 'keys.gnupg.net',
   'recv-keys' => '9E3E53F19C7DE460',
@@ -65,15 +71,36 @@ default['apt_utils']['aptly']['conf'] = {
   'SwiftPublishEndpoints' => {},
 }
 default['apt_utils']['aptly']['docker-compose']['app_dir'] = "#{node['docker-grid']['compose']['app_dir']}/aptly"
+default['apt_utils']['aptly']['docker-compose']['etc_dir'] = "#{node['apt_utils']['aptly']['docker-compose']['app_dir']}/etc"
 default['apt_utils']['aptly']['docker-compose']['data_dir'] = "#{node['apt_utils']['aptly']['docker-compose']['app_dir']}/data"
 force_override['apt_utils']['aptly']['docker-compose']['config_format_version'] = '2'
 version_2_config = {
   # Version 2 docker-compose format
   'version' => '2',
   'services' => {
+    'reverseproxy' => {
+      'depends_on' => [
+        'aptly',
+      ],
+      'restart' => 'always',
+      'image' => 'nginx:alpine',
+      'expose' => [
+        '8080',
+        '8081',
+      ],
+      'ports' => [
+        #'8080:8080',  # distribution service
+        #'8081:8081',  # API service
+      ],
+      'volumes' => [
+        # This volume will be set by the apt_utils::aptly-docker-compose recipe automatically.
+        #"#{node['apt_utils']['aptly']['docker-compose']['etc_dir']}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
+      ],
+    },
     'aptly' => {
       'restart' => 'always',
       'image' => 'whitestar/aptly',
+      # -> reverseproxy
       'ports' => [
         #'8080:8080',  # distribution service
         #'8081:8081',  # API service
index c6297ea..ab329fd 100644 (file)
@@ -17,8 +17,6 @@
 # limitations under the License.
 #
 
-#::Chef::Recipe.send(:include, SSLCert::Helper)
-
 doc_url = 'https://www.aptly.info/doc/overview/'
 
 include_recipe 'platform_utils::kernel_user_namespace'
@@ -26,11 +24,12 @@ include_recipe 'docker-grid::compose'
 
 app_dir = node['apt_utils']['aptly']['docker-compose']['app_dir']
 data_dir = node['apt_utils']['aptly']['docker-compose']['data_dir']
-etc_dir = "#{app_dir}/etc"
+etc_dir = node['apt_utils']['aptly']['docker-compose']['etc_dir']
 
 [
   app_dir,
   etc_dir,
+  "#{etc_dir}/nginx",
 ].each {|dir|
   resources(directory: dir) rescue directory dir do
     owner 'root'
@@ -45,9 +44,23 @@ override_aptly_conf = node.override['apt_utils']['aptly']['conf']
 config_srvs = node['apt_utils']['aptly']['docker-compose']['config']['services']
 override_config_srvs = node.override['apt_utils']['aptly']['docker-compose']['config']['services']
 #force_override_config_srvs = node.force_override['apt_utils']['aptly']['docker-compose']['config']['services']
-#envs_org = config_srvs['aptly']['environment']
-#envs = {}
-vols = config_srvs['aptly']['volumes'].to_a
+#aptly_envs_org = config_srvs['aptly']['environment']
+#aptly_envs = {}
+rproxy_vols = config_srvs['reverseproxy']['volumes'].to_a
+aptly_vols = config_srvs['aptly']['volumes'].to_a
+
+ports = config_srvs['reverseproxy']['ports']
+override_config_srvs['reverseproxy']['ports'] = ['8080:8080', '8081:8081'] if ports.empty?
+
+template "#{etc_dir}/nginx/nginx.conf" do
+  source 'opt/docker-compose/app/aptly/etc/nginx/nginx.conf'
+  owner 'root'
+  group 'root'
+  mode '0644'
+  action :create
+end
+
+rproxy_vols.push("#{etc_dir}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro")
 
 override_aptly_conf['rootDir'] = '/aptly-data'
 template "#{etc_dir}/aptly.conf" do
@@ -58,7 +71,7 @@ template "#{etc_dir}/aptly.conf" do
   action :create
 end
 
-vols.push("#{etc_dir}/aptly.conf:/etc/aptly.conf:rw")
+aptly_vols.push("#{etc_dir}/aptly.conf:/etc/aptly.conf:rw")
 
 # Data persistent
 if !data_dir.nil? && !data_dir.empty?
@@ -69,16 +82,22 @@ if !data_dir.nil? && !data_dir.empty?
     recursive true
   end
 
-  vols.push("#{data_dir}:/aptly-data:rw")
+  aptly_vols.push("#{data_dir}:/aptly-data:rw")
 end
 
-ports = config_srvs['aptly']['ports']
-override_config_srvs['aptly']['ports'] = ['8080:8080', '8081:8081'] if ports.empty?
+if node['apt_utils']['aptly']['with_ssl_cert_cookbook']
+  ::Chef::Recipe.send(:include, SSLCert::Helper)
+  cn = node['apt_utils']['aptly']['ssl_cert']['common_name']
+  # Concourse web process owner is root.
+  rproxy_vols.push("#{server_cert_path(cn)}:/root/server.crt:ro")
+  rproxy_vols.push("#{server_key_path(cn)}:/root/server.key:ro")
+end
 
 # merge environment hash
-#force_override_config_srvs['aptly']['environment'] = envs unless envs.empty?
+#force_override_config_srvs['aptly']['environment'] = envs unless aptly_envs.empty?
 # reset vlumes array.
-override_config_srvs['aptly']['volumes'] = vols unless vols.empty?
+override_config_srvs['reverseproxy']['volumes'] = rproxy_vols unless rproxy_vols.empty?
+override_config_srvs['aptly']['volumes'] = aptly_vols unless aptly_vols.empty?
 
 config_file = "#{app_dir}/docker-compose.yml"
 template config_file do
diff --git a/cookbooks/apt_utils/templates/default/opt/docker-compose/app/aptly/etc/nginx/nginx.conf b/cookbooks/apt_utils/templates/default/opt/docker-compose/app/aptly/etc/nginx/nginx.conf
new file mode 100644 (file)
index 0000000..63df0d9
--- /dev/null
@@ -0,0 +1,66 @@
+<%
+ssl_enabled = node['apt_utils']['aptly']['with_ssl_cert_cookbook']
+-%>
+worker_processes 1;
+
+events {
+  worker_connections 1024;
+}
+
+http {
+  sendfile on;
+
+  upstream docker-aptly {
+    server aptly:8080;
+  }
+
+  upstream docker-aptly-api {
+    server aptly:8081;
+  }
+
+  server {
+<% if ssl_enabled %>
+    listen 8080 default ssl;
+    ssl on;
+    ssl_certificate      /root/server.crt;
+    ssl_certificate_key  /root/server.key;
+<% else %>
+    listen 8080;
+<% end %>
+
+    location / {
+      proxy_pass         http://docker-aptly;
+      proxy_redirect     off;
+      proxy_set_header   Host $http_host;  # $host does not include the port number.
+      proxy_set_header   X-Real-IP $remote_addr;
+<% if ssl_enabled %>
+      proxy_set_header   X-Forwarded-Proto https;
+<% end %>
+      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header   X-Forwarded-Host $server_name;
+    }
+  }
+
+  server {
+<% if ssl_enabled %>
+    listen 8081 default ssl;
+    ssl on;
+    ssl_certificate      /root/server.crt;
+    ssl_certificate_key  /root/server.key;
+<% else %>
+    listen 8081;
+<% end %>
+
+    location / {
+      proxy_pass         http://docker-aptly-api;
+      proxy_redirect     off;
+      proxy_set_header   Host $http_host;  # $host does not include the port number.
+      proxy_set_header   X-Real-IP $remote_addr;
+<% if ssl_enabled %>
+      proxy_set_header   X-Forwarded-Proto https;
+<% end %>
+      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header   X-Forwarded-Host $server_name;
+    }
+  }
+}