package libpolicy import ( "log" "net" "net/netip" "strings" ) func contains(slice []string, val string) bool { for _, v := range slice { if v == val { return true } } return false } type Effect uint8 const ( Allow Effect = iota Deny NoMatch ) func IsIPInCIDR(ipStr, cidrStr string) bool { // Parse the IP address cidrStr = normalizeCIDR(cidrStr) log.Println("Parsing IP:", ipStr, " against CIDR:", cidrStr) ip := net.ParseIP(ipStr) if ip == nil { return false // Invalid IP } // Parse the CIDR _, ipnet, err := net.ParseCIDR(cidrStr) if err != nil { return false // Invalid CIDR } // net.IPNet.Contains() handles IPv4/IPv6 correctly, including IPv4-mapped IPv6 return ipnet.Contains(ip) } func normalizeCIDR(cidrStr string) string { cidrStr = strings.TrimSpace(cidrStr) if cidrStr == "" { return "" } // Already has a mask suffix → use as-is if strings.Contains(cidrStr, "/") { return cidrStr } // Try to parse as IP address to determine version addr, err := netip.ParseAddr(cidrStr) if err != nil { return "" // Invalid } if addr.Is4() || addr.Is4In6() { return cidrStr + "/32" } return cidrStr + "/128" } func verifyRequest(request *Request, policy *Policy) (Effect, string) { //conditionReview = []Condition{} var effect Effect effect = NoMatch statementid := "NoMatch" for _, condition := range policy.Conditions { log.Println("Checking Statement: ", condition.StatementID) // Check the principal if !contains(condition.Principal, request.Principal) { log.Println("No match on principal") log.Println("Checked condition principal:", condition.Principal) log.Println("Against: request principal:", request.Principal) continue } if !contains(condition.Actions, request.Action) { log.Println("No match on actions") log.Println("Checked condition actions:", condition.Actions) log.Println("Against: request action:", request.Action) continue } // Source Check sourceMatch := false for _, source := range condition.Source { if IsIPInCIDR(request.SourceIPAddress, source) { sourceMatch = true } } if sourceMatch == false { log.Println("No match on source") log.Println("Checked condition source:", condition.Source) log.Println("Against: request source:", request.SourceIPAddress) continue } if condition.Effect == "allow" { effect = Allow log.Println("Allowed per ") log.Printf("Request is allowed by condition: %s\n", condition.StatementID) effect = Allow statementid = condition.StatementID } else if condition.Effect == "deny" { // Immediately deny upon explicit deny log.Printf("Request is denied by condition: %s\n", condition.StatementID) return Deny, condition.StatementID } } return effect, statementid } /* func loadRequestFile(filename string) (*Request, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("failed to open '%s' %w", filename, err) } defer file.Close() var request Request if err := json.NewDecoder(file).Decode(&request); err != nil { return nil, fmt.Errorf("failed to parse json from '%s': %w", filename, err) } fmt.Printf("Successfully loaded request from %s\n", filename) return &request, nil } func loadPolicyFile(filename string) (*Policy, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("failed to open file '%s': %w", filename, err) } defer file.Close() var policy Policy if err := json.NewDecoder(file).Decode(&policy); err != nil { return nil, fmt.Errorf("failed to parse JSON from '%s': %w", filename, err) } fmt.Printf("Successfully loaded policy from %s\n", filename) return &policy, nil } */ /* func main() { policy, err := loadPolicyFile("policy.json") if err != nil { fmt.Println("Error: %v", err) os.Exit(1) } fmt.Println("Policy structure loaded successfully:") pretty, _ := json.MarshalIndent(policy, "", "\t") fmt.Println(string(pretty)) request, err := loadRequestFile("request.json") if err != nil { fmt.Println("Error: %v\n", err) os.Exit(1) } fmt.Println("Loaded Request successfully\n") pretty, _ = json.MarshalIndent(request, "", "\t") fmt.Println(string(pretty)) effect, statementid := verifyRequest(request, policy) fmt.Println("") if effect == NoMatch { fmt.Println("No matching conditions found. Defaulting to Deny.") } else if effect == Allow { fmt.Println("Request is allowed based on matching conditions.") } else { fmt.Println("Request is denied based on matching conditions.") } println("statementid:", statementid) } */