Skip to content

Sharing example of using tokens + custom ssl certs #106

@jordansissel

Description

@jordansissel

I am still feeling like it's too hard to do what I feel are common things with this client.

In order to use tokens, you have to implement a custom RoundTripper which is pretty deep and awkward within Go, especialy if you're a developer who just wants to "use elasticsearch" and move on; implementing a custom RoundTripper or custom Transport is tedious.

In order to use custom ssl certs, you have to modify the TLSClientConfig of the transport. This is still pretty deep within net/http as compared to the abstraction layer "elasticsearch client library" ; deeper than I'd prefer.

I was unable to find any solid examples of setting both custom headers (for tokens) and setting custom CA certs.

To that end, here's what I found works; this code requires Go 1.13 for http.Transport.Clone()

package main

import (
	"crypto/x509"
	"fmt"
	"github.com/elastic/go-elasticsearch/v8"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type CustomRoundTripper struct {
	http.RoundTripper
	Custom func(*http.Request) (*http.Response, error)
}

func (crt CustomRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	return crt.Custom(req)
}

func main() {
	esurl := os.Args[1]
	token := os.Args[2]
	cafile := os.Args[3]

	transport := http.DefaultTransport.(*http.Transport).Clone()

	var err error
	transport.TLSClientConfig.RootCAs, err = x509.SystemCertPool()

	b, err := ioutil.ReadFile(cafile)
	if err != nil {
		log.Printf("Error reading additional ca certs in path %s / error %s", cafile, err)
		os.Exit(1)
	}

	ok := transport.TLSClientConfig.RootCAs.AppendCertsFromPEM(b)
	if !ok {
		log.Printf("No certs were found in the additional ca cert path: %s", cafile)
		os.Exit(1)
	}

	crt := CustomRoundTripper{
		Custom: func(req *http.Request) (*http.Response, error) {
			req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
			return transport.RoundTrip(req)
		},
	}

	config := elasticsearch.Config{
		Addresses: []string{esurl},
		Transport: crt,
	}

	es, err := elasticsearch.NewClient(config)
	if err != nil {
		log.Printf("Error creating ES client: %s", err)
		os.Exit(1)
	}

	resp, err := es.Ping()
	if err != nil {
		fmt.Printf("Error pinging ES: %s\n", err)
		os.Exit(1)
	}

	fmt.Printf("Response: %s\n", resp)

}

Could we provide some kind of helper function in this library to help users generate their custom Transport? Something like:

elasticsearch.NewClient(elasticsearch.Config{
    Transport: happyHttpHelper{
        Headers: { ... },
        AdditionalCARoots: ...
    }
})

Especially as tokens are becoming more prominent in Elasticsearch (API tokens, etc), it would improve things if we made it less code to achieve this; especially if that "less code" removes areas of Go that, I assume, people do not commonly travel (DIY Transport implementations, etc)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions