mirror of
				https://github.com/simon987/ws_bucket.git
				synced 2025-10-31 08:26:55 +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 | ||||||
|  | } | ||||||
|  | |||||||
| @ -7,7 +7,8 @@ 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