New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL certificate error on Windows 7 #454

Open
bdruth opened this Issue Jun 16, 2015 · 19 comments

Comments

Projects
None yet
10 participants
@bdruth
Copy link

bdruth commented Jun 16, 2015

Good afternoon -

I'm trying to verify an automation setup that I developed on Win 2012 R2 to work on Windows 7 SP1. I have all updates installed on Win7 SP1 and my pre-r10k script installs the GeoTrust Global CA (since that was missing from the root store on Win 2012 R2). Despite this, and despite using a version of Rubygems (2.4.7) newer than the same issue/error documented here, I'm still having no luck trying to get r10k to install modules from Forge.

INFO     -> Updating module C:/Users/IEUser/Downloads/modules/chocolatey
ERROR    -> SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
INFO     -> Updating module C:/Users/IEUser/Downloads/modules/powershell
ERROR    -> SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
INFO     -> Updating module C:/Users/IEUser/Downloads/modules/windows
ERROR    -> SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
INFO     -> Updating module C:/Users/IEUser/Downloads/modules/stdlib
ERROR    -> SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
INFO     -> Updating module C:/Users/IEUser/Downloads/modules/registry
ERROR    -> SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Unfortunately, I have no idea what URL it's actually trying to access - so there may be yet another root cert missing somewhere, I just can't figure out which.

Thanks!

@bdruth

This comment has been minimized.

Copy link
Author

bdruth commented Jun 16, 2015

This is the extent of my Puppetfile:

mod 'chocolatey/chocolatey'
mod 'puppetlabs/powershell'
mod 'counsyl/windows'
mod 'puppetlabs/stdlib'
mod 'puppetlabs/registry'

There's nothing else and no other setup re: r10k and this is on a fresh VM snapshot.

@bdruth

This comment has been minimized.

Copy link
Author

bdruth commented Jun 16, 2015

I've added some debugging to puppet_forge/connection.rb and (seemingly) am able to confirm that the failing connection is to https://forgeapi.puppetlabs.com ... however, it uses the same CA as the main forge URL, so GeoTrust, and those certs are installed.

@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Jun 16, 2015

This might be due to Windows not properly initializing the SSL cert paths; try applying this patch to connection.rb - it should explicitly set up the paths as needed.

From 0e34f7031218d0a5e95fc5c4df87450935be0dff Mon Sep 17 00:00:00 2001
From: Adrien Thebo <git@somethingsinistral.net>
Date: Tue, 16 Jun 2015 14:13:50 -0700
Subject: [PATCH] Setup default SSL cert store paths when reaching forge via
 HTTPS

---
 lib/shared/puppet_forge/connection.rb | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/lib/shared/puppet_forge/connection.rb b/lib/shared/puppet_forge/connection.rb
index ac402c0..ce5cb24 100644
--- a/lib/shared/puppet_forge/connection.rb
+++ b/lib/shared/puppet_forge/connection.rb
@@ -2,6 +2,7 @@ require 'shared/puppet_forge/version'

 require 'faraday'
 require 'faraday_middleware'
+require 'openssl'

 module PuppetForge
   # Provide a common mixin for adding a HTTP connection to classes.
@@ -51,12 +52,32 @@ module PuppetForge
         options[:headers][:authorization] = token
       end

-      Faraday.new(url, options) do |builder|
-        builder.response(:json, :content_type => /\bjson$/)
-        builder.response(:raise_error)
+      builder = Faraday::RackBuilder.new do |b|
+        b.response(:json, :content_type => /\bjson$/)
+        b.response(:raise_error)
+        b.adapter(*adapter_args)
+      end
+
+      options[:builder] = builder

-        builder.adapter(*adapter_args)
+      if url.match(/^https/)
+        conn = make_https_connection(url, options)
+      else
+        conn = make_http_connection(url, options)
       end
+
+      conn
+    end
+
+    def make_http_connection(url, options)
+      Faraday.new(url, options)
+    end
+
+    def make_https_connection(url, options)
+      cert_store = OpenSSL::X509::Store.new
+      cert_store.set_default_paths
+
+      Faraday.new(url, options.merge(:ssl => {:cert_store => cert_store}))
     end
   end
 end
-- 
2.4.2
@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Jun 22, 2015

It's been about a week since this issue has seen an update, are you still affected by this?

@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Jul 1, 2015

It's been about two weeks since this issue has seen any activity; if I don't hear anything else on this issue within a week or two I'm going to assume that this issue was resolved.

@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Jul 27, 2015

Since I haven't heard back on this issue I'm going to assume this was resolved; if this is still an issue please comment on this ticket and we can continue working on this. Thanks!

@cavaliercoder

This comment has been minimized.

Copy link

cavaliercoder commented Sep 18, 2015

Damn... I'm experiencing this issue. Had the same issue with puppet module install until installing the GeoTrust Cert (on Windows Server 2012 R2 +no updates), but r10k is still no bingo.

@ericsysmin

This comment has been minimized.

Copy link

ericsysmin commented Sep 18, 2015

Yep, after making the changes I still have the issue as well.

C:\>gem list
...
r10k (2.0.3)
...

connection.rb is as follows:

require 'shared/puppet_forge/version'
require 'shared/puppet_forge/connection/connection_failure'

require 'faraday'
require 'faraday_middleware'

module PuppetForge
  # Provide a common mixin for adding a HTTP connection to classes.
  #
  # This module provides a common method for creating HTTP connections as well
  # as reusing a single connection object between multiple classes. Including
  # classes can invoke #conn to get a reasonably configured HTTP connection.
  # Connection objects can be passed with the #conn= method.
  #
  # @example
  #   class HTTPThing
  #     include PuppetForge::Connection
  #   end
  #   thing = HTTPThing.new
  #   thing.conn = thing.make_connection('https://non-standard-forge.site')
  #
  # @api private
  module Connection

    attr_writer :conn

    USER_AGENT = "PuppetForge/#{PuppetForge::VERSION} Faraday/#{Faraday::VERSION} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"

    def self.authorization=(token)
      @authorization = token
    end

    def self.authorization
      @authorization
    end

    # @return [Faraday::Connection] An existing Faraday connection if one was
    #   already set, otherwise a new Faraday connection.
    def conn
      @conn ||= make_connection('https://forgeapi.puppetlabs.com')
    end

    # Generate a new Faraday connection for the given URL.
    #
    # @param url [String] the base URL for this connection
    # @return [Faraday::Connection]
    def make_connection(url, adapter_args = nil)
      adapter_args ||= [Faraday.default_adapter]
      options = { :headers => { :user_agent => USER_AGENT }}

      if token = PuppetForge::Connection.authorization
        options[:headers][:authorization] = token
      end

      builder = Faraday::RackBuilder.new do |b|
        b.response(:json, :content_type => /\bjson$/)
        b.response(:raise_error)
        b.adapter(*adapter_args)
      end

      options[:builder] = builder

      if url.match(/^https/)
        conn = make_https_connection(url, options)
      else
        conn = make_http_connection(url, options)
      end

      conn
    end

    def make_http_connection(url, options)
      Faraday.new(url, options)
    end

    def make_https_connection(url, options)
      cert_store = OpenSSL::X509::Store.new
      cert_store.set_default_paths

      Faraday.new(url, options.merge(:ssl => {:cert_store => cert_store}))
    end
  end
end
@cavaliercoder

This comment has been minimized.

Copy link

cavaliercoder commented Sep 22, 2015

I ran Windows update until all updates were installed (including root cert updates) on Server 2012 R2 x64... issue persists :(
r10k v2.0.3

@roanosullivan

This comment has been minimized.

Copy link

roanosullivan commented Sep 22, 2015

I'm having similar issues, also r10k v2.0.3 and Windows 2012 R2. Can this Issue be re-opened?

@adrienthebo adrienthebo reopened this Sep 22, 2015

nicolasvan added a commit to red-gate/r10k that referenced this issue Oct 20, 2015

@c33s

This comment has been minimized.

Copy link

c33s commented Nov 24, 2015

same problem here.
my very insecure workaround was to add :ssl => {:verify => false} to the Faraday.new() options

full file (lib/puppet_forge/connection.rb):

require 'puppet_forge/connection/connection_failure'

require 'faraday'
require 'faraday_middleware'
require 'puppet_forge/middleware/symbolify_json'

module PuppetForge
  # Provide a common mixin for adding a HTTP connection to classes.
  #
  # This module provides a common method for creating HTTP connections as well
  # as reusing a single connection object between multiple classes. Including
  # classes can invoke #conn to get a reasonably configured HTTP connection.
  # Connection objects can be passed with the #conn= method.
  #
  # @example
  #   class HTTPThing
  #     include PuppetForge::Connection
  #   end
  #   thing = HTTPThing.new
  #   thing.conn = thing.make_connection('https://non-standard-forge.site')
  #
  # @api private
  module Connection

    attr_writer :conn

    USER_AGENT = "#{PuppetForge.user_agent} PuppetForge.gem/#{PuppetForge::VERSION} Faraday/#{Faraday::VERSION} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})".strip

    def self.authorization=(token)
      @authorization = token
    end

    def self.authorization
      @authorization
    end

    # @return [Faraday::Connection] An existing Faraday connection if one was
    #   already set, otherwise a new Faraday connection.
    def conn
      @conn ||= default_connection
    end

    def default_connection

      begin
        # Use Typhoeus if available.
        Gem::Specification.find_by_name('typhoeus', '~> 0.6')
        require 'typhoeus/adapters/faraday'
        adapter = :typhoeus
      rescue Gem::LoadError
        adapter = Faraday.default_adapter
      end

      make_connection(PuppetForge.host, [adapter])
    end
    module_function :default_connection

    # Generate a new Faraday connection for the given URL.
    #
    # @param url [String] the base URL for this connection
    # @return [Faraday::Connection]
    def make_connection(url, adapter_args = nil, opts = {})
      adapter_args ||= [Faraday.default_adapter]
      options = 
      { :headers => { :user_agent => USER_AGENT }, :ssl => {:verify => false} }.merge(opts)

      if token = PuppetForge::Connection.authorization
        options[:headers][:authorization] = token
      end

      Faraday.new(url, options) do |builder|
        builder.use PuppetForge::Middleware::SymbolifyJson
        builder.response(:json, :content_type => /\bjson$/)
        builder.response(:raise_error)
        builder.use(:connection_failure)

        builder.adapter(*adapter_args)
      end
    end
    module_function :make_connection
  end
end
@benpriestman

This comment has been minimized.

Copy link

benpriestman commented Dec 5, 2015

I've come across similar issues on Windows.
I don't have this problem, if I install r10k in the ruby install that is bundled with puppet's installable packages.
I do have this problem, if I try and use ruby from http://rubyinstaller.org/ with puppet and the puppet module tool installed as gems.

My conclusion was that this is a symptom of a much deeper problem: that stock ruby uses openssl, which uses uses hard-coded paths for its default certificate store, which are not appropriate for Windows. The best summary I've found of this is the comments made by luislavena in oneclick/rubyinstaller#249. Also see https://groups.google.com/forum/#!searchin/rubyinstaller/ssl/rubyinstaller/DVIDvs7xKC0/Z22dY49LFnEJ.

My solution was to use a provisioning script to write out a set of default certs to a file and have %SSL_CERT_FILE% hold the path to this file.

Is this the same issue that the other posting here are facing, or is this something else?

@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Dec 7, 2015

@malaikah interesting - thanks for chasing this down!

@benpriestman

This comment has been minimized.

Copy link

benpriestman commented Dec 8, 2015

If you're using Git For Windows (or any form of git, I suppose), you can also borrow the cacert bundle that uses.
git config http.sslcainfo
Will tell you where it is.
Comparing a few different installs, this seems to sometimes be a relative, sometimes an absolute path, so you might need to do some additional jiggery-pokery to construct a reliable value.

@adrienthebo

This comment has been minimized.

Copy link
Contributor

adrienthebo commented Dec 8, 2015

On your system, what is that path? Depending on how complex it is it might be possible to hardcode that path into r10k as an additional location for CA certs on Windows.

@benpriestman

This comment has been minimized.

Copy link

benpriestman commented May 24, 2016

C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt. That path is a pretty likely bet, but it depends on what git client you have installed, so hard-coding it seems like a bad idea.

@sfhardman

This comment has been minimized.

Copy link

sfhardman commented Sep 19, 2016

For Git for Windows you can workaround as follows:

echo "export SSL_CERT_FILE=/mingw64/ssl/certs/ca-bundle.crt" >> ~/.bash_profile
source ~/.bash_profile

@mattdanskey

This comment has been minimized.

Copy link

mattdanskey commented Mar 8, 2017

Thanks for giving the pieces needed to figure this out!

I've done the following workaround for powershell (with r10k installed using the ruby from RubyInstaller):

  1. Install git
  2. Set the SSL_CERT_FILE environment variable to the path to ca-bundle.crt that came with git. This can be done manually or by running the following line in powershell (double check the path is correct for you first):
[Environment]::SetEnvironmentVariable("SSL_CERT_FILE", "C:\Program Files\Git\mingw64\ssl\certs\ca-bundle.crt", "Machine")
  1. Restart powershell
@glennsarti

This comment has been minimized.

Copy link

glennsarti commented Dec 20, 2017

I created a quick PS script to download a complete ca cert bundle and configure SSL correctly for me

https://github.com/glennsarti/dev-tools/blob/master/RubyCerts.ps1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment