Auth with global secret for admin endpoints

This commit is contained in:
simon987 2019-03-09 13:05:31 -05:00
parent e2ba51b77a
commit b095c92cfd
5 changed files with 118 additions and 14 deletions

View File

@ -7,9 +7,32 @@
| `WS_BUCKET_LOGLEVEL` | `trace` |
| `WS_BUCKET_CONNSTR` | `host=localhost user=ws_bucket dbname=ws_bucket password=ws_bucket sslmode=disable` |
| `WS_BUCKET_DIALECT` | `postgres` |
| `WS_BUCKET_SECRET` | `default_secret`* |
\* You should change this value!
### Running tests
```bash
export WS_BUCKET_ADDR=0.0.0.0:3021
export WS_BUCKET_WORKDIR=.
cd test/
go test
```
```
### Auth
Administration endpoints require HMAC_SHA256 authentication.
Request header:
```
{
"Timestamp": <Current time (RFC1123)>
"X-Signature": <HMAC_SHA256(BODY + TIMESTAMP)>
}
```
Upload endpoint requires a valid upload token:
```
{
"X-Upload-Token": <token>
}
```

View File

@ -1 +1,64 @@
package api
import (
"bytes"
"crypto"
"crypto/hmac"
"encoding/hex"
"errors"
"github.com/valyala/fasthttp"
"math"
"os"
"time"
)
var Secret = []byte(getApiSecret())
func getApiSecret() string {
secret := os.Getenv("WS_BUCKET_SECRET")
if secret == "" {
return "default_secret"
} else {
return secret
}
}
func validateRequest(ctx *fasthttp.RequestCtx) error {
signature := ctx.Request.Header.Peek("X-Signature")
timeStampStr := string(ctx.Request.Header.Peek("Timestamp"))
if timeStampStr == "" {
return errors.New("date is not specified")
}
timestamp, err := time.Parse(time.RFC1123, timeStampStr)
if err != nil {
return err
}
if math.Abs(float64(timestamp.Unix()-time.Now().Unix())) > 60 {
return errors.New("invalid Timestamp")
}
var body []byte
if ctx.Request.Header.IsGet() {
body = ctx.Request.RequestURI()
} else {
body = ctx.Request.Body()
}
mac := hmac.New(crypto.SHA256.New, Secret)
mac.Write(body)
mac.Write([]byte(timeStampStr))
expectedMac := make([]byte, 64)
hex.Encode(expectedMac, mac.Sum(nil))
matches := bytes.Compare(expectedMac, signature) == 0
if !matches {
return errors.New("signature does not match")
}
return nil
}

View File

@ -7,7 +7,8 @@ import (
)
type GenericResponse struct {
Ok bool `json:"ok"`
Ok bool `json:"ok"`
Message string `json:"message,omitempty"`
}
type AllocateUploadSlotRequest struct {

View File

@ -22,10 +22,18 @@ var upgrader = websocket.FastHTTPUpgrader{
func (api *WebApi) AllocateUploadSlot(ctx *fasthttp.RequestCtx) {
//todo auth
err := validateRequest(ctx)
if err != nil {
ctx.Response.Header.SetStatusCode(401)
Json(GenericResponse{
Ok: false,
Message: err.Error(),
}, ctx)
return
}
req := &AllocateUploadSlotRequest{}
err := json.Unmarshal(ctx.Request.Body(), req)
err = json.Unmarshal(ctx.Request.Body(), req)
if err != nil {
ctx.Response.Header.SetStatusCode(400)
Json(GenericResponse{

View File

@ -2,11 +2,15 @@ package test
import (
"bytes"
"crypto"
"crypto/hmac"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/simon987/ws_bucket/api"
"io/ioutil"
"net/http"
"time"
)
func Post(path string, x interface{}) *http.Response {
@ -19,16 +23,13 @@ func Post(path string, x interface{}) *http.Response {
req, err := http.NewRequest("POST", "http://"+api.GetServerAddress()+path, buf)
handleErr(err)
//ts := time.Now().Format(time.RFC1123)
//
//mac := hmac.New(crypto.SHA256.New, worker.Secret)
//mac.Write(body)
//mac.Write([]byte(ts))
//sig := hex.EncodeToString(mac.Sum(nil))
//
//req.Header.Add("X-Worker-Id", strconv.FormatInt(worker.Id, 10))
//req.Header.Add("X-Signature", sig)
//req.Header.Add("Timestamp", ts)
ts := time.Now().Format(time.RFC1123)
mac := hmac.New(crypto.SHA256.New, []byte("default_secret"))
mac.Write(body)
mac.Write([]byte(ts))
sig := hex.EncodeToString(mac.Sum(nil))
req.Header.Add("X-Signature", sig)
req.Header.Add("Timestamp", ts)
r, err := s.Do(req)
handleErr(err)
@ -43,6 +44,14 @@ func Get(path string, token string) *http.Response {
req, err := http.NewRequest("GET", "http://"+api.GetServerAddress()+path, nil)
handleErr(err)
ts := time.Now().Format(time.RFC1123)
mac := hmac.New(crypto.SHA256.New, []byte("default_secret"))
mac.Write([]byte(path))
mac.Write([]byte(ts))
sig := hex.EncodeToString(mac.Sum(nil))
req.Header.Add("X-Signature", sig)
req.Header.Add("Timestamp", ts)
req.Header.Set("X-Upload-Token", token)
r, err := s.Do(req)