Skip to content
This repository was archived by the owner on Aug 30, 2020. It is now read-only.

Commit 93646e4

Browse files
author
Jörg Herzinger
committed
add chef vault functionality
1 parent dd9a62e commit 93646e4

9 files changed

+89
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
Gemfile.lock
2+
.bundle

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
source 'https://rcrs.rbinternational.com/artifactory/api/gems/gems/'
1+
source 'https://rubygems.org'
22

33
gem 'mixlib-shellout', '~> 2.3.2'
4+
gem 'deep_merge', '~> 1.2.1'

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ To run this you need at least:
1010

1111
* Git
1212
* Docker
13-
* Ruby (>= 2)
13+
* Ruby (>= 2) and Bundler
14+
15+
You also have to initialize the Chef Data Bag used for the certificates. By default that is called `letsencrypt` via `knife data bag create letsencrypt`.
1416

1517
### Config
1618

@@ -33,9 +35,10 @@ Create a file called `config.json` alongside the `config.default.json` and fill
3335
"chef": {
3436
"docker_image": "docker.local/chef/chefdk:v2",
3537
"data_bag": "letsencrypt",
38+
"config_dir": "~/.chef",
3639
"admins": ["admin1", "admin2"]
3740
},
38-
"backends": [
41+
"steps": [
3942
"chef_vault"
4043
],
4144
"certificates": {
@@ -70,7 +73,14 @@ rake init
7073
rake certbot:register
7174
```
7275

73-
once and commit the changes.
76+
once and commit the changes. With the account registered and the Chef Data Bag create the usual workflow is to update the `config.json` with the certificates that should be created and then to run:
77+
78+
```
79+
rake init
80+
rake certbot:renew
81+
rake chef_vault:upload
82+
rake cleanup
83+
```
7484

7585
### Running in Jenkins
7686

@@ -98,3 +108,5 @@ Pretty much everything I guess...
98108
* How to upload only changed certificates
99109
* Read state from git?
100110
* Keep state file with changes?
111+
* Change Rake tasks to be able to take a list of certificates as argument
112+
* Add Chef Vault refresh rake task

Rakefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Rake.application.options.suppress_backtrace_pattern = %r{/} # Suppress trace whe
1212
desc 'Initialize project'
1313
task :init do
1414
Helpers.log Certbot.init
15-
# ChefVault.init if Helpers.config['backends'].key?('chef_vault')
16-
# HashicorpVault.init if Helpers.config['backends'].key?('hashicorp_vault')
15+
Helpers.log ChefVault.init if Helpers.config['steps'].include?('chef_vault')
16+
# HashicorpVault.init if Helpers.config['steps'].key?('hashicorp_vault')
1717
end
1818

1919
desc 'Displays Help'
@@ -56,11 +56,14 @@ end
5656
namespace :chef_vault do
5757
desc 'Upload all changed certificates as chef vaults'
5858
task :upload do
59-
ChefVault.upload
59+
Helpers.config['certificates'].each do |name, props|
60+
Helpers.log ChefVault.upload(name, props['chef_vault'] || {})
61+
end
6062
end
61-
end
63+
end if Helpers.config['steps'].include?('chef_vault')
6264

6365
desc 'Cleanup all temporary files, docker containers etc'
6466
task :cleanup do
6567
Helpers.log Certbot.cleanup
68+
Helpers.log ChefVault.cleanup if Helpers.config['steps'].include?('chef_vault')
6669
end

config.default.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
"docker_image": "certbot/dns-route53:v0.22.0",
66
"docker_container": "certbot",
77
"aws_credentials": "~/.aws/credentials",
8-
"email": "[email protected]",
98
"server": "https://acme-staging-v02.api.letsencrypt.org/directory"
109
},
11-
"chef": {
10+
"chef_vault": {
1211
"docker_image": "chef/chefdk:2",
12+
"docker_container": "chefdk",
1313
"data_bag": "letsencrypt",
14-
"admins": ["admin1", "admin2"]
14+
"config_dir": "~/.chef"
1515
},
16-
"backends": [
17-
"chef_vault"
16+
"steps": [
17+
"init",
18+
"certbot",
19+
"chef_vault",
20+
"git",
21+
"cleanup"
1822
],
1923
"certificates": {
2024
}

lib/certbot.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require 'etc'
12
require_relative 'helpers'
23

34
# Cerbot module
@@ -25,6 +26,10 @@ def register
2526
def renew(name, domains)
2627
Helpers.info_log("Registering/Renewing certificate #{name} for domains #{domains.join(',')}")
2728
run("certonly --non-interactive --dns-route53 --cert-name #{name} --domains #{domains.join(',')}")
29+
30+
# Fix permissions for etc_letsencrypt so we can actually commit it to GIT
31+
user = Etc.getpwuid
32+
Helpers.run_command("docker exec -i #{Helpers.config['certbot']['docker_container']} chown -R #{user.uid}:#{user.gid} /etc/letsencrypt")
2833
end
2934

3035
def run(cmd)

lib/chef_vault.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,53 @@
1+
require 'json'
2+
13
# Chef Vault module
24
module ChefVault
35
extend self
46

57
def init
8+
options = [ "-itd #{Helpers.environment}",
9+
"--name #{Helpers.config['chef_vault']['docker_container']}",
10+
"-v `pwd`/etc_letsencrypt:/etc/letsencrypt",
11+
"-v #{Helpers.config['chef_vault']['config_dir']}:/root/.chef"
12+
]
13+
14+
Helpers.run_command("docker run #{options.join(' ')} #{Helpers.config['chef_vault']['docker_image']}")
15+
end
16+
17+
def cleanup
18+
Helpers.run_command("docker rm -f #{Helpers.config['chef_vault']['docker_container']}")
19+
end
20+
21+
# Upload all certificates to the chef server
22+
def upload(cert, props = {})
23+
Helpers.info_log("Uploading Chef Vault for #{cert}")
24+
options = [ '--mode client' ]
25+
options << "--admins #{Helpers.config['chef_vault']['admins'].join(',')}" if Helpers.config['chef_vault'].key?('admins')
26+
options << "--clients #{props['clients'].join(',')}" if props.key?('clients')
27+
options << "--search #{props['search']}" if props.key?('search')
28+
29+
current_item = run("vault itemtype #{Helpers.config['chef_vault']['data_bag']} #{cert}")
30+
if current_item[:return] == 0 && current_item[:stdout].include?('vault')
31+
run("vault update --clean #{options.join(' ')} #{Helpers.config['chef_vault']['data_bag']} #{cert} '#{vault_json(cert)}'")
32+
elsif current_item[:return] == 0 && !current_item[:stdout].include?('vault')
33+
{ return: 1, stdout: "The DataBag item #{Helpers.config['chef_vault']['data_bag']}/#{cert} is not of type vault. Please delete the item first.", stderr: ''}
34+
elsif current_item[:return] == 100 && current_item[:stderr].include?('ERROR: The object you are looking for could not be found')
35+
run("vault create #{options.join(' ')} #{Helpers.config['chef_vault']['data_bag']} #{cert} '#{vault_json(cert)}'")
36+
else
37+
current_item
38+
end
39+
end
40+
41+
def run(cmd)
42+
Helpers.run_command("docker exec -i #{Helpers.config['chef_vault']['docker_container']} knife #{cmd}")
43+
end
44+
45+
def vault_json(cert)
46+
vault = {}
47+
%w(cert chain fullchain privkey).each do |file|
48+
vault[file] = File.read("etc_letsencrypt/live/#{cert}/#{file}.pem")
49+
end
650

51+
vault.to_json
752
end
853
end

lib/helpers.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require 'json'
22
require 'fileutils'
33
require 'mixlib/shellout'
4+
require 'deep_merge'
45

56
# Helpers module for stuff that is always needed
67
module Helpers
@@ -27,7 +28,7 @@ def config
2728
{}
2829
end
2930

30-
@@config = default_config.merge(user_config)
31+
@@config = default_config.deep_merge!(user_config, {:overwrite_arrays => true})
3132
end
3233

3334
# Simple info logger using the log helper
@@ -49,7 +50,7 @@ def log(out, error_msg = '')
4950
puts out[:stdout] unless out[:stdout].nil? || out[:stdout].empty?
5051
else
5152
puts "--- Failed with exit code #{out[:return]}"
52-
puts "Command was: #{out[:cmd]}"
53+
puts "Command was: #{out[:cmd]}" if out.key?('cmd')
5354
unless out[:stdout].empty?
5455
puts "--- STDOUT:"
5556
puts out[:stdout].strip

lib/init.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
if [[ -e Gemfile.lock ]]
22
then
3-
bundle23 update
3+
bundle update
44
touch Gemfile.lock # Update time on file so rake won't call it again
55
else
6-
bundle23 install
6+
bundle install --path .bundle
77
fi

0 commit comments

Comments
 (0)