Implement policy system with comprehensive testing and configuration
Some checks failed
Go / build (push) Has been cancelled
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:
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user