Fix evaluate response-match validation
This commit is contained in:
@@ -1062,14 +1062,17 @@ func referencedDNSRuleSetTags(rules []option.DNSRule) []string {
|
||||
}
|
||||
|
||||
func validateLegacyDNSModeDisabledRules(rules []option.DNSRule) error {
|
||||
var seenEvaluate bool
|
||||
for i, rule := range rules {
|
||||
consumesResponse, err := validateLegacyDNSModeDisabledRuleTree(rule)
|
||||
requiresPriorEvaluate, err := validateLegacyDNSModeDisabledRuleTree(rule)
|
||||
if err != nil {
|
||||
return E.Cause(err, "validate dns rule[", i, "]")
|
||||
}
|
||||
action := dnsRuleActionType(rule)
|
||||
if action == C.RuleActionTypeEvaluate && consumesResponse {
|
||||
return E.New("dns rule[", i, "]: evaluate action cannot be used with match_response in the same rule")
|
||||
if requiresPriorEvaluate && !seenEvaluate {
|
||||
return E.New("dns rule[", i, "]: response-based matching requires a preceding evaluate action")
|
||||
}
|
||||
if dnsRuleActionType(rule) == C.RuleActionTypeEvaluate {
|
||||
seenEvaluate = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -1080,15 +1083,15 @@ func validateLegacyDNSModeDisabledRuleTree(rule option.DNSRule) (bool, error) {
|
||||
case "", C.RuleTypeDefault:
|
||||
return validateLegacyDNSModeDisabledDefaultRule(rule.DefaultOptions)
|
||||
case C.RuleTypeLogical:
|
||||
var consumesResponse bool
|
||||
var requiresPriorEvaluate bool
|
||||
for i, subRule := range rule.LogicalOptions.Rules {
|
||||
subConsumesResponse, err := validateLegacyDNSModeDisabledRuleTree(subRule)
|
||||
subRequiresPriorEvaluate, err := validateLegacyDNSModeDisabledRuleTree(subRule)
|
||||
if err != nil {
|
||||
return false, E.Cause(err, "sub rule[", i, "]")
|
||||
}
|
||||
consumesResponse = consumesResponse || subConsumesResponse
|
||||
requiresPriorEvaluate = requiresPriorEvaluate || subRequiresPriorEvaluate
|
||||
}
|
||||
return consumesResponse, nil
|
||||
return requiresPriorEvaluate, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -2163,6 +2163,140 @@ func TestInitializeRejectsDNSRuleStrategyWhenLegacyDNSModeIsDisabledByMatchRespo
|
||||
require.ErrorContains(t, err, "deprecated")
|
||||
}
|
||||
|
||||
func TestInitializeRejectsDNSMatchResponseWithoutPrecedingEvaluate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
router := &Router{
|
||||
ctx: context.Background(),
|
||||
logger: log.NewNOPFactory().NewLogger("dns"),
|
||||
transport: &fakeDNSTransportManager{},
|
||||
client: &fakeDNSClient{},
|
||||
rawRules: make([]option.DNSRule, 0, 1),
|
||||
defaultDomainStrategy: C.DomainStrategyAsIS,
|
||||
}
|
||||
router.currentRules.Store(newRulesSnapshot(make([]adapter.DNSRule, 0, 1), false))
|
||||
err := router.Initialize([]option.DNSRule{{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
MatchResponse: true,
|
||||
ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{Server: "default"},
|
||||
},
|
||||
},
|
||||
}})
|
||||
require.ErrorContains(t, err, "preceding evaluate action")
|
||||
}
|
||||
|
||||
func TestInitializeRejectsEvaluateRuleWithResponseMatchWithoutPrecedingEvaluate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
router := &Router{
|
||||
ctx: context.Background(),
|
||||
logger: log.NewNOPFactory().NewLogger("dns"),
|
||||
transport: &fakeDNSTransportManager{},
|
||||
client: &fakeDNSClient{},
|
||||
rawRules: make([]option.DNSRule, 0, 1),
|
||||
defaultDomainStrategy: C.DomainStrategyAsIS,
|
||||
}
|
||||
router.currentRules.Store(newRulesSnapshot(make([]adapter.DNSRule, 0, 1), false))
|
||||
err := router.Initialize([]option.DNSRule{{
|
||||
Type: C.RuleTypeLogical,
|
||||
LogicalOptions: option.LogicalDNSRule{
|
||||
RawLogicalDNSRule: option.RawLogicalDNSRule{
|
||||
Mode: C.LogicalTypeOr,
|
||||
Rules: []option.DNSRule{
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
Domain: badoption.Listable[string]{"example.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
MatchResponse: true,
|
||||
ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeEvaluate,
|
||||
RouteOptions: option.DNSRouteActionOptions{Server: "default"},
|
||||
},
|
||||
},
|
||||
}})
|
||||
require.ErrorContains(t, err, "preceding evaluate action")
|
||||
}
|
||||
|
||||
func TestInitializeAllowsEvaluateRuleWithResponseMatchAfterPrecedingEvaluate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
router := &Router{
|
||||
ctx: context.Background(),
|
||||
logger: log.NewNOPFactory().NewLogger("dns"),
|
||||
transport: &fakeDNSTransportManager{},
|
||||
client: &fakeDNSClient{},
|
||||
rawRules: make([]option.DNSRule, 0, 2),
|
||||
defaultDomainStrategy: C.DomainStrategyAsIS,
|
||||
}
|
||||
router.currentRules.Store(newRulesSnapshot(make([]adapter.DNSRule, 0, 2), false))
|
||||
err := router.Initialize([]option.DNSRule{
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
Domain: badoption.Listable[string]{"bootstrap.example"},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeEvaluate,
|
||||
RouteOptions: option.DNSRouteActionOptions{Server: "bootstrap"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: C.RuleTypeLogical,
|
||||
LogicalOptions: option.LogicalDNSRule{
|
||||
RawLogicalDNSRule: option.RawLogicalDNSRule{
|
||||
Mode: C.LogicalTypeOr,
|
||||
Rules: []option.DNSRule{
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
Domain: badoption.Listable[string]{"example.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
MatchResponse: true,
|
||||
ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeEvaluate,
|
||||
RouteOptions: option.DNSRouteActionOptions{Server: "default"},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLookupLegacyDNSModeDisabledReturnsRejectedErrorForRejectAction(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user