You've already forked caddy-opnsense-blocker
135 lines
4.8 KiB
Go
135 lines
4.8 KiB
Go
package opnsense
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.dern.ovh/infrastructure/caddy-opnsense-blocker/internal/config"
|
|
)
|
|
|
|
func TestClientCreatesAliasAndBlocksAndUnblocksIPs(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type state struct {
|
|
mu sync.Mutex
|
|
aliasUUID string
|
|
aliasExists bool
|
|
ips map[string]struct{}
|
|
}
|
|
|
|
backendState := &state{ips: map[string]struct{}{}}
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
username, password, ok := r.BasicAuth()
|
|
if !ok || username != "key" || password != "secret" {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
backendState.mu.Lock()
|
|
defer backendState.mu.Unlock()
|
|
|
|
switch {
|
|
case r.Method == http.MethodGet && r.URL.Path == "/api/firewall/alias/get_alias_u_u_i_d/blocked-ips":
|
|
if backendState.aliasExists {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"uuid": backendState.aliasUUID})
|
|
} else {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"uuid": ""})
|
|
}
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/firewall/alias/add_item":
|
|
backendState.aliasExists = true
|
|
backendState.aliasUUID = "uuid-1"
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"status": "ok"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/firewall/alias/set_item/uuid-1":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"status": "ok"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/firewall/alias/reconfigure":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"status": "ok"})
|
|
case r.Method == http.MethodGet && r.URL.Path == "/api/firewall/alias_util/list/blocked-ips":
|
|
rows := make([]map[string]string, 0, len(backendState.ips))
|
|
for ip := range backendState.ips {
|
|
rows = append(rows, map[string]string{"ip": ip})
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"rows": rows})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/firewall/alias_util/add/blocked-ips":
|
|
var payload map[string]string
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
backendState.ips[payload["address"]] = struct{}{}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"status": "done"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/firewall/alias_util/delete/blocked-ips":
|
|
var payload map[string]string
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
delete(backendState.ips, payload["address"])
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"status": "done"})
|
|
default:
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(config.OPNsenseConfig{
|
|
Enabled: true,
|
|
BaseURL: server.URL,
|
|
APIKey: "key",
|
|
APISecret: "secret",
|
|
EnsureAlias: true,
|
|
Timeout: config.Duration{Duration: time.Second},
|
|
Alias: config.AliasConfig{
|
|
Name: "blocked-ips",
|
|
Type: "host",
|
|
},
|
|
APIPaths: config.APIPathsConfig{
|
|
AliasGetUUID: "/api/firewall/alias/get_alias_u_u_i_d/{alias}",
|
|
AliasAddItem: "/api/firewall/alias/add_item",
|
|
AliasSetItem: "/api/firewall/alias/set_item/{uuid}",
|
|
AliasReconfig: "/api/firewall/alias/reconfigure",
|
|
AliasUtilList: "/api/firewall/alias_util/list/{alias}",
|
|
AliasUtilAdd: "/api/firewall/alias_util/add/{alias}",
|
|
AliasUtilDelete: "/api/firewall/alias_util/delete/{alias}",
|
|
},
|
|
})
|
|
|
|
ctx := context.Background()
|
|
if result, err := client.AddIPIfMissing(ctx, "203.0.113.10"); err != nil || result != "added" {
|
|
t.Fatalf("unexpected add result: result=%q err=%v", result, err)
|
|
}
|
|
if result, err := client.AddIPIfMissing(ctx, "203.0.113.10"); err != nil || result != "already_present" {
|
|
t.Fatalf("unexpected add replay result: result=%q err=%v", result, err)
|
|
}
|
|
present, err := client.IsIPPresent(ctx, "203.0.113.10")
|
|
if err != nil {
|
|
t.Fatalf("is ip present: %v", err)
|
|
}
|
|
if !present {
|
|
t.Fatalf("expected IP to be present in alias")
|
|
}
|
|
if result, err := client.RemoveIPIfPresent(ctx, "203.0.113.10"); err != nil || result != "removed" {
|
|
t.Fatalf("unexpected remove result: result=%q err=%v", result, err)
|
|
}
|
|
if result, err := client.RemoveIPIfPresent(ctx, "203.0.113.10"); err != nil || result != "already_absent" {
|
|
t.Fatalf("unexpected remove replay result: result=%q err=%v", result, err)
|
|
}
|
|
|
|
backendState.mu.Lock()
|
|
defer backendState.mu.Unlock()
|
|
if !backendState.aliasExists || backendState.aliasUUID == "" {
|
|
t.Fatalf("expected alias to exist after first add")
|
|
}
|
|
if len(backendState.ips) != 0 {
|
|
t.Fatalf("expected alias to be empty after remove, got %v", backendState.ips)
|
|
}
|
|
if strings.TrimSpace(backendState.aliasUUID) == "" {
|
|
t.Fatalf("expected alias uuid to be populated")
|
|
}
|
|
}
|