Files
onix/pkg/plugin/implementation/policyenforcer/config.go
Ayush Rawat a806af3228 Update Policy Enforcer Configuration Keys
- Changed configuration key from `policyDir` to `policyPaths` across multiple YAML files and related code to standardize the naming convention.
- Updated documentation to reflect the new key name and its usage for specifying local directories containing `.rego` policy files.
- Adjusted tests to ensure compatibility with the updated configuration structure.
2026-03-03 15:02:04 +05:30

141 lines
3.9 KiB
Go

package policyenforcer
import (
"fmt"
"os"
"strings"
)
// Config holds the configuration for the Policy Enforcer plugin.
type Config struct {
// PolicyPaths is a local directory containing .rego policy files (all loaded).
// At least one policy source (PolicyPaths, PolicyFile, or PolicyUrls) is required.
PolicyPaths string
// PolicyFile is a single local .rego file path.
PolicyFile string
// PolicyUrls is a list of URLs (or local file paths) pointing to .rego files,
// fetched at startup or read from disk.
// Parsed from the comma-separated "policyUrls" config key.
PolicyUrls []string
// Query is the Rego query that returns a set of violation strings.
// Default: "data.policy.violations".
Query string
// Actions is the list of beckn actions to enforce policies on.
// When empty or nil, all actions are considered and the Rego policy
// is responsible for deciding which actions to gate.
Actions []string
// Enabled controls whether the plugin is active.
Enabled bool
// DebugLogging enables verbose logging.
DebugLogging bool
// RuntimeConfig holds arbitrary key-value pairs passed to Rego as data.config.
// Keys like minDeliveryLeadHours are forwarded here.
RuntimeConfig map[string]string
}
// Known config keys that are handled directly (not forwarded to RuntimeConfig).
var knownKeys = map[string]bool{
"policyPaths": true,
"policyFile": true,
"policyUrls": true,
"query": true,
"actions": true,
"enabled": true,
"debugLogging": true,
}
// DefaultConfig returns a Config with sensible defaults.
func DefaultConfig() *Config {
return &Config{
Query: "data.policy.violations",
Enabled: true,
DebugLogging: false,
RuntimeConfig: make(map[string]string),
}
}
// ParseConfig parses the plugin configuration map into a Config struct.
func ParseConfig(cfg map[string]string) (*Config, error) {
config := DefaultConfig()
if dir, ok := cfg["policyPaths"]; ok && dir != "" {
config.PolicyPaths = dir
}
if file, ok := cfg["policyFile"]; ok && file != "" {
config.PolicyFile = file
}
// Comma-separated policyUrls (supports URLs, local files, and directory paths)
if urls, ok := cfg["policyUrls"]; ok && urls != "" {
for _, u := range strings.Split(urls, ",") {
u = strings.TrimSpace(u)
if u != "" {
config.PolicyUrls = append(config.PolicyUrls, u)
}
}
}
if config.PolicyPaths == "" && config.PolicyFile == "" && len(config.PolicyUrls) == 0 {
// Fall back to the default ./policies directory if it exists on disk.
if info, err := os.Stat("./policies"); err == nil && info.IsDir() {
config.PolicyPaths = "./policies"
} else {
return nil, fmt.Errorf("at least one policy source is required (policyPaths, policyFile, or policyUrls)")
}
}
if query, ok := cfg["query"]; ok && query != "" {
config.Query = query
}
if actions, ok := cfg["actions"]; ok && actions != "" {
actionList := strings.Split(actions, ",")
config.Actions = make([]string, 0, len(actionList))
for _, action := range actionList {
action = strings.TrimSpace(action)
if action != "" {
config.Actions = append(config.Actions, action)
}
}
}
if enabled, ok := cfg["enabled"]; ok {
config.Enabled = enabled == "true" || enabled == "1"
}
if debug, ok := cfg["debugLogging"]; ok {
config.DebugLogging = debug == "true" || debug == "1"
}
// Forward unknown keys to RuntimeConfig (e.g., minDeliveryLeadHours)
for k, v := range cfg {
if !knownKeys[k] {
config.RuntimeConfig[k] = v
}
}
return config, nil
}
// IsActionEnabled checks if the given action is in the configured actions list.
// When the actions list is empty/nil, all actions are enabled and action-gating
// is delegated entirely to the Rego policy.
func (c *Config) IsActionEnabled(action string) bool {
if len(c.Actions) == 0 {
return true
}
for _, a := range c.Actions {
if a == action {
return true
}
}
return false
}