Skip to content

Commit

Permalink
key authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
cjimti committed May 13, 2019
1 parent ffe400c commit 49b8cc5
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 10 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ The fields in the data sent to [txn2/rxtx] should match the fields described in
Run **query** from source. Configure it to use the services running from docker-compose above.

```bash
go run ./cmd/query.go --esServer=http://localhost:9200 --tokenKey="somegoodkey"
go run ./cmd/query.go --esServer=http://localhost:9200 --provisionServer=http://localhost:8070 --tokenKey="somesharedkey"
```

### Run a [Query]:
Expand Down Expand Up @@ -214,6 +214,13 @@ curl -X GET \
-H "Authorization: Bearer $TOKEN"
```

### Execute a [Query] with BasicAuth using an [Account] [AccessKey]:
```bash
curl -X GET \
http://localhost:8080/exec/test/count_some_metrics \
-H 'Authorization: Basic dGVzdDpQRFdnWXIzYlFHTm9McHRCUkRrTFRHUWNSbUNNcUxHUkZwWG9YSjh4TVBzTUxNZzNMSHZXcEpnRHUydjNMWUJB'
```

[Token]: https://github.com/txn2/token
[txn2/provision]: https://github.com/txn2/provision
[txn2/tm]: https://github.com/txn2/tm
Expand All @@ -228,6 +235,7 @@ curl -X GET \
[Cerebro]: https://github.com/lmenezes/cerebro
[Logstash]: https://www.elastic.co/products/logstash
[docker-compose.yml]: docker-compose.yml
[AccessKey]: https://godoc.org/github.com/txn2/provision#AccessKey

## Release Packaging

Expand Down
104 changes: 97 additions & 7 deletions cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,40 @@
package main

import (
"bytes"
"flag"
"fmt"
"net/http"
"os"
"strconv"
"time"

"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/json"
"github.com/patrickmn/go-cache"
"github.com/txn2/ack"
"github.com/txn2/micro"
"github.com/txn2/provision"
"github.com/txn2/query"
"go.uber.org/zap"
)

var (
elasticServerEnv = getEnv("ELASTIC_SERVER", "http://elasticsearch:9200")
elasticServerEnv = getEnv("ELASTIC_SERVER", "http://elasticsearch:9200")
provisionServerEnv = getEnv("PROVISION_SERVER", "http://provision:8070")
authCacheEnv = getEnv("AUTH_CACHE", "60")
)

func main() {
authCacheInt, err := strconv.Atoi(authCacheEnv)
if err != nil {
fmt.Println("Parsing error, AUTH_CACHE must be an integer in seconds.")
os.Exit(1)
}

esServer := flag.String("esServer", elasticServerEnv, "Elasticsearch Server")
provisionServer := flag.String("provisionServer", provisionServerEnv, "Provision Server (txn2/provision)")
authCache := flag.Int("authCache", authCacheInt, "Seconds to cache key (BasicAuth) authentication.")

serverCfg, _ := micro.NewServerCfg("Query")
server := micro.NewServer(serverCfg)
Expand All @@ -40,36 +60,106 @@ func main() {
os.Exit(1)
}

// setup authentication cache
csh := cache.New(time.Duration(*authCache)*time.Second, 10*time.Minute)

accessHandler := func(checkAdmin bool) gin.HandlerFunc {
return func(c *gin.Context) {

// check for basic auth first. if found, bypass token check
// basic auth requires a network hit to provision, to
// reduce latency in future calls cache results for a time
name, key, ok := c.Request.BasicAuth()
if ok {

cacheKey := name + key
// check cache
cacheResult, found := csh.Get(cacheKey)
if found {
if cacheResult.(bool) {
return
}

ak := ack.Gin(c)
ak.SetPayload("Unauthorized via cache.")
ak.GinErrorAbort(401, "E401", "UnauthorizedFailure")

return
}

accessKey := provision.AccessKey{
Name: name,
Key: key,
}

url := fmt.Sprintf("%s/keyCheck/%s", *provisionServer, c.Param("account"))
server.Logger.Debug("Authenticating BasicAuth with AccessKey", zap.String("url", url))

payload, _ := json.Marshal(accessKey)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
req.Header.Add("Content-Type", "application/json")

res, err := server.Client.Http.Do(req)
if err != nil {
ak := ack.Gin(c)
ak.SetPayload("Error contacting provision service.")
ak.GinErrorAbort(500, "E500", err.Error())
csh.Set(cacheKey, false, cache.DefaultExpiration)
return
}

if res.StatusCode != 200 {
ak := ack.Gin(c)
ak.SetPayload("Unable to authenticate using BasicAuth.")
ak.GinErrorAbort(res.StatusCode, "E"+strconv.Itoa(res.StatusCode), "AuthenticationFailure")
csh.Set(cacheKey, false, cache.DefaultExpiration)
return
}

csh.Set(cacheKey, true, cache.DefaultExpiration)
return
}

// Load token
tokenHandler := provision.UserTokenHandler()
tokenHandler(c)

// Check token
tokenCheck := provision.AccountAccessCheckHandler(checkAdmin)
tokenCheck(c)
}
}

// User token middleware
server.Router.Use(provision.UserTokenHandler())
//server.Router.Use()

// run a query (one-off operation for running or testing queries"
server.Router.POST("run/:account",
provision.AccountAccessCheckHandler(false),
accessHandler(false),
qApi.RunQueryHandler,
)

// Execute a query
server.Router.GET("exec/:account/:id",
provision.AccountAccessCheckHandler(false),
accessHandler(false),
qApi.ExecuteQueryHandler,
)

// Upsert a query
server.Router.POST("upsert/:account",
provision.AccountAccessCheckHandler(true),
accessHandler(true),
qApi.UpsertQueryHandler,
)

// Get a query
server.Router.GET("get/:account/:id",
provision.AccountAccessCheckHandler(false),
accessHandler(false),
qApi.GetQueryHandler,
)

// Search for queries
server.Router.POST("search/:account",
provision.AccountAccessCheckHandler(false),
accessHandler(false),
qApi.SearchQueryHandler,
)

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ services:
- IP=0.0.0.0
- PORT=8070
- TOKEN_EXP=1440
- TOKEN_KEY=somegoodkey
- TOKEN_KEY=somesharedkey
- AGENT=DockerCompose
- SERVICE_ENV=local
ports:
Expand Down Expand Up @@ -108,7 +108,7 @@ services:
- IP=0.0.0.0
- PORT=8080
- TOKEN_EXP=1440
- TOKEN_KEY=somegoodkey
- TOKEN_KEY=somesharedkey
- AGENT="DockerCompose"
- SERVICE_ENV="local"
ports:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.12

require (
github.com/gin-gonic/gin v1.3.0
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/txn2/ack v1.8.2
github.com/txn2/es v1.3.5
github.com/txn2/micro v0.0.5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down

0 comments on commit 49b8cc5

Please sign in to comment.