Chef remote_file from https site with self signed certificate

7.7k views Asked by At

I was wondering if Chef can use a remote_file resource form a https source that uses self signed certificate. It doesn't seem to be able to. Documentation does not mention certificates and offer configuration for disable SSL check.

If you have a site with https with self signed certificate this can for example be reproduced with recipe that has

remote_file "/tmp/image.png" do
  source "https://mywebsite.com/image.png"
end

You can of course use knife to fetch the certificate on the target node for example as follows

vagrant@devops:~$ knife ssl fetch https://mywebsite.com/
WARNING: No knife configuration file found
WARNING: Certificates from mywebsite.com will be fetched and placed in your trusted_cert directory (/home/vagrant/.chef/trusted_certs).
Knife has no means to verify these are the correct certificates. You should verify the authenticity of these certificates after downloading.

This doesn't seem to do much/anything. Chef will continue to show message

==> default: [2015-06-08T06:30:33+00:00] ERROR: remote_file[/tmp/image.png] (jenkins::remote_file_test line 1) had an error: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Maybe this is a bug? It seems that Chef is ignoring the trusted certs.

Is there a workaround for this? Can we make Chef trust the cert somehow?

Update Correct answer was given by Tensibai. See his comment.

4

There are 4 answers

0
onknows On BEST ANSWER

I use certificate cookbook to install my self signed certificates. So my solution was based on that. In my recipe I use certificate_manage to install certificate which is stored in encrypted data bag.

cert_resource = certificate_manage node['hostname'] do
  action :create
  ignore_missing false
end

Then I can add certificate to cacert.pem with something like

ruby_block 'add_self_signed_certificate_to_cacert' do
  block do
    cert_file_path = ::File.join(cert_resource.cert_path, 'certs', cert_resource.cert_file)
    cacert = ::File.read('/opt/chef/embedded/ssl/certs/cacert.pem')
    pem = ::File.read(::File.join(cert_resource.cert_path, 'certs',cert_resource.cert_file))
    unless cacert.include? pem
      File.open('/opt/chef/embedded/ssl/certs/cacert.pem', 'w') {|f| f.write(cacert + "\n" + pem) }
    end
  end
end
0
Max Monterumisi On

Thank you onknows for the solution.

On AWS OpsWorks I had same problem when try to download file from remote https source signed by internal CA Authority.

On Windows machine the workaround can be the following.

  1. Save in Base-64 encoded X.509 (.CER) the CA Auth certificate.
  2. Put the certificate in the cookbook / files directory
  3. Copy the certificate on the instance disk (for example using a recipe in the setup phase)
cookbook_file 'C:\tmp\calive.cer' do
    source "calive.cer"
    rights :full_control, 'Everyone'
    action :create_if_missing
end
  1. Add the content of the your CA Auth Certificate to the end of the file: C:\opscode\chef\embedded\ssl\certs\cacert.pem
ruby_block 'install_cert' do
    block do
        filemyca = File.open("c:\\tmp\\calive.cer").readlines
        open("C:\\opscode\\chef\\embedded\\ssl\\certs\\cacert.pem", 'a') do |f|
            f.puts ""
            f.puts "My Internel CA Auth Cert"
            f.puts "==========================================="
            f.puts filemyca
        end
    end
    action :run
end
  1. Execute the remote file copy
mypath = 'https://mysite.mydom.local/the_file'
mylocalfile = "c://mydir//the_file"
remote_file mylocalfile do
    source mypath
    action :create_if_missing
end
2
user7039751 On

as of chef 12, the place to put your ca cert file is in /etc/chef/trusted_certs. Putting your file there will resolve this problem.

0
akaphenom On

Per tensibai's technique (comment in the original question) I have the following bit of a recipe to install the cert:

bash 'pull certificate from gitlab' do
  code <<-EOH
    openssl s_client -connect hqdevgit01.my.lan:443 -showcerts | openssl x509 -outform PEM > /opt/chef/embedded/ssl/certs/gitlab.pem
    cat /opt/chef/embedded/ssl/certs/gitlab.pem >> /opt/chef/embedded/ssl/certs/cacert.pem
  EOH
  not_if { ::File.exists?('/opt/chef/embedded/ssl/certs/gitlab.pem') }
end

I download and store the pem in a separate file, and trigger the action off of that existance in the future. I suppose I should check the cacert.pem, but there doesn't seem to be much problem should the cert be appended more than once.

Ultimately I need to get some certs for my internal tools servers - but the organization is small, and there isn't a clear indication of what and where we will be in 6 months. This solution is fine (not ideal) for my short term needs (and we are 100% behind firewalls here).