diff --git a/caboose.go b/caboose.go index 68f6b94..71178c7 100644 --- a/caboose.go +++ b/caboose.go @@ -24,7 +24,6 @@ import ( const ( SaturnEnvKey = "STRN_ENV_TAG" - OrchestratorJwtSecret = "JWT_SECRET" ) type Config struct { @@ -35,10 +34,6 @@ type Config struct { // OrchestratorOverride replaces calls to the orchestrator with a fixed response. OrchestratorOverride []tieredhashing.NodeInfo - // OrchestratorJwtSecret is an auth secret that allows for Caboose to make authenticated - // http requests to the orchestrator. - OrchestratorJwtSecret string - // LoggingEndpoint is the URL of the logging endpoint where we submit logs pertaining to our Saturn retrieval requests. LoggingEndpoint url.URL // LoggingClient is the HTTP client to use when communicating with the logging endpoint. @@ -216,10 +211,6 @@ func NewCaboose(config *Config) (*Caboose, error) { config.OrchestratorOverride = overrideNodes } - if jwtSecret := os.Getenv(OrchestratorJwtSecret); len(jwtSecret) > 0 { - config.OrchestratorJwtSecret = jwtSecret - } - c := Caboose{ config: config, pool: newPool(config), diff --git a/pool.go b/pool.go index 7b66d62..ad9356e 100644 --- a/pool.go +++ b/pool.go @@ -21,8 +21,6 @@ import ( "github.com/filecoin-saturn/caboose/tieredhashing" - "github.com/golang-jwt/jwt/v5" - "github.com/ipfs/boxo/path" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" @@ -33,33 +31,10 @@ const ( tierMainToUnknown = "main-to-unknown" tierUnknownToMain = "unknown-to-main" BackendOverrideKey = "CABOOSE_BACKEND_OVERRIDE" - CabooseJwtIssuer = "caboose-client" ) var sentinelCidReqTemplate = "/ipfs/%s?format=raw" -// authenticateReq adds authentication to a request when a JWT_SECRET is present as an environment variable. -func authenticateReq(req *http.Request, key string) (*http.Request, error) { - - claims := &jwt.MapClaims{ - "ExpiresAt": time.Now().Add(10 * time.Minute).Unix(), // Token expires after 10 minutes - "Issuer": CabooseJwtIssuer, - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - ss, err := token.SignedString([]byte(key)) - - if err != nil { - goLogger.Warnw("failed to generate JWT", "err", err) - return nil, err - } - - req.Header.Add("Authorization", "Bearer "+ss) - - return req, nil - -} - // loadPool refreshes the set of Saturn endpoints in the pool by fetching an updated list of responsive Saturn nodes from the // Saturn Orchestrator. func (p *pool) loadPool() ([]tieredhashing.NodeInfo, error) { @@ -67,7 +42,6 @@ func (p *pool) loadPool() ([]tieredhashing.NodeInfo, error) { if p.config.OrchestratorOverride != nil { return p.config.OrchestratorOverride, nil } - client := p.config.OrchestratorClient req, err := http.NewRequest("GET", p.config.OrchestratorEndpoint.String(), nil) @@ -76,15 +50,6 @@ func (p *pool) loadPool() ([]tieredhashing.NodeInfo, error) { goLogger.Warnw("failed to create request to orchestrator", "err", err, "endpoint", p.config.OrchestratorEndpoint) return nil, err } - - if len(p.config.OrchestratorJwtSecret) > 0 { - req, err = authenticateReq(req, p.config.OrchestratorJwtSecret) - if err != nil { - goLogger.Warnw("failed to authenticate request to orchestrator", "err", err, "endpoint", p.config.OrchestratorEndpoint) - return nil, err - } - } - resp, err := client.Do(req) if err != nil { diff --git a/pool_test.go b/pool_test.go index de5af1d..520fc2a 100644 --- a/pool_test.go +++ b/pool_test.go @@ -5,7 +5,6 @@ import ( "context" "crypto/tls" "encoding/json" - "fmt" "math/rand" "net/http" "net/http/httptest" @@ -17,7 +16,6 @@ import ( "unsafe" "github.com/filecoin-saturn/caboose/tieredhashing" - "github.com/golang-jwt/jwt/v5" "github.com/ipfs/go-cid" "github.com/ipld/go-car/v2" "github.com/ipld/go-ipld-prime" @@ -112,92 +110,33 @@ func TestPoolMiroring(t *testing.T) { func TestLoadPool(t *testing.T) { - t.Run("returns error if JWT generation fails", func(t *testing.T) { - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - - endpoint, _ := url.Parse(server.URL) - p := &pool{ - config: &Config{ - OrchestratorEndpoint: endpoint, - OrchestratorClient: http.DefaultClient, - OrchestratorJwtSecret: "", // Empty secret will cause JWT generation to fail - }, - } - - _, err := p.loadPool() - - assert.Error(t, err) - }) - - t.Run("adds JWT to request if secret is provided", func(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - authHeader := r.Header.Get("Authorization") - assert.NotEmpty(t, authHeader) - - parts := strings.Split(authHeader, " ") - assert.Equal(t, 2, len(parts)) - assert.Equal(t, "Bearer", parts[0]) - - tokenString := parts[1] - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte("secret"), nil - }) - - assert.NoError(t, err) - assert.True(t, token.Valid) - json.NewEncoder(w).Encode([]tieredhashing.NodeInfo{}) - })) - defer server.Close() - - endpoint, _ := url.Parse(server.URL) - p := &pool{ - config: &Config{ - OrchestratorEndpoint: endpoint, - OrchestratorClient: server.Client(), - OrchestratorJwtSecret: "secret", - }, - } - _, err := p.loadPool() - assert.NoError(t, err) - }) - -} - -func TestAuthenticateReq(t *testing.T) { - - req, _ := http.NewRequest("GET", "http://example.com", nil) - testKey := "testKey" - - newReq, err := authenticateReq(req, testKey) - - assert.NoError(t, err, "Error should not occur during authentication") - - assert.NotNil(t, newReq, "Request should be defined") + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + cid, _ := cid.V1Builder{Codec: uint64(multicodec.Raw), MhType: uint64(multicodec.Sha2_256)}.Sum([]byte("node")) + response := [1]tieredhashing.NodeInfo{{ + IP: "node", + ID: "node", + Weight: rand.Intn(100), + Distance: rand.Float32(), + SentinelCid: cid.String(), + }} - authHeader := newReq.Header.Get("Authorization") - assert.NotEmpty(t, authHeader, "Authorization header should not be empty") + w.Header().Set("Content-Type", "application/json") - parts := strings.Split(authHeader, " ") - assert.Equal(t, 2, len(parts), "Authorization header should have 2 parts") + // Encoding the response to JSON + json.NewEncoder(w).Encode(response) + })) - tokenPart := parts[1] - token, err := jwt.Parse(tokenPart, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(testKey), nil - }) - assert.NoError(t, err, "Error should not occur during parsing JWT") + endpoint, _ := url.Parse(server.URL) + p := &pool{ + config: &Config{ + OrchestratorEndpoint: endpoint, + OrchestratorClient: http.DefaultClient, + }, + } - claims, _ := token.Claims.(jwt.MapClaims) + _, err := p.loadPool() - expiresAt, ok := claims["ExpiresAt"].(float64) - assert.True(t, ok, "ExpiresAt should be a float64") - assert.True(t, time.Now().Unix() < int64(expiresAt), "Token should not have expired") + assert.NoError(t, err) } func TestFetchSentinelCid(t *testing.T) {