84 lines
2.9 KiB
Go
84 lines
2.9 KiB
Go
package hammerhead
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func keyCall(t *testing.T, s *Server, key, method, path, body string) (int, map[string]any) {
|
|
t.Helper()
|
|
req := httptest.NewRequest(method, path, strings.NewReader(body))
|
|
if key != "" {
|
|
req.Header.Set("Authorization", "Bearer "+key)
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
s.Handler().ServeHTTP(rec, req)
|
|
var out map[string]any
|
|
json.Unmarshal(rec.Body.Bytes(), &out)
|
|
return rec.Code, out
|
|
}
|
|
|
|
func mintKey(t *testing.T, s *Server, org string) string {
|
|
t.Helper()
|
|
k := "hhk_" + randHex(4) + "_" + randHex(24)
|
|
parts := strings.SplitN(k, "_", 3)
|
|
s.mu.Lock()
|
|
s.st.APIKeys = append(s.st.APIKeys, &APIKey{ID: parts[1], OrgID: org, Name: "t", Hash: sha(parts[2])})
|
|
s.mu.Unlock()
|
|
return k
|
|
}
|
|
|
|
func TestServerKeysManageEdgesAndOrgs(t *testing.T) {
|
|
f := newFx(t)
|
|
server := mintKey(t, f.s, "")
|
|
orgKey := mintKey(t, f.s, f.org)
|
|
|
|
if c, _ := keyCall(t, f.s, server, "POST", "/api/edges", `{"name":"e2","tunnelAddr":"1.2.3.4:51820"}`); c != 200 {
|
|
t.Fatalf("server key should create an edge, got %d", c)
|
|
}
|
|
if c, _ := keyCall(t, f.s, orgKey, "POST", "/api/edges", `{"name":"e3","tunnelAddr":"1.2.3.4:51820"}`); c != 401 {
|
|
t.Fatalf("org key must not create edges, got %d", c)
|
|
}
|
|
if c, _ := keyCall(t, f.s, server, "POST", "/api/orgs", `{"name":"Second"}`); c != 200 {
|
|
t.Fatalf("server key should create an org, got %d", c)
|
|
}
|
|
// server key reaches any org's endpoints; an org key only its own
|
|
if c, _ := keyCall(t, f.s, server, "POST", "/api/orgs/"+f.org+"/sites", `{"name":"x"}`); c != 200 {
|
|
t.Fatalf("server key on org: %d", c)
|
|
}
|
|
if c, _ := keyCall(t, f.s, orgKey, "POST", "/api/orgs/nope/sites", `{"name":"x"}`); c != 404 {
|
|
t.Fatalf("org key on other org: %d", c)
|
|
}
|
|
// server alert channels
|
|
if c, _ := keyCall(t, f.s, server, "GET", "/api/admin/alerts", ""); c != 200 {
|
|
t.Fatalf("server key alerts: %d", c)
|
|
}
|
|
// keys can't mint keys at server level
|
|
if c, _ := keyCall(t, f.s, server, "POST", "/api/admin/apikeys", `{"name":"k"}`); c != 401 {
|
|
t.Fatalf("server key must not mint server keys, got %d", c)
|
|
}
|
|
if c, _ := keyCall(t, f.s, "", "GET", "/api/orgs", ""); c != 401 {
|
|
t.Fatalf("anonymous list orgs: %d", c)
|
|
}
|
|
req := httptest.NewRequest("GET", "/api/orgs", nil)
|
|
req.Header.Set("Authorization", "Bearer "+orgKey)
|
|
rec := httptest.NewRecorder()
|
|
f.s.Handler().ServeHTTP(rec, req)
|
|
var orgs []Org
|
|
json.Unmarshal(rec.Body.Bytes(), &orgs)
|
|
if rec.Code != http.StatusOK || len(orgs) != 1 || orgs[0].ID != f.org {
|
|
t.Fatalf("org key should list only its org: %d %s", rec.Code, rec.Body)
|
|
}
|
|
// org key lists edges its org may use
|
|
req = httptest.NewRequest("GET", "/api/edges", nil)
|
|
req.Header.Set("Authorization", "Bearer "+orgKey)
|
|
rec = httptest.NewRecorder()
|
|
f.s.Handler().ServeHTTP(rec, req)
|
|
if rec.Code != 200 || !strings.Contains(rec.Body.String(), "edge-1") {
|
|
t.Fatalf("org key edges: %d %s", rec.Code, rec.Body)
|
|
}
|
|
}
|