diff --git a/elasticsearch.go b/elasticsearch.go index 4224754702..0d312aa500 100755 --- a/elasticsearch.go +++ b/elasticsearch.go @@ -30,6 +30,8 @@ type Config struct { Password string // Password for HTTP Basic Authentication. CloudID string // Endpoint for the Elastic Service (https://elastic.co/cloud). + APIKey string // Base64-encoded token for authorization; if set, overrides username and password. + Transport http.RoundTripper // The HTTP transport object. Logger estransport.Logger // The logger object. } @@ -108,6 +110,7 @@ func NewClient(cfg Config) (*Client, error) { URLs: urls, Username: cfg.Username, Password: cfg.Password, + APIKey: cfg.APIKey, Transport: cfg.Transport, Logger: cfg.Logger, diff --git a/estransport/estransport.go b/estransport/estransport.go index 70ce829f93..cd5c62f3c2 100755 --- a/estransport/estransport.go +++ b/estransport/estransport.go @@ -39,6 +39,7 @@ type Config struct { URLs []*url.URL Username string Password string + APIKey string Transport http.RoundTripper Logger Logger @@ -50,6 +51,7 @@ type Client struct { urls []*url.URL username string password string + apikey string transport http.RoundTripper selector Selector @@ -69,6 +71,7 @@ func New(cfg Config) *Client { urls: cfg.URLs, username: cfg.Username, password: cfg.Password, + apikey: cfg.APIKey, transport: cfg.Transport, selector: NewRoundRobinSelector(cfg.URLs...), @@ -89,7 +92,7 @@ func (c *Client) Perform(req *http.Request) (*http.Response, error) { c.setUserAgent(req) if _, ok := req.Header["Authorization"]; !ok { - c.setBasicAuth(u, req) + c.setAuthorization(u, req) } var dupReqBody *bytes.Buffer @@ -154,13 +157,22 @@ func (c *Client) setURL(u *url.URL, req *http.Request) *http.Request { return req } -func (c *Client) setBasicAuth(u *url.URL, req *http.Request) *http.Request { +func (c *Client) setAuthorization(u *url.URL, req *http.Request) *http.Request { if u.User != nil { password, _ := u.User.Password() req.SetBasicAuth(u.User.Username(), password) return req } + if c.apikey != "" { + var b bytes.Buffer + b.Grow(len("APIKey ") + len(c.apikey)) + b.WriteString("APIKey ") + b.WriteString(c.apikey) + req.Header.Set("Authorization", b.String()) + return req + } + if c.username != "" && c.password != "" { req.SetBasicAuth(c.username, c.password) return req diff --git a/estransport/estransport_internal_test.go b/estransport/estransport_internal_test.go index 29e0f7724b..5fcc9dff46 100755 --- a/estransport/estransport_internal_test.go +++ b/estransport/estransport_internal_test.go @@ -97,7 +97,7 @@ func TestTransportPerform(t *testing.T) { tp := New(Config{URLs: []*url.URL{u}}) req, _ := http.NewRequest("GET", "/", nil) - tp.setBasicAuth(u, req) + tp.setAuthorization(u, req) username, password, ok := req.BasicAuth() if !ok { @@ -114,7 +114,7 @@ func TestTransportPerform(t *testing.T) { tp := New(Config{URLs: []*url.URL{u}, Username: "foo", Password: "bar"}) req, _ := http.NewRequest("GET", "/", nil) - tp.setBasicAuth(u, req) + tp.setAuthorization(u, req) username, password, ok := req.BasicAuth() if !ok { @@ -126,6 +126,23 @@ func TestTransportPerform(t *testing.T) { } }) + t.Run("Sets APIKey Authentication from configuration", func(t *testing.T) { + u, _ := url.Parse("http://example.com") + tp := New(Config{URLs: []*url.URL{u}, APIKey: "Zm9vYmFy"}) // foobar + + req, _ := http.NewRequest("GET", "/", nil) + tp.setAuthorization(u, req) + + value := req.Header.Get("Authorization") + if value == "" { + t.Errorf("Expected the request to have the Authorization header set") + } + + if value != "APIKey Zm9vYmFy" { + t.Errorf(`Unexpected value for Authorization: want="APIKey Zm9vYmFy", got="%s"`, value) + } + }) + t.Run("Sets UserAgent", func(t *testing.T) { u, _ := url.Parse("http://example.com") tp := New(Config{URLs: []*url.URL{u}})