How to setup HTTPS client in Golang with self-signed SSL TLS client certificate

Author: Ganesh Velrajan

Last Updated: Fri, Sep 22, 2023

In this tutorial, you’ll create a simple HTTPS web client using Go’s standard net/http library. You’ll also create a self-signed SSL TLS X.509 client certificate using the OpenSSL tool. You’ll then use the client certficate to connect the Golang HTTPS web client with the HTTPS web server that enforces mutual TLS (mTLS) authentication.

Create SSL TLS X.509 client certificate

Before you could create the HTTPS client, you need to create a self-signed SSL/TLS X.509 client certificate for the HTTPS web client. For this, please refer to the following tutorial:

BastionXP is a free open-source based SSL TLS X.509 certificate management software to automatically generate, renew and manage SSL X.509 certificates for various applications(web server, web clients, database, web apps, workloads, devices) in your orgnaization.

Once you have created the client SSL certificate and key, you can move on to the next section.

Simple Golang HTTPS Client Example

Here’s is a simple Golang HTTPS client example that doesn’t use any SSL client certificate yet. The HTTPS client also doesn’t verify the HTTPS server’s SSL certificate by setting the InsecureSkipVerify flag to true in the TLSClientConfig field of the HTTP transport instance.

You can use this simple Golang HTTPS client to connect with a simple HTTPS web server written in Go that doesn’t enforce mutual TLS authentication or mTLS.

This HTTPS client performs the equivalent of a curl https://localhost:4443 --insecure command.

// https-client.go
package main
import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
)
func httpsClient(url string) []byte {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get(url)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	fmt.Println("Response status:", resp.Status)
	msg, _ := io.ReadAll(resp.Body)
	return msg
}

func main() {
	// hello, world.
	msg := httpsClient("https://localhost:4443")
	fmt.Println("Msg: ", string(msg))
}

Now, let’s execute the above Go code to connect with the simple HTTPS server written in Go.

Test the HTTPS web client


 $ go run https-client.go
 Hello,World!

Now that you have a functioning simple HTTPS client, you can move to create a mTLS HTTPS client in Go that requires a SSL/TLS X.509 client certificate to connect with the HTTPS web server that enforces mutual TLS (mTLS) authentication.

Golang HTTPS web client example with X.509 SSL Client Certificate

Here is the HTTPS web client that uses SSL client certificate.

//https-client-mtls.go
package main
import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)
var (
	CACertFilePath = "/home/user/ca-cert.pem"
	CertFilePath   = "/home/user/client-cert.pem"
	KeyFilePath    = "/home/user/client-key.pem"
)
func httpsClient(url string) []byte {
	// load tls certificates
	clientTLSCert, err := tls.LoadX509KeyPair(CertFilePath, KeyFilePath)
	if err != nil {
		log.Fatalf("Error loading certificate and key file: %v", err)
		return nil
	}
	// Configure the client to trust TLS server certs issued by a CA.
	certPool, err := x509.SystemCertPool()
	if err != nil {
		panic(err)
	}
	if caCertPEM, err := ioutil.ReadFile(CACertFilePath); err != nil {
		panic(err)
	} else if ok := certPool.AppendCertsFromPEM(caCertPEM); !ok {
		panic("invalid cert in CA PEM")
	}
	tlsConfig := &tls.Config{
		RootCAs:      certPool,
		Certificates: []tls.Certificate{clientTLSCert},
	}
	tr := &http.Transport{
		TLSClientConfig: tlsConfig,
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get(url)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	fmt.Println("Response status:", resp.Status)
	msg, _ := io.ReadAll(resp.Body)
	return msg
}

func main() {
	// hello, world.
	msg := httpsClient("https://localhost:4443")
	fmt.Println("Msg: ", string(msg))
}

Let’s execute the above Go code to connect with the mTLS HTTPS web server:


 $ go run  https-client-mtls.go 
 Response status: 200 OK
 Msg:  Hello,World!

Automate SSL Certificate Management using BastionXP

BastionXP PKI/CA simplifies and automates the management of SSH and SSL/TLS X.509 certificates(both server and client certificates) without affecting the end user workflow.

BastionXP automatically generates new server and client SSH, SSL/TLS X.509 certificates after an end user successfully authenticates via a 2FA (two-factor authentication) enabled SSO provider such as Microsoft Azure 365, Google G-Suite, Okta, GitHub, Keycloak or any SSO provider.

Enforce mutual-TLS authentication for web apps, servers, databases, microservices, service mesh, and workloads in your organization using BastionXP CA.

BastionXP PKI/CA with built-in Role Based Access Control (RBAC), issues short-lived SSH and SSL/TLS client certificates to end users, so that IT admins have fine-grained control over who can access what resources in your organization and for how long.

Start Your Free Trial Now

Try BastionXP for free with no commitments. No credit card required.