mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-09-16 15:52:05 -04:00
153 lines
4.7 KiB
Go
153 lines
4.7 KiB
Go
|
|
package handler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"log/slog"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/git-pkgs/proxy/internal/config"
|
||
|
|
"github.com/git-pkgs/proxy/internal/scanner"
|
||
|
|
)
|
||
|
|
|
||
|
|
// newEnabledScanGroup returns a scanner.Group that reports Enabled() true,
|
||
|
|
// so tests can exercise ServeScanFetch's normal signature-checking path
|
||
|
|
// rather than tripping its "scanning not configured" guard.
|
||
|
|
func newEnabledScanGroup(t testing.TB) *scanner.Group {
|
||
|
|
t.Helper()
|
||
|
|
g, err := scanner.NewGroup(config.ScanningConfig{
|
||
|
|
Enabled: true,
|
||
|
|
Timeout: "15s",
|
||
|
|
SigningKey: "test-signing-key",
|
||
|
|
Scanners: []config.ScannerConfig{
|
||
|
|
{Name: "test-scanner", URL: "http://localhost/scan", Mode: "block"},
|
||
|
|
},
|
||
|
|
}, slog.Default())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("scanner.NewGroup() error: %v", err)
|
||
|
|
}
|
||
|
|
return g
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_ValidToken(t *testing.T) {
|
||
|
|
proxy, _, store, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
store.files["npm/lodash/4.17.21/lodash-4.17.21.tgz"] = []byte("artifact bytes")
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/lodash/4.17.21/lodash-4.17.21.tgz", time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusOK {
|
||
|
|
t.Fatalf("status = %d, want 200; body: %s", w.Code, w.Body.String())
|
||
|
|
}
|
||
|
|
if w.Body.String() != "artifact bytes" {
|
||
|
|
t.Errorf("body = %q, want %q", w.Body.String(), "artifact bytes")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_Expired(t *testing.T) {
|
||
|
|
proxy, _, store, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
store.files["npm/lodash/4.17.21/lodash-4.17.21.tgz"] = []byte("artifact bytes")
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/lodash/4.17.21/lodash-4.17.21.tgz", -time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusForbidden {
|
||
|
|
t.Errorf("status = %d, want 403", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_TamperedSignature(t *testing.T) {
|
||
|
|
proxy, _, store, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
store.files["npm/lodash/4.17.21/lodash-4.17.21.tgz"] = []byte("artifact bytes")
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/lodash/4.17.21/lodash-4.17.21.tgz", time.Minute)
|
||
|
|
tampered := strings.Replace(target, "sig=", "sig=deadbeef", 1)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, tampered, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusForbidden {
|
||
|
|
t.Errorf("status = %d, want 403", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_PathTraversal(t *testing.T) {
|
||
|
|
proxy, _, _, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("../../etc/passwd", time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusForbidden {
|
||
|
|
t.Errorf("status = %d, want 403", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_ScanningDisabled(t *testing.T) {
|
||
|
|
proxy, _, store, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
// proxy.Scanners left nil: scanning disabled.
|
||
|
|
store.files["npm/lodash/4.17.21/lodash-4.17.21.tgz"] = []byte("artifact bytes")
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/lodash/4.17.21/lodash-4.17.21.tgz", time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusNotFound {
|
||
|
|
t.Errorf("status = %d, want 404 when scanning is disabled", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_NoSigningKey(t *testing.T) {
|
||
|
|
proxy, _, store, _ := setupTestProxy(t)
|
||
|
|
// proxy.ScanSigningKey left empty.
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
store.files["npm/lodash/4.17.21/lodash-4.17.21.tgz"] = []byte("artifact bytes")
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/lodash/4.17.21/lodash-4.17.21.tgz", time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusNotFound {
|
||
|
|
t.Errorf("status = %d, want 404 when no signing key is configured", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServeScanFetch_MissingObject(t *testing.T) {
|
||
|
|
proxy, _, _, _ := setupTestProxy(t)
|
||
|
|
proxy.ScanSigningKey = []byte("test-signing-key")
|
||
|
|
proxy.Scanners = newEnabledScanGroup(t)
|
||
|
|
|
||
|
|
target := proxy.scanFetchURL("npm/missing/1.0.0/missing-1.0.0.tgz", time.Minute)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, target, nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
proxy.ServeScanFetch(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusNotFound {
|
||
|
|
t.Errorf("status = %d, want 404", w.Code)
|
||
|
|
}
|
||
|
|
}
|