Grid環境構築用のChefリポジトリです。
Revision | 6b42ef0c159737e79a4cd63c9d82a73bbb572a24 (tree) |
---|---|
Zeit | 2017-02-26 18:27:26 |
Autor | whitestar <whitestar@gaea...> |
Commiter | whitestar |
adds the ['concourse-ci']['docker-compose']['web_oauth_client_(id|secret)_vault_item'] attributes.
@@ -1,6 +1,11 @@ | ||
1 | 1 | concourse-ci CHANGELOG |
2 | 2 | ====================== |
3 | 3 | |
4 | +0.1.6 | |
5 | +----- | |
6 | +- adds CA certificates import feature. | |
7 | +- adds the `['concourse-ci']['docker-compose']['web_oauth_client_(id|secret)_vault_item']` attributes. | |
8 | + | |
4 | 9 | 0.1.5 |
5 | 10 | ----- |
6 | 11 | - adds the `concourse-ci::fly` recipe. |
@@ -17,6 +17,7 @@ This cookbook sets up a Concourse CI service by Docker Compose. | ||
17 | 17 | - [concourse-ci::docker-compose](#concourse-cidocker-compose) |
18 | 18 | - [Role Examples](#role-examples) |
19 | 19 | - [SSL server keys and certificates management by ssl_cert cookbook](#ssl-server-keys-and-certificates-management-by-ssl_cert-cookbook) |
20 | + - [OAuth client ID and secret management by Chef Vault](#oauth-client-id-and-secret-management-by-chef-vault) | |
20 | 21 | - [License and Authors](#license-and-authors) |
21 | 22 | |
22 | 23 | ## Requirements |
@@ -40,6 +41,10 @@ This cookbook sets up a Concourse CI service by Docker Compose. | ||
40 | 41 | |`['concourse-ci']['fly']['release_checksum']`|String||`nil`| |
41 | 42 | |`['concourse-ci']['fly']['auto_upgrade']`|Boolean||`false`| |
42 | 43 | |`['concourse-ci']['fly']['install_path']`|String||`'/usr/local/bin/fly'`| |
44 | +|`['concourse-ci']['with_ssl_cert_cookbook']`|Boolean|See `attributes/default.rb`|`false`| | |
45 | +|`['concourse-ci']['ssl_cert']['ca_names']`|Array|Internal CA names that are imported by the ssl_cert cookbook.|`[]`| | |
46 | +|`['concourse-ci']['ssl_cert']['common_name']`|String|Server common name for TLS|`node['fqdn']`| | |
47 | +|`['concourse-ci']['docker-compose']['import_ca']`|Boolean|whether import internal CA certificates or not.|`false`| | |
43 | 48 | |`['concourse-ci']['docker-compose']['app_dir']`|String||`"#{node['docker-grid']['compose']['app_dir']}/concourse"`| |
44 | 49 | |`['concourse-ci']['docker-compose']['pgdata_dir']`|String|Path string or nil (unset).|`"#{node['concourse-ci']['docker-compose']['app_dir']}/database"`| |
45 | 50 | |`['concourse-ci']['docker-compose']['web_keys_dir']`|String|Path string.|`"#{node['concourse-ci']['docker-compose']['app_dir']}/keys/web"`| |
@@ -49,6 +54,8 @@ This cookbook sets up a Concourse CI service by Docker Compose. | ||
49 | 54 | |`['concourse-ci']['docker-compose']['db_password_vault_item']`|Hash|See `attributes/default.rb`|`{}`| |
50 | 55 | |`['concourse-ci']['docker-compose']['web_password_reset']`|String|Only available if the password is automatically generated by Chef.|`false`| |
51 | 56 | |`['concourse-ci']['docker-compose']['web_password_vault_item']`|Hash|See `attributes/default.rb`|`{}`| |
57 | +|`['concourse-ci']['docker-compose']['web_oauth_client_id_vault_item']`|Hash|See `attributes/default.rb`|`{}`| | |
58 | +|`['concourse-ci']['docker-compose']['web_oauth_client_secret_vault_item']`|Hash|See `attributes/default.rb`|`{}`| | |
52 | 59 | |`['concourse-ci']['docker-compose']['ssh_keys_reset']`|String|Resets all SSH keys forcely.|`false`| |
53 | 60 | |`['concourse-ci']['docker-compose']['config_format_version']`|String|Read only. `docker-compose.yml` format version. Only version 1 is supported now.|`'1'`| |
54 | 61 | |`['concourse-ci']['docker-compose']['config']`|Hash|`docker-compose.yml` configurations.|See `attributes/default.rb`| |
@@ -178,6 +185,82 @@ override_attributes( | ||
178 | 185 | ) |
179 | 186 | ``` |
180 | 187 | |
188 | +- `roles/concourse-with-oauth.rb` | |
189 | + | |
190 | +```ruby | |
191 | +name 'concourse-with-oauth' | |
192 | +description 'Concourse with OAuth' | |
193 | + | |
194 | +run_list( | |
195 | + 'recipe[ssl_cert::ca_certs]', | |
196 | + 'recipe[ssl_cert::server_key_pairs]', | |
197 | + 'role[docker]', | |
198 | + 'recipe[concourse-ci::docker-compose]', | |
199 | +) | |
200 | + | |
201 | +image = 'concourse/concourse:2.7.0' | |
202 | +port = '18443' | |
203 | +ca_name = 'grid_ca' | |
204 | +cn = 'concourse.io.example.com' | |
205 | +gitlab_cn = 'gitlab.io.example.com' | |
206 | + | |
207 | +override_attributes( | |
208 | + 'ssl_cert' => { | |
209 | + 'ca_names' => [ | |
210 | + ca_name, | |
211 | + ], | |
212 | + 'common_names' => [ | |
213 | + cn, | |
214 | + ], | |
215 | + }, | |
216 | + 'concourse-ci' => { | |
217 | + 'with_ssl_cert_cookbook' => true, | |
218 | + 'ssl_cert' => { | |
219 | + 'ca_names' => [ | |
220 | + ca_name, | |
221 | + ], | |
222 | + 'common_name' => cn, | |
223 | + }, | |
224 | + 'docker-compose' => { | |
225 | + 'import_ca' => true, | |
226 | + 'web_oauth_client_id_vault_item' => { | |
227 | + 'vault' => 'concourse', | |
228 | + 'name' => 'web_oauth_client_id', | |
229 | + 'env_context' => false, | |
230 | + 'key' => 'cid', | |
231 | + }, | |
232 | + 'web_oauth_client_secret_vault_item' => { | |
233 | + 'vault' => 'concourse', | |
234 | + 'name' => 'web_oauth_client_secret', | |
235 | + 'env_context' => false, | |
236 | + 'key' => 'secret', | |
237 | + }, | |
238 | + 'config' => { | |
239 | + # Version 1 docker-compose format | |
240 | + 'concourse-web' => { | |
241 | + 'ports' => [ | |
242 | + #'4080:8080', | |
243 | + "#{port}:8443", | |
244 | + ], | |
245 | + 'environment' => { | |
246 | + 'CONCOURSE_TLS_BIND_PORT' => '8443', | |
247 | + 'CONCOURSE_EXTERNAL_URL' => "https://#{cn}:#{port}", | |
248 | + # OAuth for the default `main`` team | |
249 | + 'CONCOURSE_GENERIC_OAUTH_DISPLAY_NAME' => 'GitLab', | |
250 | + # The following 2 variables are set automatically, | |
251 | + # if the ['concourse-ci']['docker-compose']['web_oauth_client_(id|secret)_vault_item'] attributes are specified. | |
252 | + #'CONCOURSE_GENERIC_OAUTH_CLIENT_ID' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_ID}', | |
253 | + #'CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET}', | |
254 | + 'CONCOURSE_GENERIC_OAUTH_AUTH_URL' => "https://#{gitlab_cn}/oauth/authorize", | |
255 | + 'CONCOURSE_GENERIC_OAUTH_TOKEN_URL' => "https://#{gitlab_cn}/oauth/token", | |
256 | + }, | |
257 | + }, | |
258 | + }, | |
259 | + }, | |
260 | + }, | |
261 | +) | |
262 | +``` | |
263 | + | |
181 | 264 | ### SSL server keys and certificates management by ssl_cert cookbook |
182 | 265 | |
183 | 266 | - create vault items. |
@@ -186,12 +269,14 @@ override_attributes( | ||
186 | 269 | $ ruby -rjson -e 'puts JSON.generate({"private" => File.read("concourse_io_example_com.prod.key")})' \ |
187 | 270 | > > ~/tmp/concourse_io_example_com.prod.key.json |
188 | 271 | |
189 | -$ knife vault create ssl_server_keys concourse.io.example.com.prod \ | |
190 | -> --json ~/tmp/concourse_io_example_com.prod.key.json | |
191 | - | |
192 | 272 | $ ruby -rjson -e 'puts JSON.generate({"public" => File.read("concourse_io_example_com.prod.crt")})' \ |
193 | 273 | > > ~/tmp/concourse_io_example_com.prod.crt.json |
194 | 274 | |
275 | +$ cd $CHEF_REPO_PATH | |
276 | + | |
277 | +$ knife vault create ssl_server_keys concourse.io.example.com.prod \ | |
278 | +> --json ~/tmp/concourse_io_example_com.prod.key.json | |
279 | + | |
195 | 280 | $ knife vault create ssl_server_certs concourse.io.example.com.prod \ |
196 | 281 | > --json ~/tmp/concourse_io_example_com.prod.crt.json |
197 | 282 | ``` |
@@ -227,6 +312,52 @@ override_attributes( | ||
227 | 312 | ) |
228 | 313 | ``` |
229 | 314 | |
315 | +### OAuth client ID and secret management by Chef Vault | |
316 | + | |
317 | +- create vault items. | |
318 | + | |
319 | +```text | |
320 | +$ cat ~/tmp/concourse_oauth_client_id.json | |
321 | +{"cid":"***************************************************************"} | |
322 | +$ cat ~/tmp/concourse_oauth_client_secret.json | |
323 | +{"secret":"***************************************************************"} | |
324 | + | |
325 | +$ knife vault create concourse web_oauth_client_id --json ~/tmp/concourse_oauth_client_id.json | |
326 | +$ knife vault create concourse web_oauth_client_secret --json ~/tmp/concourse_oauth_client_secret.json | |
327 | +``` | |
328 | + | |
329 | +- grant reference permission to the Concourse host | |
330 | + | |
331 | +```text | |
332 | +$ knife vault update concourse web_oauth_client_id -S 'name:concourse-host.example.com' | |
333 | +$ knife vault update concourse web_oauth_client_secret -S 'name:concourse-host.example.com' | |
334 | +``` | |
335 | + | |
336 | +- modify attributes | |
337 | + | |
338 | +```ruby | |
339 | +override_attributes( | |
340 | + 'concourse-ci' => { | |
341 | + # ... | |
342 | + 'docker-compose' => { | |
343 | + 'web_oauth_client_id_vault_item' => { | |
344 | + 'vault' => 'concourse', | |
345 | + 'name' => 'web_oauth_client_id', | |
346 | + 'env_context' => false, | |
347 | + 'key' => 'cid', | |
348 | + }, | |
349 | + 'web_oauth_client_secret_vault_item' => { | |
350 | + 'vault' => 'concourse', | |
351 | + 'name' => 'web_oauth_client_secret', | |
352 | + 'env_context' => false, | |
353 | + 'key' => 'secret', | |
354 | + }, | |
355 | + # ... | |
356 | + }, | |
357 | + }, | |
358 | +) | |
359 | +``` | |
360 | + | |
230 | 361 | ## License and Authors |
231 | 362 | |
232 | 363 | - Author:: whitestar at osdn.jp |
@@ -27,7 +27,9 @@ default['concourse-ci']['with_ssl_cert_cookbook'] = false | ||
27 | 27 | # If ['concourse-ci']['with_ssl_cert_cookbook'] is true, |
28 | 28 | # node['concourse-ci']['docker-compose']['config'] |
29 | 29 | # are overridden by the following 'common_name' attributes. |
30 | +default['concourse-ci']['ssl_cert']['ca_names'] = [] | |
30 | 31 | default['concourse-ci']['ssl_cert']['common_name'] = node['fqdn'] |
32 | +default['concourse-ci']['docker-compose']['import_ca'] = false | |
31 | 33 | default['concourse-ci']['docker-compose']['app_dir'] = "#{node['docker-grid']['compose']['app_dir']}/concourse" |
32 | 34 | default['concourse-ci']['docker-compose']['pgdata_dir'] = "#{node['concourse-ci']['docker-compose']['app_dir']}/database" |
33 | 35 | default['concourse-ci']['docker-compose']['web_keys_dir'] = "#{node['concourse-ci']['docker-compose']['app_dir']}/keys/web" |
@@ -58,6 +60,30 @@ default['concourse-ci']['docker-compose']['web_password_vault_item'] = { | ||
58 | 60 | #'key' => 'hash/path/to/password', # real hash path: "/#{node.chef_environment}/hash/path/to/password" |
59 | 61 | =end |
60 | 62 | } |
63 | +default['concourse-ci']['docker-compose']['web_oauth_client_id_vault_item'] = { | |
64 | +=begin | |
65 | + 'vault' => 'concourse', | |
66 | + 'name' => 'web_oauth_client_id', | |
67 | + # single cid or nested hash cid path delimited by slash | |
68 | + 'env_context' => false, | |
69 | + 'key' => 'cid', # real hash path: "/cid", Note: do not use `id`, which is preserved by Chef Vault. | |
70 | + # or nested hash id path delimited by slash | |
71 | + #'env_context' => true, | |
72 | + #'key' => 'hash/path/to/cid', # real hash path: "/#{node.chef_environment}/hash/path/to/cid" | |
73 | +=end | |
74 | +} | |
75 | +default['concourse-ci']['docker-compose']['web_oauth_client_secret_vault_item'] = { | |
76 | +=begin | |
77 | + 'vault' => 'concourse', | |
78 | + 'name' => 'web_oauth_client_secret', | |
79 | + # single secret or nested hash secret path delimited by slash | |
80 | + 'env_context' => false, | |
81 | + 'key' => 'secret', # real hash path: "/secret" | |
82 | + # or nested hash secret path delimited by slash | |
83 | + #'env_context' => true, | |
84 | + #'key' => 'hash/path/to/secret', # real hash path: "/#{node.chef_environment}/hash/path/to/secret" | |
85 | +=end | |
86 | +} | |
61 | 87 | default['concourse-ci']['docker-compose']['ssh_keys_reset'] = false |
62 | 88 | |
63 | 89 | # TODO: support version 2 format, and use `default` instead of `force_override` |
@@ -97,6 +123,14 @@ version_1_config = { | ||
97 | 123 | 'CONCOURSE_BASIC_AUTH_USERNAME' => 'concourse', |
98 | 124 | # Note: You should use the `['concourse-ci']['docker-compose']['web_password_vault_item']` attribute. |
99 | 125 | 'CONCOURSE_BASIC_AUTH_PASSWORD' => nil, |
126 | + # OAuth for the default `main`` team | |
127 | + #'CONCOURSE_GENERIC_OAUTH_DISPLAY_NAME' => 'GitLab', | |
128 | + # The following 2 variables are set automatically, | |
129 | + # if the ['concourse-ci']['docker-compose']['web_oauth_client_(id|secret)_vault_item'] attributes are specified. | |
130 | + #'CONCOURSE_GENERIC_OAUTH_CLIENT_ID' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_ID}', | |
131 | + #'CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET}', | |
132 | + #'CONCOURSE_GENERIC_OAUTH_AUTH_URL' => 'https://gitlab.io.example.com/oauth/authorize', | |
133 | + #'CONCOURSE_GENERIC_OAUTH_TOKEN_URL' => 'https://gitlab.io.example.com/oauth/token', | |
100 | 134 | # If you sepecify no value, Chef will sets "http://#{node['ipaddress']}:8080". |
101 | 135 | 'CONCOURSE_EXTERNAL_URL' => nil, |
102 | 136 | # `${POSTGRES_PASSWORD}` is a placeholder of password string. |
@@ -5,7 +5,7 @@ maintainer_email '' | ||
5 | 5 | license 'Apache 2.0' |
6 | 6 | description 'Installs/Configures Concourse CI by Docker Compose' |
7 | 7 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) |
8 | -version '0.1.5' | |
8 | +version '0.1.6' | |
9 | 9 | source_url 'http://scm.osdn.jp/gitroot/metasearch/grid-chef-repo.git' |
10 | 10 | issues_url 'https://osdn.jp/projects/metasearch/ticket' |
11 | 11 |
@@ -27,12 +27,14 @@ include_recipe 'platform_utils::kernel_user_namespace' | ||
27 | 27 | include_recipe 'docker-grid::compose' |
28 | 28 | |
29 | 29 | app_dir = node['concourse-ci']['docker-compose']['app_dir'] |
30 | +bin_dir = "#{app_dir}/bin" | |
30 | 31 | pgdata_dir = node['concourse-ci']['docker-compose']['pgdata_dir'] |
31 | 32 | web_keys_dir = node['concourse-ci']['docker-compose']['web_keys_dir'] |
32 | 33 | worker_keys_dir = node['concourse-ci']['docker-compose']['worker_keys_dir'] |
33 | 34 | |
34 | 35 | [ |
35 | 36 | app_dir, |
37 | + bin_dir, | |
36 | 38 | web_keys_dir, |
37 | 39 | worker_keys_dir, |
38 | 40 | ].each {|dir| |
@@ -180,6 +182,20 @@ end | ||
180 | 182 | # prevent Chef from logging password attribute value. (=> template variables) |
181 | 183 | web_envs['CONCOURSE_BASIC_AUTH_PASSWORD'] = '${CONCOURSE_BASIC_AUTH_PASSWORD}' |
182 | 184 | |
185 | +oauth_client_id = nil | |
186 | +oauth_client_id_vault_item = node['concourse-ci']['docker-compose']['web_oauth_client_id_vault_item'] | |
187 | +unless oauth_client_id_vault_item.empty? | |
188 | + oauth_client_id = get_vault_item_value(oauth_client_id_vault_item) | |
189 | + web_envs['CONCOURSE_GENERIC_OAUTH_CLIENT_ID'] = '${CONCOURSE_GENERIC_OAUTH_CLIENT_ID}' | |
190 | +end | |
191 | + | |
192 | +oauth_client_secret = nil | |
193 | +oauth_client_secret_vault_item = node['concourse-ci']['docker-compose']['web_oauth_client_secret_vault_item'] | |
194 | +unless oauth_client_secret_vault_item.empty? | |
195 | + oauth_client_secret = get_vault_item_value(oauth_client_secret_vault_item) | |
196 | + web_envs['CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET'] = '${CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET}' | |
197 | +end | |
198 | + | |
183 | 199 | external_url = web_envs_org['CONCOURSE_EXTERNAL_URL'] |
184 | 200 | web_envs['CONCOURSE_EXTERNAL_URL'] = "http://#{node['ipaddress']}:8080" if external_url.nil? |
185 | 201 |
@@ -188,6 +204,30 @@ data_source = web_envs_org['CONCOURSE_POSTGRES_DATA_SOURCE'] | ||
188 | 204 | data_source = data_source.gsub(/<POSTGRES_PASSWORD>/, '${POSTGRES_PASSWORD}') |
189 | 205 | web_envs['CONCOURSE_POSTGRES_DATA_SOURCE'] = data_source |
190 | 206 | |
207 | +if node['concourse-ci']['docker-compose']['import_ca'] | |
208 | + ::Chef::Recipe.send(:include, SSLCert::Helper) | |
209 | + node['concourse-ci']['ssl_cert']['ca_names'].each {|ca_name| | |
210 | + web_vols.push("#{ca_cert_path(ca_name)}:/usr/share/ca-certificates/#{ca_name}.crt:ro") | |
211 | + } | |
212 | + | |
213 | + template "#{bin_dir}/concourse_import_ca" do | |
214 | + source 'opt/docker-compose/app/concourse/bin/concourse_import_ca' | |
215 | + owner 'root' | |
216 | + group 'root' | |
217 | + mode '0755' | |
218 | + action :create | |
219 | + end | |
220 | + web_vols.push("#{bin_dir}/concourse_import_ca:/usr/local/bin/concourse_import_ca:ro") | |
221 | +end | |
222 | + | |
223 | +template "#{bin_dir}/concourse_up" do | |
224 | + source 'opt/docker-compose/app/concourse/bin/concourse_up' | |
225 | + owner 'root' | |
226 | + group 'root' | |
227 | + mode '0755' | |
228 | + action :create | |
229 | +end | |
230 | + | |
191 | 231 | if node['concourse-ci']['with_ssl_cert_cookbook'] |
192 | 232 | ::Chef::Recipe.send(:include, SSLCert::Helper) |
193 | 233 | cn = node['concourse-ci']['ssl_cert']['common_name'] |
@@ -219,7 +259,9 @@ template env_file do | ||
219 | 259 | variables( |
220 | 260 | # secrets |
221 | 261 | db_passwd: db_passwd, |
222 | - basic_auth_passwd: basic_auth_passwd | |
262 | + basic_auth_passwd: basic_auth_passwd, | |
263 | + oauth_client_id: oauth_client_id, | |
264 | + oauth_client_secret: oauth_client_secret | |
223 | 265 | ) |
224 | 266 | end |
225 | 267 |
@@ -235,7 +277,7 @@ Note: You must execute the following command manually. | ||
235 | 277 | See #{doc_url} |
236 | 278 | - Start: |
237 | 279 | $ cd #{app_dir} |
238 | - $ sudo docker-compose up -d | |
280 | + $ ./bin/concourse_up | |
239 | 281 | - Stop |
240 | 282 | $ sudo docker-compose down |
241 | 283 | EOM |
@@ -5,3 +5,9 @@ | ||
5 | 5 | -%> |
6 | 6 | POSTGRES_PASSWORD=<%= @db_passwd %> |
7 | 7 | CONCOURSE_BASIC_AUTH_PASSWORD=<%= @basic_auth_passwd %> |
8 | +<% unless @oauth_client_id.nil? %> | |
9 | +CONCOURSE_GENERIC_OAUTH_CLIENT_ID=<%= @oauth_client_id %> | |
10 | +<% end %> | |
11 | +<% unless @oauth_client_secret.nil? %> | |
12 | +CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET=<%= @oauth_client_secret %> | |
13 | +<% end %> |
@@ -0,0 +1,12 @@ | ||
1 | +#!/bin/sh | |
2 | + | |
3 | +<% | |
4 | +node['concourse-ci']['ssl_cert']['ca_names'].each {|ca_name| | |
5 | +-%> | |
6 | +if ! cat /etc/ca-certificates.conf | grep <%= ca_name %>; then | |
7 | + echo <%= ca_name %>.crt >> /etc/ca-certificates.conf | |
8 | +fi | |
9 | +<% | |
10 | +} | |
11 | +-%> | |
12 | +update-ca-certificates |
@@ -0,0 +1,7 @@ | ||
1 | +#!/bin/sh | |
2 | + | |
3 | +cd <%= node['concourse-ci']['docker-compose']['app_dir'] %> | |
4 | +sudo docker-compose up -d | |
5 | +<% if node['concourse-ci']['docker-compose']['import_ca'] %> | |
6 | +sudo docker exec $(sudo docker ps | grep "concourse_concourse-web" | awk '{print $1}') concourse_import_ca | |
7 | +<% end %> |