Skip to content

Instantly share code, notes, and snippets.

@pblesi
Last active November 6, 2019 04:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pblesi/a48e2a2c07cd22f3e0cab49d3888e724 to your computer and use it in GitHub Desktop.
Save pblesi/a48e2a2c07cd22f3e0cab49d3888e724 to your computer and use it in GitHub Desktop.
An example runbook that handles SSL cert rotation
#!/usr/bin/env ruby
require "runbook"
host = ENV["HOST"] # e.x. ldap01.stg
raise "Error no host specified using HOST env var" unless host
service = ENV["SERVICE"] # e.x. slapd
raise "Error no service specified using SERVICE env var" unless service
local_user = ENV["USER"]
company_name = "patricks_pickles"
intermediate_ca_path = "/root/ca/intermediate"
local_git_dir = "/home/#{local_user}/dev/#{company_name}/pp-infrastructure"
local_cert_path = "modules/ldap/files"
local_cert_file = "#{host}_#{service}.cert.pem"
staging_suffix = "#{company_name}-staging.com"
prod_suffix = "#{company_name}.com"
runbook = Runbook.book "Renew SSL Certs" do
description <<-DESC
This Runbook rotates SSL Certs.
DESC
layout [[:runbook, :commands]]
section "Setup" do
step { ruby_command { @env = host.split(".").last.to_sym } }
end
section "Create New Cert" do
user "root"
step "Backup and update index.txt" do
capture %Q{ls #{intermediate_ca_path}/index.txt.old* | tail -n 1 | sed -E "s/.*([0-9]{2})/\\1/"}, into: :backup_num
ruby_command do
@backup_num = (backup_num.to_i + 1).to_s.rjust(2, "0")
command "cp #{intermediate_ca_path}/index.txt #{intermediate_ca_path}/index.txt.old#{@backup_num}"
command "cp #{intermediate_ca_path}/index.txt.attr #{intermediate_ca_path}/index.txt.attr.old#{@backup_num}"
command %Q{sed -i "/#{host} #{service.upcase}/d" #{intermediate_ca_path}/index.txt}
end
end
step "Generate new cert" do
ruby_command do
case env
when :stg
@expiration_days = 1035
when :prod
@expiration_days = 1095
else
raise "Unknown env: #{env}"
end
tmux_command "sudo openssl ca -config #{intermediate_ca_path}/openssl.cnf -extensions server_cert -days #{@expiration_days} -notext -md sha256 -in #{intermediate_ca_path}/csr/#{host}_#{service}.csr.pem -out #{intermediate_ca_path}/certs/#{local_cert_file}", :commands
confirm "Have you generated the cert?"
end
command "sudo chmod 444 #{intermediate_ca_path}/certs/#{local_cert_file}"
tmux_command "sudo openssl x509 -noout -text -in #{intermediate_ca_path}/certs/#{local_cert_file}", :commands
confirm "Does the cert look correct?"
tmux_command "sudo openssl verify -CAfile #{intermediate_ca_path}/certs/ca-chain.cert.pem #{intermediate_ca_path}/certs/#{local_cert_file}", :commands
confirm "Is the cert valid?"
end
end
section "Upload Cert" do
step "Copy the cert to pp-infrastructure" do
user "root"
command "cp #{intermediate_ca_path}/certs/#{local_cert_file} #{local_git_dir}/#{local_cert_path}"
command "chown #{local_user}:#{local_user} #{local_git_dir}/#{local_cert_path}/#{local_cert_file}"
end
step "Upload the cert" do
server host
upload "#{local_git_dir}/#{local_cert_path}/#{local_cert_file}", to: "/home/#{local_user}"
end
step "Install the cert" do
server host
user "root"
command "mv ~#{local_user}/#{local_cert_file} /etc/ssl"
command "chown root:ssl-cert /etc/ssl/#{local_cert_file}"
command "chmod 444 /etc/ssl/#{local_cert_file}"
command "cp /etc/ssl/#{local_cert_file} /etc/ssl/certs"
end
step "Restart the service" do
server host
user "root"
command "service #{service} restart"
end
step "Validate the service cert is valid" do
ruby_command do
case env
when :stg
@suffix = staging_suffix
when :prod
@suffix = prod_suffix
else
raise "Unknown env: #{env}"
end
tmux_command "ssh #{host}", :commands
tmux_command "openssl s_client -connect #{host}.#{@suffix}:12345 -CApath /etc/ssl/certs", :commands
confirm "Is the cert valid?"
end
end
step "Commit cert changes" do
path "#{local_git_dir}"
command "git add #{local_cert_path}/#{local_cert_file}"
command %Q{git commit -m "Update #{local_cert_file} certificate"}
command "git push"
end
end
end
if __FILE__ == $0
Runbook::Runner.new(runbook).run
else
runbook
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment