Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(screener): fix screener http 502 #2650

Merged
merged 12 commits into from
May 30, 2024
63 changes: 28 additions & 35 deletions contrib/screener-api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"time"
Expand Down Expand Up @@ -90,18 +91,27 @@
timestamp := fmt.Sprintf("%d", time.Now().Unix())
queryString := ""

signature := GenerateSignature(appsecret, appid, timestamp, nonce, queryString, body)
bodyBz, err := json.Marshal(body)
if err != nil {
return "", fmt.Errorf("error marshalling body: %w", err)

Check failure on line 96 in contrib/screener-api/client/client.go

View workflow job for this annotation

GitHub Actions / Lint (contrib/screener-api)

`marshalling` is a misspelling of `marshaling` (misspell)
trajan0x marked this conversation as resolved.
Show resolved Hide resolved
}
bodyStr := string(bodyBz)

message := fmt.Sprintf("%s%s%s%s%s%s%s",
appid, timestamp, nonce, "POST", BlacklistEndpoint, queryString, bodyStr)

signature := GenerateSignature(appsecret, message)

resp, err := c.rClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("appid", appid).
SetHeader("timestamp", timestamp).
SetHeader("nonce", nonce).
SetHeader("queryString", queryString).
SetHeader("signature", signature).
SetResult(&blacklistRes).
SetHeader("Appid", appid).
SetHeader("Timestamp", timestamp).
SetHeader("Nonce", nonce).
SetHeader("QueryString", queryString).
SetHeader("Signature", signature).
SetBody(body).
SetResult(&blacklistRes).
Post(BlacklistEndpoint)

if err != nil {
Expand All @@ -115,6 +125,17 @@
return blacklistRes.Status, nil
}

// GenerateSignature generates a signature for the request.
func GenerateSignature(
secret,
message string,
) string {
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(message))
return hex.EncodeToString(h.Sum(nil))
}

// NewNoOpClient creates a new no-op client for the Screener API.
// it returns false for every address.
func NewNoOpClient() (ScreenerClient, error) {
Expand All @@ -131,32 +152,4 @@
return "", nil
}

// GenerateSignature generates a signature for the request.
func GenerateSignature(secret string,
appid string,
timestamp string,
nonce string,
queryString string,
body BlackListBody,
) string {
key := []byte(secret)

// Concatenate the body.
message := fmt.Sprintf(
"%s%s%s%s%s%s%s",
appid,
timestamp,
nonce,
"POST",
BlacklistEndpoint,
queryString,
body,
)

h := hmac.New(sha256.New, key)
h.Write([]byte(message))

return strings.ToLower(hex.EncodeToString(h.Sum(nil)))
}

var _ ScreenerClient = noOpClient{}
40 changes: 18 additions & 22 deletions contrib/screener-api/screener/screener.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"sync"
Expand Down Expand Up @@ -93,8 +94,7 @@
screener.router.Use(screener.metrics.Gin())
screener.router.Handle(http.MethodGet, "/:ruleset/address/:address", screener.screenAddress)

screener.router.Handle(http.MethodPost, "/api/data/sync", screener.authMiddleware(cfg), screener.blacklistAddress)

screener.router.POST("/api/data/sync", screener.authMiddleware(cfg), screener.blacklistAddress)
screener.router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

return &screener, nil
Expand Down Expand Up @@ -190,6 +190,7 @@

case "update":
if err := s.db.UpdateBlacklistedAddress(c, blacklistedAddress.ID, blacklistedAddress); err != nil {
span.AddEvent("error", trace.WithAttributes(attribute.String("error", err.Error())))

Check warning on line 193 in contrib/screener-api/screener/screener.go

View check run for this annotation

Codecov / codecov/patch

contrib/screener-api/screener/screener.go#L193

Added line #L193 was not covered by tests
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
Expand All @@ -199,6 +200,7 @@

case "delete":
if err := s.db.DeleteBlacklistedAddress(c, blacklistedAddress.Address); err != nil {
span.AddEvent("error", trace.WithAttributes(attribute.String("error", err.Error())))

Check warning on line 203 in contrib/screener-api/screener/screener.go

View check run for this annotation

Codecov / codecov/patch

contrib/screener-api/screener/screener.go#L203

Added line #L203 was not covered by tests
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
Expand All @@ -207,6 +209,7 @@
return

default:
span.AddEvent("error", trace.WithAttributes(attribute.String("error", err.Error())))

Check warning on line 212 in contrib/screener-api/screener/screener.go

View check run for this annotation

Codecov / codecov/patch

contrib/screener-api/screener/screener.go#L212

Added line #L212 was not covered by tests
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid type"})
return
}
Expand All @@ -216,34 +219,27 @@
// compare it with the signature provided. If they match, the request is allowed to pass through.
func (s *screenerImpl) authMiddleware(cfg config.Config) gin.HandlerFunc {
return func(c *gin.Context) {
var blacklistBody client.BlackListBody
appID := c.Request.Header.Get("Appid")
timestamp := c.Request.Header.Get("Timestamp")
nonce := c.Request.Header.Get("Nonce")
signature := c.Request.Header.Get("Signature")

if err := c.ShouldBindBodyWith(&blacklistBody, binding.JSON); err != nil {
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
c.Abort()
return
}
bodyBytes, _ := io.ReadAll(c.Request.Body)
bodyString := string(bodyBytes)

appid := cfg.AppID
appsecret := cfg.AppSecret
c.Request.Body = io.NopCloser(strings.NewReader(bodyString))

nonce := c.GetHeader("nonce")
timestamp := c.GetHeader("timestamp")
queryString := c.GetHeader("queryString")
if nonce == "" || timestamp == "" || appid == "" {
c.JSON(http.StatusConflict, gin.H{"error": "missing headers"})
c.Abort()
return
}
message := fmt.Sprintf("%s%s%s%s%s%s",
appID, timestamp, nonce, "POST", client.BlacklistEndpoint, bodyString)

// reconstruct signature
expected := client.GenerateSignature(appsecret, appid, timestamp, nonce, queryString, blacklistBody)
expectedSignature := client.GenerateSignature(cfg.AppSecret, message)

if c.GetHeader("Signature") != expected {
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
if expectedSignature != signature {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid signature"})
c.Abort()
return
}

c.Next()
}
}
Expand Down
2 changes: 1 addition & 1 deletion contrib/screener-api/screener/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (s *ScreenerSuite) TestScreener() {
s.T().Setenv("TRM_URL", "")

cfg := config.Config{
AppSecret: "appsecret",
AppSecret: "secret",
AppID: "appid",
TRMKey: "",
Rulesets: map[string]config.RulesetConfig{
Expand Down
Loading