1package app
2
3import (
4 "context"
5 "net/http"
6 "net/http/httptest"
7 "testing"
8
9 adminhttp "github.com/bnema/gordon/internal/adapters/in/http/admin"
10 "github.com/bnema/zerowrap"
11)
12
13func TestCreateAuthService_Disabled_ReturnsNilServices(t *testing.T) {
14 t.Parallel()
15
16 cfg := Config{}
17 cfg.Auth.Enabled = false
18
19 store, authSvc, err := createAuthService(context.Background(), cfg, zerowrap.Default())
20 if err != nil {
21 t.Fatalf("expected no error when auth is disabled, got %v", err)
22 }
23 if store != nil {
24 t.Fatalf("expected nil token store when auth is disabled")
25 }
26 if authSvc != nil {
27 t.Fatalf("expected nil auth service when auth is disabled")
28 }
29}
30
31func TestCreateHTTPHandlers_LocalMode_DisablesAdminRoutes(t *testing.T) {
32 t.Parallel()
33
34 cfg := Config{}
35 cfg.Auth.Enabled = false
36
37 svc := &services{adminHandler: &adminhttp.Handler{}}
38 registryHandler, _ := createHTTPHandlers(svc, cfg, zerowrap.Default())
39
40 req := httptest.NewRequest(http.MethodGet, "/admin/status", nil)
41 req.RemoteAddr = "192.0.2.10:12345"
42
43 rec := httptest.NewRecorder()
44 registryHandler.ServeHTTP(rec, req)
45
46 if rec.Code != http.StatusNotFound {
47 t.Fatalf("expected status %d, got %d", http.StatusNotFound, rec.Code)
48 }
49}
50
51func TestCreateHTTPHandlers_LocalMode_RestrictsRegistryToLoopback(t *testing.T) {
52 t.Parallel()
53
54 cfg := Config{}
55 cfg.Auth.Enabled = false
56
57 registryHandler, _ := createHTTPHandlers(&services{}, cfg, zerowrap.Default())
58
59 req := httptest.NewRequest(http.MethodGet, "/v2/test/manifests/latest", nil)
60 req.RemoteAddr = "192.0.2.20:12345"
61
62 rec := httptest.NewRecorder()
63 registryHandler.ServeHTTP(rec, req)
64
65 if rec.Code != http.StatusForbidden {
66 t.Fatalf("expected status %d, got %d", http.StatusForbidden, rec.Code)
67 }
68}
69
70func TestCreateHTTPHandlers_AuthEnabled_ExposesAdminOnProxyForRegistryHost(t *testing.T) {
71 t.Parallel()
72
73 cfg := Config{}
74 cfg.Auth.Enabled = true
75 cfg.Server.RegistryDomain = "gordon.local"
76
77 svc := &services{adminHandler: &adminhttp.Handler{}}
78 _, proxyHandler := createHTTPHandlers(svc, cfg, zerowrap.Default())
79 // services uses an adminHandler stub with authSvc left nil. In createHTTPHandlers,
80 // registerAdminRoutes installs fail-closed middleware for that case, so admin
81 // requests on the allowed host return 503 ServiceUnavailable.
82
83 req := httptest.NewRequest(http.MethodGet, "/admin/status", nil)
84 req.Host = "gordon.local"
85 req.RemoteAddr = "192.0.2.30:12345"
86
87 rec := httptest.NewRecorder()
88 proxyHandler.ServeHTTP(rec, req)
89
90 if rec.Code != http.StatusServiceUnavailable {
91 t.Fatalf("expected status %d, got %d", http.StatusServiceUnavailable, rec.Code)
92 }
93}
94
95func TestCreateHTTPHandlers_AuthEnabled_BlocksAdminOnNonRegistryHost(t *testing.T) {
96 t.Parallel()
97
98 cfg := Config{}
99 cfg.Auth.Enabled = true
100 cfg.Server.RegistryDomain = "gordon.local"
101
102 svc := &services{adminHandler: &adminhttp.Handler{}}
103 _, proxyHandler := createHTTPHandlers(svc, cfg, zerowrap.Default())
104
105 req := httptest.NewRequest(http.MethodGet, "/admin/status", nil)
106 req.Host = "app.example.com"
107 req.RemoteAddr = "192.0.2.30:12345"
108
109 rec := httptest.NewRecorder()
110 proxyHandler.ServeHTTP(rec, req)
111
112 if rec.Code != http.StatusNotFound {
113 t.Fatalf("expected status %d, got %d", http.StatusNotFound, rec.Code)
114 }
115}
116
117func TestBuildRegistryCIDRAllowlistMiddleware_InvalidEntries_DenyAll(t *testing.T) {
118 t.Parallel()
119
120 cfg := Config{}
121 cfg.Server.RegistryAllowedIPs = []string{"not-a-cidr"}
122
123 mw := buildRegistryCIDRAllowlistMiddleware(cfg, nil, zerowrap.Default())
124 if mw == nil {
125 t.Fatal("expected non-nil allowlist middleware")
126 }
127
128 handler := mw(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
129 w.WriteHeader(http.StatusOK)
130 }))
131
132 req := httptest.NewRequest(http.MethodGet, "/v2/test/manifests/latest", nil)
133 req.RemoteAddr = "127.0.0.1:12345"
134
135 rec := httptest.NewRecorder()
136 handler.ServeHTTP(rec, req)
137
138 if rec.Code != http.StatusForbidden {
139 t.Fatalf("expected status %d, got %d", http.StatusForbidden, rec.Code)
140 }
141}