hoverfly
hoverfly copied to clipboard
HTTPS error when using Go core package to setup hoverfly instance
Description of the bug
I have been looking into managing hoverfly from my Go tests directly. In the documentation I do not see any official mention for a Go SDK, however I did find https://pkg.go.dev/github.com/SpectoLabs/[email protected]/core which seems to expose all the functionality I need.
The issue I am facing is a TLS error due to unknown certificate authority, however when running a hoverfly instance with hoverctl
I do not face this issue and can confirm I have configured the hoverfly ca cert in my keychain following the documentation.
Steps to reproduce the issue
Go code which configures the hoverfly instance using "github.com/SpectoLabs/hoverfly/core"
settings := hoverfly.InitSettings()
settings.Verbose = true
hv := hoverfly.NewHoverflyWithConfiguration(settings)
err := hv.StartProxy()
if err != nil {
log.Fatalf("Failed to start Hoverfly: %v", err)
}
err = hv.SetModeWithArguments(v2.ModeView{Mode: "capture", Arguments: v2.ModeArgumentsView{Stateful: true}})
if err != nil {
log.Fatalf("Failed to set Hoverfly mode: %v", err)
}
Subsequent calls fail, detailed error below.
Observed result
output from verbose logs:
024/03/20 14:24:08 [001] INFO: Running 1 CONNECT handlers
2024/03/20 14:24:08 [001] INFO: on 0th handler: &{2 <nil> 0x10597a7e0} cloud.mongodb.com:443
2024/03/20 14:24:08 [001] INFO: Assuming CONNECT is TLS, mitm proxying it
2024/03/20 14:24:08 [001] INFO: signing for cloud-dev.mongodb.com
2024/03/20 14:24:08 [001] WARN: Cannot handshake client cloud.mongodb.com:443 remote error: tls: bad certificate
error from client call:
tls: failed to verify certificate: x509: certificate signed by unknown authority
Expected result
I would expect the same behaviour as when I setup hoverfly using hoverctl
:
hoverctl start
hoverctl mode capture --stateful
In this case my https requests are successfully captured.
Additional relevant information
- Hoverfly version: 1.8.0
Any inputs would be greatly appreciated, also want to confirm that using the github.com/SpectoLabs/hoverfly/core
package is advised.
how do you call cloud.mongodb.com:443
? your http client needs to configure to trust the hoverfly ca cert as well.
cloud.mongodb.com is being called directly by a regular Go client which also has configured the env variable "HTTPS_PROXY": "http://localhost:<port>"
func NewTransport(username, password string) *Transport {
t := &Transport{
Username: username,
Password: password,
}
t.Transport = http.DefaultTransport
return t
}
// Client returns an HTTP client that uses the digest transport.
func (t *Transport) Client() (*http.Client, error) {
if t.Transport == nil {
return nil, ErrNilTransport
}
return &http.Client{Transport: t}, nil
}
What is suprising is that if I run hoverfly through the cli using hoverctl
with the command mentioned above I face no issue, however when starting hoverfly with the Go module I am facing the error (no changes in how the client calls the proxy).
Hey @AgustinBettati , sorry for the radio silence, since hoverfly has its own custom CA cert as I mentioned before, your go http client need to be able to trust it, otherwise you will get the bad tls cert error. You can do something like this to load the hoverfly ca cert in pem format , and add it to a CertPool
, then sets up a http.Transport
with TLSClientConfig
that uses the CertPool
, and finally a http.Client
that uses the Transport
:
// Read the certificate file
cert, err := ioutil.ReadFile("/path/to/your/certificate.pem")
if err != nil {
log.Fatalf("Couldn't load certificate: %v", err)
}
// Create a CertPool and add the certificate to it
certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM(cert); !ok {
log.Fatalf("Failed to append certificate")
}
// Create a new Transport that uses the CertPool
tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
}
// Create a new Client that uses the Transport
client := &http.Client{Transport: tr}
// Now you can use this client as you would normally
// It will trust your custom certificate authority
_, err = client.Get("https://your.domain")
if err != nil {
log.Fatalf("Could not get response: %v", err)
}