Skip to content

Commit

Permalink
More rework
Browse files Browse the repository at this point in the history
  • Loading branch information
bruce-riley committed Oct 11, 2023
1 parent 8cf7462 commit 93b59cf
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 16 deletions.
8 changes: 4 additions & 4 deletions node/cmd/ccq/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (s *httpServer) handleQuery(w http.ResponseWriter, r *http.Request) {
apiKey, exists := r.Header["X-Api-Key"]
if !exists || len(apiKey) != 1 {
s.logger.Debug("received a request without an api key", zap.Stringer("url", r.URL), zap.Error(err))
http.Error(w, "api key is missing", http.StatusBadRequest)
http.Error(w, "api key is missing", http.StatusUnauthorized)
return
}

Expand All @@ -84,9 +84,9 @@ func (s *httpServer) handleQuery(w http.ResponseWriter, r *http.Request) {
Signature: signature,
}

if err := validateRequest(s.logger, s.env, s.permissions, s.signerKey, apiKey[0], signedQueryRequest); err != nil {
if status, err := validateRequest(s.logger, s.env, s.permissions, s.signerKey, apiKey[0], signedQueryRequest); err != nil {
// Don't need to log here because the details were logged in the function.
http.Error(w, err.Error(), http.StatusBadRequest)
http.Error(w, err.Error(), status)
return
}

Expand All @@ -106,7 +106,7 @@ func (s *httpServer) handleQuery(w http.ResponseWriter, r *http.Request) {
pendingResponse := NewPendingResponse(signedQueryRequest)
added := s.pendingResponses.Add(pendingResponse)
if !added {
http.Error(w, "Duplicate request", http.StatusInternalServerError)
http.Error(w, "Duplicate request", http.StatusBadRequest)
return
}

Expand Down
25 changes: 13 additions & 12 deletions node/cmd/ccq/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
Expand Down Expand Up @@ -174,13 +175,13 @@ func parseConfig(byteValue []byte) (Permissions, error) {
return ret, nil
}

// validateRequest verifies that this API key is allowed to do all of the calls in this request.
func validateRequest(logger *zap.Logger, env common.Environment, perms Permissions, signerKey *ecdsa.PrivateKey, apiKey string, qr *gossipv1.SignedQueryRequest) error {
// validateRequest verifies that this API key is allowed to do all of the calls in this request. In the case of an error, it returns the HTTP status.
func validateRequest(logger *zap.Logger, env common.Environment, perms Permissions, signerKey *ecdsa.PrivateKey, apiKey string, qr *gossipv1.SignedQueryRequest) (int, error) {
apiKey = strings.ToLower(apiKey)
permsForUser, exists := perms[strings.ToLower(apiKey)]
if !exists {
logger.Debug("invalid api key", zap.String("apiKey", apiKey))
return fmt.Errorf("invalid api key")
return http.StatusForbidden, fmt.Errorf("invalid api key")
}

// TODO: Should we verify the signatures?
Expand All @@ -192,7 +193,7 @@ func validateRequest(logger *zap.Logger, env common.Environment, perms Permissio
zap.Bool("allowUnsigned", permsForUser.allowUnsigned),
zap.Bool("signerKeyConfigured", signerKey != nil),
)
return fmt.Errorf("request not signed")
return http.StatusBadRequest, fmt.Errorf("request not signed")
}

// Sign the request using our key.
Expand All @@ -201,21 +202,21 @@ func validateRequest(logger *zap.Logger, env common.Environment, perms Permissio
qr.Signature, err = ethCrypto.Sign(digest.Bytes(), signerKey)
if err != nil {
logger.Debug("failed to sign request", zap.String("userName", permsForUser.userName), zap.Error(err))
return fmt.Errorf("failed to sign request: %w", err)
return http.StatusInternalServerError, fmt.Errorf("failed to sign request: %w", err)
}
}

var queryRequest query.QueryRequest
err := queryRequest.Unmarshal(qr.QueryRequest)
if err != nil {
logger.Debug("failed to unmarshal request", zap.String("userName", permsForUser.userName), zap.Error(err))
return fmt.Errorf("failed to unmarshal request: %w", err)
return http.StatusInternalServerError, fmt.Errorf("failed to unmarshal request: %w", err)
}

// Make sure the overall query request is sane.
if err := queryRequest.Validate(); err != nil {
logger.Debug("failed to validate request", zap.String("userName", permsForUser.userName), zap.Error(err))
return fmt.Errorf("failed to validate request: %w", err)
return http.StatusBadRequest, fmt.Errorf("failed to validate request: %w", err)
}

// Make sure they are allowed to make all of the calls that they are asking for.
Expand All @@ -226,25 +227,25 @@ func validateRequest(logger *zap.Logger, env common.Environment, perms Permissio
contractAddress, err := vaa.BytesToAddress(callData.To)
if err != nil {
logger.Debug("failed to parse contract address", zap.String("userName", permsForUser.userName), zap.String("contract", hex.EncodeToString(callData.To)), zap.Error(err))
return fmt.Errorf("failed to parse contract address: %w", err)
return http.StatusBadRequest, fmt.Errorf("failed to parse contract address: %w", err)
}
if len(callData.Data) < ETH_CALL_SIG_LENGTH {
logger.Debug("eth call data must be at least four bytes", zap.String("userName", permsForUser.userName), zap.String("data", hex.EncodeToString(callData.Data)))
return fmt.Errorf("eth call data must be at least four bytes")
return http.StatusBadRequest, fmt.Errorf("eth call data must be at least four bytes")
}
call := hex.EncodeToString(callData.Data[0:ETH_CALL_SIG_LENGTH])
callKey := fmt.Sprintf("ethCall:%d:%s:%s", pcq.ChainId, contractAddress, call)
if _, exists := permsForUser.allowedCalls[callKey]; !exists {
logger.Debug("requested call not authorized", zap.String("userName", permsForUser.userName), zap.String("callKey", callKey))
return fmt.Errorf(`call "%s" not authorized`, callKey)
return http.StatusBadRequest, fmt.Errorf(`call "%s" not authorized`, callKey)
}
}
default:
logger.Debug("unsupported query type", zap.String("userName", permsForUser.userName), zap.Any("type", pcq.Query))
return fmt.Errorf("unsupported query type")
return http.StatusBadRequest, fmt.Errorf("unsupported query type")
}
}

logger.Debug("submitting query request", zap.String("userName", permsForUser.userName))
return nil
return http.StatusOK, nil
}

0 comments on commit 93b59cf

Please sign in to comment.