Skip to content

Instantly share code, notes, and snippets.

@kwilczynski
Created June 12, 2023 12:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwilczynski/02f529156210f07d501da9a4c59efc7a to your computer and use it in GitHub Desktop.
Save kwilczynski/02f529156210f07d501da9a4c59efc7a to your computer and use it in GitHub Desktop.
ZooKeeper TLS in Go example
package main
import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"net"
"os"
"time"
"github.com/go-zookeeper/zk"
)
var (
ca = flag.String("ca", "", "")
insecure = flag.Bool("insecure", false, "")
host = flag.String("host", "localhost", "")
port = flag.String("port", "2182", "")
)
func main() {
flag.Parse()
caCert, err := ioutil.ReadFile(*ca)
if err != nil {
panic(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
RootCAs: caCertPool,
ServerName: *host,
InsecureSkipVerify: *insecure,
PreferServerCipherSuites: true,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
MinVersion: tls.VersionTLS12,
}
tlsConfig.BuildNameToCertificate()
*host = net.JoinHostPort(*host, *port)
conn, err := net.DialTimeout("tcp", *host, 10*time.Second)
if err != nil {
panic(err)
}
conn.SetDeadline(time.Now().Add(3 * time.Second))
tlsConn := tls.Client(conn, tlsConfig)
if err := tlsConn.Handshake(); err != nil {
panic(err)
}
state := tlsConn.ConnectionState()
for _, v := range state.PeerCertificates {
asn1Bytes, err := x509.MarshalPKIXPublicKey(v.PublicKey)
if err != nil {
panic(err)
}
pub, err := x509.ParsePKIXPublicKey(asn1Bytes)
if err != nil {
panic(err)
}
switch pub := pub.(type) {
case *rsa.PublicKey:
fmt.Println("RSA:", pub)
case *dsa.PublicKey:
fmt.Println("DSA:", pub)
case *ecdsa.PublicKey:
fmt.Println("ECDSA:", pub)
default:
panic("unknown type of public key")
}
block := &pem.Block{
Type: "PUBLIC KEY",
Bytes: asn1Bytes,
}
err = pem.Encode(os.Stdout, block)
if err != nil {
panic(err)
}
fmt.Println(v.Subject)
}
fmt.Println("Handshake complete:", state.HandshakeComplete)
fmt.Println("Negotiated protocol is mutual:", state.NegotiatedProtocolIsMutual)
dialer := func() zk.Dialer {
return func(_, _ string, _ time.Duration) (net.Conn, error) {
return tlsConn, nil
}
}()
c, _, err := zk.Connect([]string{*host}, 60*time.Second, zk.WithDialer(dialer))
if err != nil {
panic(err)
}
children, stat, channel, err := c.ChildrenW("/")
if err != nil {
panic(err)
}
fmt.Printf("%+v %+v\n", children, stat)
fmt.Printf("%+v\n", <-channel)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment