Implement policy system with comprehensive testing and configuration
Some checks failed
Go / build (push) Has been cancelled

- Introduced a new policy system for event processing, allowing fine-grained control over event storage and retrieval based on various criteria.
- Added support for policy configuration via JSON files, including whitelists, blacklists, and custom scripts.
- Implemented a test suite for the policy system, ensuring 100% test coverage of core functionality and edge cases.
- Created benchmark tests to evaluate policy performance under various conditions.
- Updated event handling to integrate policy checks for both read and write access.
- Enhanced documentation with examples and usage instructions for the policy system.
- Bumped version to v0.16.0.
This commit is contained in:
2025-10-16 11:37:30 +01:00
parent f19dc4e5c8
commit a84782bd52
17 changed files with 2643 additions and 1 deletions

View File

@@ -54,6 +54,8 @@ type C struct {
// Sprocket settings
SprocketEnabled bool `env:"ORLY_SPROCKET_ENABLED" default:"false" usage:"enable sprocket event processing plugin system"`
PolicyEnabled bool `env:"ORLY_POLICY_ENABLED" default:"false" usage:"enable policy-based event processing (configuration found in $HOME/.config/ORLY/policy.json)"`
}
// New creates and initializes a new configuration object for the relay

View File

@@ -109,6 +109,46 @@ func (l *Listener) HandleEvent(msg []byte) (err error) {
// Default to accept for unknown actions
}
}
// Check if policy is enabled and process event through it
if l.policyManager != nil && l.policyManager.Manager != nil && l.policyManager.Manager.IsEnabled() {
if l.policyManager.Manager.IsDisabled() {
// Policy is disabled due to failure - reject all events
log.W.F("policy is disabled, rejecting event %0x", env.E.ID)
if err = Ok.Error(
l, env,
"policy disabled - events rejected until policy is restored",
); chk.E(err) {
return
}
return
}
// Check policy for write access
allowed, policyErr := l.policyManager.CheckPolicy("write", env.E, l.authedPubkey.Load(), l.remote)
if chk.E(policyErr) {
log.E.F("policy check failed: %v", policyErr)
if err = Ok.Error(
l, env, "policy check failed",
); chk.E(err) {
return
}
return
}
if !allowed {
log.D.F("policy rejected event %0x", env.E.ID)
if err = Ok.Blocked(
l, env, "event blocked by policy",
); chk.E(err) {
return
}
return
}
log.D.F("policy allowed event %0x", env.E.ID)
}
// check the event ID is correct
calculatedId := env.E.GetIDBytes()
if !utils.FastEqual(calculatedId, env.E.ID) {

View File

@@ -240,6 +240,27 @@ privCheck:
}
}
events = tmp
// Apply policy filtering for read access if policy is enabled
if l.policyManager != nil && l.policyManager.Manager != nil && l.policyManager.Manager.IsEnabled() {
var policyFilteredEvents event.S
for _, ev := range events {
allowed, policyErr := l.policyManager.CheckPolicy("read", ev, l.authedPubkey.Load(), l.remote)
if chk.E(policyErr) {
log.E.F("policy check failed for read: %v", policyErr)
// Default to allow on policy error
policyFilteredEvents = append(policyFilteredEvents, ev)
continue
}
if allowed {
policyFilteredEvents = append(policyFilteredEvents, ev)
} else {
log.D.F("policy filtered out event %0x for read access", ev.ID)
}
}
events = policyFilteredEvents
}
seen := make(map[string]struct{})
for _, ev := range events {
log.T.C(

View File

@@ -11,6 +11,7 @@ import (
"next.orly.dev/pkg/crypto/keys"
"next.orly.dev/pkg/database"
"next.orly.dev/pkg/encoders/bech32encoding"
"next.orly.dev/pkg/policy"
"next.orly.dev/pkg/protocol/publish"
)
@@ -60,6 +61,9 @@ func Run(
// Initialize sprocket manager
l.sprocketManager = NewSprocketManager(ctx, cfg.AppName, cfg.SprocketEnabled)
// Initialize policy manager
l.policyManager = policy.NewWithManager(ctx, cfg.AppName, cfg.PolicyEnabled)
// Initialize the user interface
l.UserInterface()

View File

@@ -22,6 +22,7 @@ import (
"next.orly.dev/pkg/encoders/filter"
"next.orly.dev/pkg/encoders/hex"
"next.orly.dev/pkg/encoders/tag"
"next.orly.dev/pkg/policy"
"next.orly.dev/pkg/protocol/auth"
"next.orly.dev/pkg/protocol/httpauth"
"next.orly.dev/pkg/protocol/publish"
@@ -46,6 +47,7 @@ type Server struct {
paymentProcessor *PaymentProcessor
sprocketManager *SprocketManager
policyManager *policy.P
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {