Managing certificates with Chef and Windows
Managing stuff on windows with Chef can be tough.. Especially compared to Linux systems. I’ve been doing it like this:
pfx.each do |pfx|
s3_file 'c:/chef/' + pfx do
remote_path '/' + pfx
bucket 'chef'
aws_access_key_id node['iis']['aws_key']
aws_secret_access_key node['iis']['aws_secret']
action :create
not_if {::File.exists?("c:/chef/#{pfx}.zip")}
end
execute 'import pfx' do
command "c:/chef/importpfx.exe -f c:/chef/#{pfx} -t MACHINE -s MY -p \"#{pass}\""
end
end
cert_map = pfx.zip(cert, ip)
cert_map.each do |pfx, cert, ip|
powershell_script 'bind cert' do
code <<-EOH
$var = dir cert:\\LocalMachine\\my | grep #{cert}
$pos = $var.IndexOf(" ")
$sub = $var.Substring(0,$pos)
netsh http add sslcert ipport=#{ip}:443 certhash=$sub appid={ab3c58f7-8316-42e3-bc6e-771d4ce4b201}
EOH
not_if {"$var = dir cert:\\LocalMachine\\my | grep #{cert} ;; $pos = $var.IndexOf(\" \") ;; $sub = $var.Substring(0,$pos) ;; netsh http show sslcert | grep $sub -i"}
end
end
I’ve not yet found a better way to do it. This lets me download the cert and bind it to a certain interface. My personal use case is ssl bindings for IIS, but this should work for any other use as well.
Update:
I’ve since updated this a little bit -
if node['iis']['manage_ssl'] == true
if node.chef_environment == 'prod-windows'
`powershell.exe -Command (invoke-webrequest http://169.254.169.254/latest/meta-data/network/interfaces/macs -UseBasicParsing -DisableKeepAlive).content.trim()`.split("\n").each do |mac|
ip = `powershell.exe -Command (invoke-webrequest http://169.254.169.254/latest/meta-data/network/interfaces/macs/#{mac}local-ipv4s -UseBasicParsing -DisableKeepAlive).content.trim()}.delete("\n")`
end
pfx = %w(star.example.com.pfx star.example.com.pfx)
cert = %w(*.example.com *.example.com)
pass = %w(T00lb0x! T00lb0x!)
else
pfx = %w(_.example.com.pfx)
cert = %w(*.example.com)
pass = %w()
ip = %w(0.0.0.0)
end
cert_map = pfx.zip(cert, pass, ip)
cert_map.each do |pfx, cert, pass, ip|
s3_file 'c:/chef/' + pfx do
remote_path '/' + pfx
bucket 'chef'
aws_access_key_id node['iis']['aws_key']
aws_secret_access_key node['iis']['aws_secret']
action :create
not_if { ::File.exist?("c:/chef/#{pfx}") }
end
execute 'import pfx' do
command "c:/chef/importpfx.exe -f c:/chef/#{pfx} -t MACHINE -s MY -p \"#{pass}\""
end
powershell_script 'bind cert' do
code <<-EOH
$var = dir cert:\\LocalMachine\\my | grep #{cert}
$pos = $var.IndexOf(" ")
$sub = $var.Substring(0,$pos)
netsh http add sslcert ipport=#{ip}:443 certhash=$sub appid={ab3c58f7-8316-42e3-bc6e-771d4ce4b201}
EOH
not_if { "$var = dir cert:\\LocalMachine\\my | grep #{cert} ;; $pos = $var.IndexOf(\" \") ;; $sub = $var.Substring(0,$pos) ;; netsh http show sslcert | grep $sub -i" }
end
end
end
The idea behind this method is that it should be able to automatically parse through the aws metadata service to get the IP’s assigned to a certain instance, and then assign certificates to them.