Skip to content
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

HTTPS error when using Go core package to setup hoverfly instance #1120

Open
AgustinBettati opened this issue Mar 20, 2024 · 3 comments
Open

Comments

@AgustinBettati
Copy link

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/hoverfly@v1.8.0/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

  1. 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.

@tommysitu
Copy link
Member

how do you call cloud.mongodb.com:443? your http client needs to configure to trust the hoverfly ca cert as well.

@AgustinBettati
Copy link
Author

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).

@tommysitu
Copy link
Member

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)
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants