bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/pkg/apiserver/middlewares/v1/api_key.go (about)

     1  package v1
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/sha512"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"net/http"
     9  	"strings"
    10  
    11  	"bitbucket.org/Aishee/synsec/pkg/database"
    12  	"bitbucket.org/Aishee/synsec/pkg/types"
    13  	"github.com/gin-gonic/gin"
    14  	log "github.com/sirupsen/logrus"
    15  )
    16  
    17  var (
    18  	APIKeyHeader = "X-Api-Key"
    19  )
    20  
    21  type APIKey struct {
    22  	HeaderName string
    23  	DbClient   *database.Client
    24  }
    25  
    26  func GenerateAPIKey(n int) (string, error) {
    27  	bytes := make([]byte, n)
    28  	if _, err := rand.Read(bytes); err != nil {
    29  		return "", err
    30  	}
    31  	return hex.EncodeToString(bytes), nil
    32  }
    33  
    34  func NewAPIKey(dbClient *database.Client) *APIKey {
    35  	return &APIKey{
    36  		HeaderName: APIKeyHeader,
    37  		DbClient:   dbClient,
    38  	}
    39  }
    40  
    41  func HashSHA512(str string) string {
    42  	hashedKey := sha512.New()
    43  	hashedKey.Write([]byte(str))
    44  
    45  	hashStr := fmt.Sprintf("%x", hashedKey.Sum(nil))
    46  
    47  	return hashStr
    48  }
    49  
    50  func (a *APIKey) MiddlewareFunc() gin.HandlerFunc {
    51  	return func(c *gin.Context) {
    52  		defer types.CatchPanic("synsec/middlewaresV1/api_key/MiddlewareFunc")
    53  		val, ok := c.Request.Header[APIKeyHeader]
    54  		if !ok {
    55  			c.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})
    56  			c.Abort()
    57  			return
    58  		}
    59  
    60  		hashStr := HashSHA512(val[0])
    61  		bouncer, err := a.DbClient.SelectBouncer(hashStr)
    62  		if err != nil {
    63  			log.Errorf("auth api key error: %s", err)
    64  			c.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})
    65  			c.Abort()
    66  			return
    67  		}
    68  
    69  		if bouncer == nil {
    70  			c.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})
    71  			c.Abort()
    72  			return
    73  		}
    74  
    75  		c.Set("BOUNCER_NAME", bouncer.Name)
    76  
    77  		if bouncer.IPAddress == "" {
    78  			err = a.DbClient.UpdateBouncerIP(c.ClientIP(), bouncer.ID)
    79  			if err != nil {
    80  				log.Errorf("Failed to update ip address for '%s': %s\n", bouncer.Name, err)
    81  				c.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})
    82  				c.Abort()
    83  				return
    84  			}
    85  		}
    86  
    87  		if bouncer.IPAddress != c.ClientIP() && bouncer.IPAddress != "" {
    88  			log.Warningf("new IP address detected for bouncer '%s': %s (old: %s)", bouncer.Name, c.ClientIP(), bouncer.IPAddress)
    89  			err = a.DbClient.UpdateBouncerIP(c.ClientIP(), bouncer.ID)
    90  			if err != nil {
    91  				log.Errorf("Failed to update ip address for '%s': %s\n", bouncer.Name, err)
    92  				c.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})
    93  				c.Abort()
    94  				return
    95  			}
    96  		}
    97  
    98  		useragent := strings.Split(c.Request.UserAgent(), "/")
    99  
   100  		if len(useragent) != 2 {
   101  			log.Warningf("bad user agent '%s' from '%s'", c.Request.UserAgent(), c.ClientIP())
   102  			useragent = []string{c.Request.UserAgent(), "N/A"}
   103  		}
   104  
   105  		if err := a.DbClient.UpdateBouncerTypeAndVersion(useragent[0], useragent[1], bouncer.ID); err != nil {
   106  			log.Errorf("failed to update bouncer version and type from '%s' (%s): %s", c.Request.UserAgent(), c.ClientIP(), err)
   107  			c.JSON(http.StatusForbidden, gin.H{"message": "bad user agent"})
   108  			c.Abort()
   109  			return
   110  		}
   111  
   112  		c.Next()
   113  	}
   114  }