Skip to content

Commit 3b68c0f

Browse files
committed
Add support for APIKey authentication
In order to facilitate connecting to clusters with API Key (https://www.elastic.co/guide/en/elasticsearch/reference/master/security-api-create-api-key.html), add the corresponding configuration option. Takes precedence over username/password.
1 parent ddd1954 commit 3b68c0f

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

elasticsearch.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type Config struct {
3030
Password string // Password for HTTP Basic Authentication.
3131

3232
CloudID string // Endpoint for the Elastic Service (https://elastic.co/cloud).
33+
APIKey string // Base64-encoded token for authorization; if set, overrides username and password.
34+
3335
Transport http.RoundTripper // The HTTP transport object.
3436
Logger estransport.Logger // The logger object.
3537
}
@@ -108,6 +110,7 @@ func NewClient(cfg Config) (*Client, error) {
108110
URLs: urls,
109111
Username: cfg.Username,
110112
Password: cfg.Password,
113+
APIKey: cfg.APIKey,
111114

112115
Transport: cfg.Transport,
113116
Logger: cfg.Logger,

estransport/estransport.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Config struct {
3939
URLs []*url.URL
4040
Username string
4141
Password string
42+
APIKey string
4243

4344
Transport http.RoundTripper
4445
Logger Logger
@@ -50,6 +51,7 @@ type Client struct {
5051
urls []*url.URL
5152
username string
5253
password string
54+
apikey string
5355

5456
transport http.RoundTripper
5557
selector Selector
@@ -69,6 +71,7 @@ func New(cfg Config) *Client {
6971
urls: cfg.URLs,
7072
username: cfg.Username,
7173
password: cfg.Password,
74+
apikey: cfg.APIKey,
7275

7376
transport: cfg.Transport,
7477
selector: NewRoundRobinSelector(cfg.URLs...),
@@ -89,7 +92,7 @@ func (c *Client) Perform(req *http.Request) (*http.Response, error) {
8992
c.setUserAgent(req)
9093

9194
if _, ok := req.Header["Authorization"]; !ok {
92-
c.setBasicAuth(u, req)
95+
c.setAuthorization(u, req)
9396
}
9497

9598
var dupReqBody *bytes.Buffer
@@ -154,13 +157,22 @@ func (c *Client) setURL(u *url.URL, req *http.Request) *http.Request {
154157
return req
155158
}
156159

157-
func (c *Client) setBasicAuth(u *url.URL, req *http.Request) *http.Request {
160+
func (c *Client) setAuthorization(u *url.URL, req *http.Request) *http.Request {
158161
if u.User != nil {
159162
password, _ := u.User.Password()
160163
req.SetBasicAuth(u.User.Username(), password)
161164
return req
162165
}
163166

167+
if c.apikey != "" {
168+
var b bytes.Buffer
169+
b.Grow(len("APIKey ") + len(c.apikey))
170+
b.WriteString("APIKey ")
171+
b.WriteString(c.apikey)
172+
req.Header.Set("Authorization", b.String())
173+
return req
174+
}
175+
164176
if c.username != "" && c.password != "" {
165177
req.SetBasicAuth(c.username, c.password)
166178
return req

estransport/estransport_internal_test.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestTransportPerform(t *testing.T) {
9797
tp := New(Config{URLs: []*url.URL{u}})
9898

9999
req, _ := http.NewRequest("GET", "/", nil)
100-
tp.setBasicAuth(u, req)
100+
tp.setAuthorization(u, req)
101101

102102
username, password, ok := req.BasicAuth()
103103
if !ok {
@@ -114,7 +114,7 @@ func TestTransportPerform(t *testing.T) {
114114
tp := New(Config{URLs: []*url.URL{u}, Username: "foo", Password: "bar"})
115115

116116
req, _ := http.NewRequest("GET", "/", nil)
117-
tp.setBasicAuth(u, req)
117+
tp.setAuthorization(u, req)
118118

119119
username, password, ok := req.BasicAuth()
120120
if !ok {
@@ -126,6 +126,23 @@ func TestTransportPerform(t *testing.T) {
126126
}
127127
})
128128

129+
t.Run("Sets APIKey Authentication from configuration", func(t *testing.T) {
130+
u, _ := url.Parse("http://example.com")
131+
tp := New(Config{URLs: []*url.URL{u}, APIKey: "Zm9vYmFy"}) // foobar
132+
133+
req, _ := http.NewRequest("GET", "/", nil)
134+
tp.setAuthorization(u, req)
135+
136+
value := req.Header.Get("Authorization")
137+
if value == "" {
138+
t.Errorf("Expected the request to have the Authorization header set")
139+
}
140+
141+
if value != "APIKey Zm9vYmFy" {
142+
t.Errorf(`Unexpected value for Authorization: want="APIKey Zm9vYmFy", got="%s"`, value)
143+
}
144+
})
145+
129146
t.Run("Sets UserAgent", func(t *testing.T) {
130147
u, _ := url.Parse("http://example.com")
131148
tp := New(Config{URLs: []*url.URL{u}})

0 commit comments

Comments
 (0)