I know this is an old thread, but I found it, so others might, too.  

I struggled with a similar problem of the Go HTTP client not sending client 
certs when challenged by the server.  Yet, curl worked fine when given the 
same client certs, calling the same server endpoint.  The cert chains I was 
dealing with look like

leaf + intermediate + root


The solution for me was to provide the server (Envoy proxy) with a the root 
cert AND intermediate cert, the latter of which signed my Go client cert.  
When the server challenges the client for its cert, the server will send a 
TLS Certificate Request with, among other things, the certificate authority 
that must have signed the client cert.  Without including the intermediate 
cert with the root cert on the server side, the client cannot not build a 
complete path from its client cert to the root and therefore cannot 
determine which cert to send in response.  The client will not use 
tls.Config.RootCAs in this analysis (RootCAs is for validating the server 
cert chain).  Moreover, when the client parses its cert with 

cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)


only the leaf is returned even if the certFile contains the concatenated 
intermediate.

Including the full cert bundle on the server side solves this for me.

Hope that helps.



On Tuesday, March 17, 2015 at 10:19:01 AM UTC-7, Dots Connected wrote:
>
> Hello!
>
> I am trying to access an API served by nginx (with a self-signed SSL cert) 
> that requires client certificate authentication, and while I can 
> successfully auth with curl, I unable to accomplish the same with golang.
>
> Example using curl:
>
> # Will not work
> curl -k https://127.0.0.1/api
>
> # Works
> curl -k -E example_key+cert.pem https://127.0.0.1/api
>
>
> I found an example from this list that I've tried to adapt:
>
> https://groups.google.com/forum/#!topic/golang-nuts/dEfqPOSccIchttps://groups.google.com/forum/#!topic/golang-nuts/dEfqPOSccIc
>  
> <https://groups.google.com/forum/#!topic/golang-nuts/dEfqPOSccIc>
> And another from github:
> https://gist.github.com/michaljemala/d6f4e01c4834bf47a9c4
>
> Despite this, golang gets the same result as the first curl with no client 
> cert.
> Am I missing something, or is this a regression in go?
>
> I'm on go version go1.4.2 linux/amd64. My code (or via 
> http://pastebin.com/LGiXZpgx):
>
> package main
>
> import (
> "crypto/tls"
> "io/ioutil"
> "log"
> "net/http"
> )
>
> func main() {
>
> certFile := "example_cert.pem"
> keyFile := "example_key.pem"
>
> // Load client cert
> cert, err := tls.LoadX509KeyPair(certFile, keyFile)
> if err != nil {
> log.Fatal(err)
> }
>
> // Setup HTTPS client
> tlsConfig := &tls.Config{
> Certificates: []tls.Certificate{cert},
> ClientAuth: tls.RequireAndVerifyClientCert,
> InsecureSkipVerify: true,
> }
> tlsConfig.BuildNameToCertificate()
>
> transport := &http.Transport{
> TLSClientConfig: tlsConfig,
> }
> client := &http.Client{
> Transport: transport,
> }
>
> // Do GET something
> resp, err := client.Get("https://localhost/api/";)
> if err != nil {
> log.Fatal(err)
> }
> defer resp.Body.Close()
>
> // Dump response
> data, err := ioutil.ReadAll(resp.Body)
> if err != nil {
> log.Fatal(err)
> }
> log.Println(string(data))
> }
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/43ca36e6-bffe-4b2f-8ee6-c34288685023%40googlegroups.com.

Reply via email to