mirror of
https://github.com/simon987/ws_bucket.git
synced 2025-04-19 18:26:45 +00:00
Auth with global secret for admin endpoints
This commit is contained in:
parent
e2ba51b77a
commit
b095c92cfd
23
README.md
23
README.md
@ -7,9 +7,32 @@
|
|||||||
| `WS_BUCKET_LOGLEVEL` | `trace` |
|
| `WS_BUCKET_LOGLEVEL` | `trace` |
|
||||||
| `WS_BUCKET_CONNSTR` | `host=localhost user=ws_bucket dbname=ws_bucket password=ws_bucket sslmode=disable` |
|
| `WS_BUCKET_CONNSTR` | `host=localhost user=ws_bucket dbname=ws_bucket password=ws_bucket sslmode=disable` |
|
||||||
| `WS_BUCKET_DIALECT` | `postgres` |
|
| `WS_BUCKET_DIALECT` | `postgres` |
|
||||||
|
| `WS_BUCKET_SECRET` | `default_secret`* |
|
||||||
|
|
||||||
|
\* You should change this value!
|
||||||
|
|
||||||
### Running tests
|
### Running tests
|
||||||
```bash
|
```bash
|
||||||
|
export WS_BUCKET_ADDR=0.0.0.0:3021
|
||||||
|
export WS_BUCKET_WORKDIR=.
|
||||||
|
|
||||||
cd test/
|
cd test/
|
||||||
go 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>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
63
api/auth.go
63
api/auth.go
@ -1 +1,64 @@
|
|||||||
package api
|
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
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
type GenericResponse struct {
|
type GenericResponse struct {
|
||||||
Ok bool `json:"ok"`
|
Ok bool `json:"ok"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllocateUploadSlotRequest struct {
|
type AllocateUploadSlotRequest struct {
|
||||||
|
12
api/slot.go
12
api/slot.go
@ -22,10 +22,18 @@ var upgrader = websocket.FastHTTPUpgrader{
|
|||||||
|
|
||||||
func (api *WebApi) AllocateUploadSlot(ctx *fasthttp.RequestCtx) {
|
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{}
|
req := &AllocateUploadSlotRequest{}
|
||||||
err := json.Unmarshal(ctx.Request.Body(), req)
|
err = json.Unmarshal(ctx.Request.Body(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Response.Header.SetStatusCode(400)
|
ctx.Response.Header.SetStatusCode(400)
|
||||||
Json(GenericResponse{
|
Json(GenericResponse{
|
||||||
|
@ -2,11 +2,15 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/hmac"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/simon987/ws_bucket/api"
|
"github.com/simon987/ws_bucket/api"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Post(path string, x interface{}) *http.Response {
|
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)
|
req, err := http.NewRequest("POST", "http://"+api.GetServerAddress()+path, buf)
|
||||||
handleErr(err)
|
handleErr(err)
|
||||||
|
|
||||||
//ts := time.Now().Format(time.RFC1123)
|
ts := time.Now().Format(time.RFC1123)
|
||||||
//
|
mac := hmac.New(crypto.SHA256.New, []byte("default_secret"))
|
||||||
//mac := hmac.New(crypto.SHA256.New, worker.Secret)
|
mac.Write(body)
|
||||||
//mac.Write(body)
|
mac.Write([]byte(ts))
|
||||||
//mac.Write([]byte(ts))
|
sig := hex.EncodeToString(mac.Sum(nil))
|
||||||
//sig := hex.EncodeToString(mac.Sum(nil))
|
req.Header.Add("X-Signature", sig)
|
||||||
//
|
req.Header.Add("Timestamp", ts)
|
||||||
//req.Header.Add("X-Worker-Id", strconv.FormatInt(worker.Id, 10))
|
|
||||||
//req.Header.Add("X-Signature", sig)
|
|
||||||
//req.Header.Add("Timestamp", ts)
|
|
||||||
|
|
||||||
r, err := s.Do(req)
|
r, err := s.Do(req)
|
||||||
handleErr(err)
|
handleErr(err)
|
||||||
@ -43,6 +44,14 @@ func Get(path string, token string) *http.Response {
|
|||||||
req, err := http.NewRequest("GET", "http://"+api.GetServerAddress()+path, nil)
|
req, err := http.NewRequest("GET", "http://"+api.GetServerAddress()+path, nil)
|
||||||
handleErr(err)
|
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)
|
req.Header.Set("X-Upload-Token", token)
|
||||||
|
|
||||||
r, err := s.Do(req)
|
r, err := s.Do(req)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user