mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 05:13:01 +00:00
- integrate Zig-built vault-guardian into cross-compile process - add `orama sandbox` for ephemeral Hetzner Cloud clusters - update docs for `orama node` subcommands and new guides
133 lines
3.5 KiB
Go
133 lines
3.5 KiB
Go
// Package vault provides HTTP handlers for vault proxy operations.
|
|
//
|
|
// The gateway acts as a smart proxy between RootWallet clients and
|
|
// vault guardian nodes on the WireGuard overlay network. It handles
|
|
// Shamir split/combine so clients make a single HTTPS call.
|
|
package vault
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/DeBrosOfficial/network/pkg/client"
|
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
|
)
|
|
|
|
const (
|
|
// VaultGuardianPort is the port vault guardians listen on (client API).
|
|
VaultGuardianPort = 7500
|
|
|
|
// guardianTimeout is the per-guardian HTTP request timeout.
|
|
guardianTimeout = 5 * time.Second
|
|
|
|
// overallTimeout is the maximum time for the full fan-out operation.
|
|
overallTimeout = 15 * time.Second
|
|
|
|
// maxPushBodySize limits push request bodies (1 MiB).
|
|
maxPushBodySize = 1 << 20
|
|
|
|
// maxPullBodySize limits pull request bodies (4 KiB).
|
|
maxPullBodySize = 4 << 10
|
|
)
|
|
|
|
// Handlers provides HTTP handlers for vault proxy operations.
|
|
type Handlers struct {
|
|
logger *logging.ColoredLogger
|
|
dbClient client.NetworkClient
|
|
rateLimiter *IdentityRateLimiter
|
|
httpClient *http.Client
|
|
}
|
|
|
|
// NewHandlers creates vault proxy handlers.
|
|
func NewHandlers(logger *logging.ColoredLogger, dbClient client.NetworkClient) *Handlers {
|
|
h := &Handlers{
|
|
logger: logger,
|
|
dbClient: dbClient,
|
|
rateLimiter: NewIdentityRateLimiter(
|
|
30, // 30 pushes per hour per identity
|
|
120, // 120 pulls per hour per identity
|
|
),
|
|
httpClient: &http.Client{
|
|
Timeout: guardianTimeout,
|
|
Transport: &http.Transport{
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
},
|
|
},
|
|
}
|
|
h.rateLimiter.StartCleanup(10*time.Minute, 1*time.Hour)
|
|
return h
|
|
}
|
|
|
|
// guardian represents a reachable vault guardian node.
|
|
type guardian struct {
|
|
IP string
|
|
Port int
|
|
}
|
|
|
|
// discoverGuardians queries dns_nodes for all active nodes.
|
|
// Every Orama node runs a vault guardian, so every active node is a guardian.
|
|
func (h *Handlers) discoverGuardians(ctx context.Context) ([]guardian, error) {
|
|
db := h.dbClient.Database()
|
|
internalCtx := client.WithInternalAuth(ctx)
|
|
|
|
query := "SELECT COALESCE(internal_ip, ip_address) FROM dns_nodes WHERE status = 'active'"
|
|
result, err := db.Query(internalCtx, query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("vault: failed to query guardian nodes: %w", err)
|
|
}
|
|
if result == nil || len(result.Rows) == 0 {
|
|
return nil, fmt.Errorf("vault: no active guardian nodes found")
|
|
}
|
|
|
|
guardians := make([]guardian, 0, len(result.Rows))
|
|
for _, row := range result.Rows {
|
|
if len(row) == 0 {
|
|
continue
|
|
}
|
|
ip := getString(row[0])
|
|
if ip == "" {
|
|
continue
|
|
}
|
|
guardians = append(guardians, guardian{IP: ip, Port: VaultGuardianPort})
|
|
}
|
|
if len(guardians) == 0 {
|
|
return nil, fmt.Errorf("vault: no guardian nodes with valid IPs found")
|
|
}
|
|
return guardians, nil
|
|
}
|
|
|
|
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
json.NewEncoder(w).Encode(v)
|
|
}
|
|
|
|
func writeError(w http.ResponseWriter, status int, msg string) {
|
|
writeJSON(w, status, map[string]string{"error": msg})
|
|
}
|
|
|
|
func getString(v interface{}) string {
|
|
if s, ok := v.(string); ok {
|
|
return s
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// isValidIdentity checks that identity is exactly 64 hex characters.
|
|
func isValidIdentity(identity string) bool {
|
|
if len(identity) != 64 {
|
|
return false
|
|
}
|
|
for _, c := range identity {
|
|
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|