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.

 
4
Kudos
 
4
Kudos

Now read this

What is DevOps?

DevOps can be a lot of different things depending on the context - a methodology, a culture, a set of tools, a department or job title… The purest definition of DevOps is a culture of collaboration between Development and Operations (and... Continue →