Skip to content

Commit

Permalink
Support alternative auth mechanisms (#15)
Browse files Browse the repository at this point in the history
With this commit we add support for two alternatives to user/password
based authentication:

* API keys
* Service account tokens

Closes #12
  • Loading branch information
danielmitterdorfer authored Nov 24, 2023
1 parent dfe16c5 commit 35b1bae
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 19 deletions.
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,34 @@ This [Dockerfile](./Dockerfile) builds a docker image with the k6 binary.

## Configuration

### Running on Elastic Cloud
### Running in Production

> [!NOTE]
> The examples below use Elastic Cloud, which allows to connect via `K6_ELASTICSEARCH_CLOUD_ID`. Alternatively you can also specify the connection URL with `K6_ELASTICSEARCH_URL`.
You can run the new k6 binary against a Cloud cluster with:
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_USER=elastic
export K6_ELASTICSEARCH_PASSWORD=your-password-here

./k6 run script.js -o output-elasticsearch
./k6 run ./examples/script.js -o output-elasticsearch
```

or alternatively via an [API key](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html) (see also how to [create an API key in Kibana](https://www.elastic.co/guide/en/kibana/current/api-keys.html)):
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_API_KEY=your-base64-encoded-api-key-here

./k6 run ./examples/script.js -o output-elasticsearch
```

or a [service account token](https://www.elastic.co/guide/en/elasticsearch/reference/current/service-accounts.html#service-accounts-tokens):
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN=your-service-account-token-here

./k6 run ./examples/script.js -o output-elasticsearch
```

### Running a local cluster
Expand Down
51 changes: 37 additions & 14 deletions pkg/esoutput/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,25 @@ type Config struct {
CACert null.String `json:"caCertFile" envconfig:"K6_ELASTICSEARCH_CA_CERT_FILE"`
InsecureSkipVerify null.Bool `json:"insecureSkipVerify" envconfig:"K6_ELASTICSEARCH_INSECURE_SKIP_VERIFY"`

User null.String `json:"user" envconfig:"K6_ELASTICSEARCH_USER"`
Password null.String `json:"password" envconfig:"K6_ELASTICSEARCH_PASSWORD"`
User null.String `json:"user" envconfig:"K6_ELASTICSEARCH_USER"`
Password null.String `json:"password" envconfig:"K6_ELASTICSEARCH_PASSWORD"`
APIKey null.String `json:"apiKey" envconfig:"K6_ELASTICSEARCH_API_KEY"`
ServiceAccountToken null.String `json:"serviceAccountToken" envconfig:"K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN"`

FlushPeriod types.NullDuration `json:"flushPeriod" envconfig:"K6_ELASTICSEARCH_FLUSH_PERIOD"`
}

func NewConfig() Config {
return Config{
Url: null.StringFrom("http://localhost:9200"),
CloudID: null.NewString("", false),
CACert: null.NewString("", false),
InsecureSkipVerify: null.BoolFrom(false),
User: null.NewString("", false),
Password: null.NewString("", false),
FlushPeriod: types.NullDurationFrom(defaultFlushPeriod),
Url: null.StringFrom("http://localhost:9200"),
CloudID: null.NewString("", false),
APIKey: null.NewString("", false),
CACert: null.NewString("", false),
InsecureSkipVerify: null.BoolFrom(false),
User: null.NewString("", false),
Password: null.NewString("", false),
ServiceAccountToken: null.NewString("", false),
FlushPeriod: types.NullDurationFrom(defaultFlushPeriod),
}
}

Expand All @@ -71,6 +75,9 @@ func (base Config) Apply(applied Config) Config {
if applied.CloudID.Valid {
base.CloudID = applied.CloudID
}
if applied.APIKey.Valid {
base.APIKey = applied.APIKey
}

if applied.CACert.Valid {
base.CACert = applied.CACert
Expand All @@ -87,6 +94,10 @@ func (base Config) Apply(applied Config) Config {
base.Password = applied.Password
}

if applied.ServiceAccountToken.Valid {
base.ServiceAccountToken = applied.ServiceAccountToken
}

if applied.FlushPeriod.Valid {
base.FlushPeriod = applied.FlushPeriod
}
Expand Down Expand Up @@ -125,6 +136,12 @@ func ParseArg(arg string) (Config, error) {
if v, ok := params["password"].(string); ok {
c.Password = null.StringFrom(v)
}
if v, ok := params["apiKey"].(string); ok {
c.APIKey = null.StringFrom(v)
}
if v, ok := params["serviceAccountToken"].(string); ok {
c.ServiceAccountToken = null.StringFrom(v)
}

if v, ok := params["flushPeriod"].(string); ok {
if err := c.FlushPeriod.UnmarshalText([]byte(v)); err != nil {
Expand Down Expand Up @@ -165,15 +182,15 @@ func GetConsolidatedConfig(jsonRawConf json.RawMessage, env map[string]string, a
}
}

if url, urlDefined := env["K6_ELASTICSEARCH_URL"]; urlDefined {
if url, defined := env["K6_ELASTICSEARCH_URL"]; defined {
result.Url = null.StringFrom(url)
}

if cloudId, cloudIdDefined := env["K6_ELASTICSEARCH_CLOUD_ID"]; cloudIdDefined {
if cloudId, defined := env["K6_ELASTICSEARCH_CLOUD_ID"]; defined {
result.CloudID = null.StringFrom(cloudId)
}

if ca, caDefined := env["K6_ELASTICSEARCH_CA_CERT_FILE"]; caDefined {
if ca, defined := env["K6_ELASTICSEARCH_CA_CERT_FILE"]; defined {
result.CACert = null.StringFrom(ca)
}

Expand All @@ -185,13 +202,19 @@ func GetConsolidatedConfig(jsonRawConf json.RawMessage, env map[string]string, a
}
}

if user, userDefined := env["K6_ELASTICSEARCH_USER"]; userDefined {
if user, defined := env["K6_ELASTICSEARCH_USER"]; defined {
result.User = null.StringFrom(user)
}

if password, passwordDefined := env["K6_ELASTICSEARCH_PASSWORD"]; passwordDefined {
if password, defined := env["K6_ELASTICSEARCH_PASSWORD"]; defined {
result.Password = null.StringFrom(password)
}
if apiKey, defined := env["K6_ELASTICSEARCH_API_KEY"]; defined {
result.APIKey = null.StringFrom(apiKey)
}
if serviceAccountToken, defined := env["K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN"]; defined {
result.ServiceAccountToken = null.StringFrom(serviceAccountToken)
}

if arg != "" {
argConf, err := ParseArg(arg)
Expand Down
12 changes: 9 additions & 3 deletions pkg/esoutput/esoutput.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import (
_ "embed"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"

Expand Down Expand Up @@ -80,7 +80,7 @@ func New(params output.Params) (output.Output, error) {

var esConfig es.Config

// Cloud id takes precendence over a URL (which is localhost by default)
// Cloud id takes precedence over a URL (which is localhost by default)
if config.CloudID.Valid {
esConfig.CloudID = config.CloudID.String
} else if config.Url.Valid {
Expand All @@ -92,8 +92,14 @@ func New(params output.Params) (output.Output, error) {
if config.Password.Valid {
esConfig.Password = config.Password.String
}
if config.APIKey.Valid {
esConfig.APIKey = config.APIKey.String
}
if config.ServiceAccountToken.Valid {
esConfig.ServiceToken = config.ServiceAccountToken.String
}
if config.CACert.Valid {
cert, err := ioutil.ReadFile(config.CACert.String)
cert, err := os.ReadFile(config.CACert.String)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 35b1bae

Please sign in to comment.