// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
package libddwaf
import (
"errors"
"fmt"
)
// Diagnostics stores the information as provided by the WAF about WAF rules parsing and loading. It
// is returned by [Builder.AddOrUpdateConfig].
type Diagnostics struct {
// Rules contains information about the loaded rules.
Rules *Feature
// CustomRules contains information about the loaded custom rules.
CustomRules *Feature
// Actions contains information about the loaded actions.
Actions *Feature
// Exclusions contains information about the loaded exclusions.
Exclusions *Feature
// RulesOverrides contains information about the loaded rules overrides.
RulesOverrides *Feature
// RulesData contains information about the loaded rules data.
RulesData *Feature
// ExclusionData contains information about the loaded exclusion data.
ExclusionData *Feature
// Processors contains information about the loaded processors.
Processors *Feature
// ProcessorOverrides contains information about the loaded processor overrides.
ProcessorOverrides *Feature
// Scanners contains information about the loaded scanners.
Scanners *Feature
// Version is the version of the parsed ruleset if available.
Version string
}
// EachFeature calls the provided callback for each (non-nil) feature in this diagnostics object.
func (d *Diagnostics) EachFeature(cb func(string, *Feature)) {
byName := map[string]*Feature{
"rules": d.Rules,
"custom_rules": d.CustomRules,
"actions": d.Actions,
"exclusions": d.Exclusions,
"rules_overrides": d.RulesOverrides,
"rules_data": d.RulesData,
"exclusion_data": d.ExclusionData,
"processors": d.Processors,
"processor_overrides": d.ProcessorOverrides,
"scanners": d.Scanners,
}
for name, feat := range byName {
if feat != nil {
cb(name, feat)
}
}
}
// TopLevelError returns the list of top-level errors reported by the WAF on any of the Diagnostics
// entries, rolled up into a single error value. Returns nil if no top-level errors were reported.
// Individual, item-level errors might still exist.
func (d *Diagnostics) TopLevelError() error {
var err error
d.EachFeature(func(name string, feat *Feature) {
if feat.Error != "" {
err = errors.Join(err, fmt.Errorf("%q: %s", name, feat.Error))
}
})
return err
}
// Feature stores the information as provided by the WAF about loaded and failed
// rules for a specific feature of the WAF ruleset.
type Feature struct {
// Errors is a map of parsing errors to a list of unique identifiers from the elements which
// failed loading due to this specific error.
Errors map[string][]string
// Warnings is a map of parsing warnings to a list of unique identifiers from the elements which
// resulted in this specific warning.
Warnings map[string][]string
// Error is the single error which prevented parsing this feature.
Error string
// Loaded is a list of the unique identifiers from successfully loaded elements.
Loaded []string
// Failed is a list of the unique identifiers from the elements which couldn't be loaded.
Failed []string
// Skipped is a list of the unique identifiers from the elements which were skipped.
Skipped []string
}