blocky/resolver/blocking_resolver_test.go

1209 lines
40 KiB
Go
Raw Normal View History

2020-01-12 18:23:35 +01:00
package resolver
import (
"context"
"time"
2021-08-25 22:06:34 +02:00
"github.com/0xERR0R/blocky/config"
. "github.com/0xERR0R/blocky/evt"
. "github.com/0xERR0R/blocky/helpertest"
"github.com/0xERR0R/blocky/lists"
refactor: configuration rework (usage and printing) (#920) * refactor: make `config.Duration` a struct with `time.Duration` embed Allows directly calling `time.Duration` methods. * refactor(HostsFileResolver): don't copy individual config items The idea is to make adding configuration options easier, and searching for references straight forward. * refactor: move config printing to struct and use a logger Using a logger allows using multiple levels so the whole configuration can be printed in trace/verbose mode, but only important parts are shown by default. * squash: rename `Cast` to `ToDuration` * squash: revert `Duration` to a simple wrapper ("new type" pattern) * squash: `Duration.IsZero` tests * squash: refactor resolvers to rely on their config directly if possible * squash: implement `IsEnabled` and `LogValues` for all resolvers * refactor: use go-enum `--values` to simplify getting all log fields * refactor: simplify `QType` unmarshaling * squash: rename `ValueLogger` to `Configurable` * squash: rename `UpstreamConfig` to `ParallelBestConfig` * squash: rename `RewriteConfig` to `RewriterConfig` * squash: config tests * squash: resolver tests * squash: add `ForEach` test and improve `Chain` ones * squash: simplify implementing `config.Configurable` * squash: minor changes for better coverage * squash: more `UnmarshalYAML` -> `UnmarshalText` * refactor: move `config.Upstream` into own file * refactor: add `Resolver.Type` method * squash: add `log` method to `typed` to use `Resolover.Type` as prefix * squash: tweak startup config logging * squash: add `LogResolverConfig` tests * squash: make sure all options of type `Duration` use `%s`
2023-03-12 22:14:10 +01:00
"github.com/0xERR0R/blocky/log"
. "github.com/0xERR0R/blocky/model"
"github.com/0xERR0R/blocky/redis"
2021-08-25 22:06:34 +02:00
"github.com/0xERR0R/blocky/util"
"github.com/alicebob/miniredis/v2"
"github.com/creasty/defaults"
2020-08-24 22:15:31 +02:00
2020-01-12 18:23:35 +01:00
"github.com/miekg/dns"
2022-03-03 11:27:27 +01:00
. "github.com/onsi/ginkgo/v2"
2020-05-04 22:20:13 +02:00
. "github.com/onsi/gomega"
2020-01-12 18:23:35 +01:00
"github.com/stretchr/testify/mock"
)
var (
group1File, group2File, defaultGroupFile *TmpFile
tmpDir *TmpFolder
)
2022-03-03 11:27:27 +01:00
var _ = BeforeSuite(func() {
tmpDir = NewTmpFolder("BlockingResolver")
group1File = tmpDir.CreateStringFile("group1File", "DOMAIN1.com")
group2File = tmpDir.CreateStringFile("group2File", "blocked2.com")
defaultGroupFile = tmpDir.CreateStringFile("defaultGroupFile",
"blocked3.com",
"123.145.123.145",
"2001:db8:85a3:08d3::370:7344",
"badcnamedomain.com")
2022-03-03 11:27:27 +01:00
})
var _ = Describe("BlockingResolver", Label("blockingResolver"), func() {
2020-05-04 22:20:13 +02:00
var (
sut *BlockingResolver
2023-11-21 22:27:51 +01:00
sutConfig config.Blocking
m *mockResolver
2020-05-04 22:20:13 +02:00
mockAnswer *dns.Msg
ctx context.Context
cancelFn context.CancelFunc
2020-05-04 22:20:13 +02:00
)
refactor: configuration rework (usage and printing) (#920) * refactor: make `config.Duration` a struct with `time.Duration` embed Allows directly calling `time.Duration` methods. * refactor(HostsFileResolver): don't copy individual config items The idea is to make adding configuration options easier, and searching for references straight forward. * refactor: move config printing to struct and use a logger Using a logger allows using multiple levels so the whole configuration can be printed in trace/verbose mode, but only important parts are shown by default. * squash: rename `Cast` to `ToDuration` * squash: revert `Duration` to a simple wrapper ("new type" pattern) * squash: `Duration.IsZero` tests * squash: refactor resolvers to rely on their config directly if possible * squash: implement `IsEnabled` and `LogValues` for all resolvers * refactor: use go-enum `--values` to simplify getting all log fields * refactor: simplify `QType` unmarshaling * squash: rename `ValueLogger` to `Configurable` * squash: rename `UpstreamConfig` to `ParallelBestConfig` * squash: rename `RewriteConfig` to `RewriterConfig` * squash: config tests * squash: resolver tests * squash: add `ForEach` test and improve `Chain` ones * squash: simplify implementing `config.Configurable` * squash: minor changes for better coverage * squash: more `UnmarshalYAML` -> `UnmarshalText` * refactor: move `config.Upstream` into own file * refactor: add `Resolver.Type` method * squash: add `log` method to `typed` to use `Resolover.Type` as prefix * squash: tweak startup config logging * squash: add `LogResolverConfig` tests * squash: make sure all options of type `Duration` use `%s`
2023-03-12 22:14:10 +01:00
Describe("Type", func() {
It("follows conventions", func() {
expectValidResolverType(sut)
})
})
2020-05-04 22:20:13 +02:00
BeforeEach(func() {
ctx, cancelFn = context.WithCancel(context.Background())
DeferCleanup(cancelFn)
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
}
2020-05-04 22:20:13 +02:00
mockAnswer = new(dns.Msg)
})
JustBeforeEach(func() {
var err error
m = &mockResolver{}
2020-05-04 22:20:13 +02:00
m.On("Resolve", mock.Anything).Return(&Response{Res: mockAnswer}, nil)
sut, err = NewBlockingResolver(ctx, sutConfig, nil, systemResolverBootstrap)
Expect(err).Should(Succeed())
2020-05-04 22:20:13 +02:00
sut.Next(m)
})
refactor: configuration rework (usage and printing) (#920) * refactor: make `config.Duration` a struct with `time.Duration` embed Allows directly calling `time.Duration` methods. * refactor(HostsFileResolver): don't copy individual config items The idea is to make adding configuration options easier, and searching for references straight forward. * refactor: move config printing to struct and use a logger Using a logger allows using multiple levels so the whole configuration can be printed in trace/verbose mode, but only important parts are shown by default. * squash: rename `Cast` to `ToDuration` * squash: revert `Duration` to a simple wrapper ("new type" pattern) * squash: `Duration.IsZero` tests * squash: refactor resolvers to rely on their config directly if possible * squash: implement `IsEnabled` and `LogValues` for all resolvers * refactor: use go-enum `--values` to simplify getting all log fields * refactor: simplify `QType` unmarshaling * squash: rename `ValueLogger` to `Configurable` * squash: rename `UpstreamConfig` to `ParallelBestConfig` * squash: rename `RewriteConfig` to `RewriterConfig` * squash: config tests * squash: resolver tests * squash: add `ForEach` test and improve `Chain` ones * squash: simplify implementing `config.Configurable` * squash: minor changes for better coverage * squash: more `UnmarshalYAML` -> `UnmarshalText` * refactor: move `config.Upstream` into own file * refactor: add `Resolver.Type` method * squash: add `log` method to `typed` to use `Resolover.Type` as prefix * squash: tweak startup config logging * squash: add `LogResolverConfig` tests * squash: make sure all options of type `Duration` use `%s`
2023-03-12 22:14:10 +01:00
Describe("IsEnabled", func() {
It("is false", func() {
Expect(sut.IsEnabled()).Should(BeFalse())
})
})
Describe("LogConfig", func() {
It("should log something", func() {
logger, hook := log.NewMockEntry()
sut.LogConfig(logger)
Expect(hook.Calls).ShouldNot(BeEmpty())
})
})
2021-01-19 21:52:24 +01:00
Describe("Events", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"gr1": config.NewBytesSources(group1File.Path),
"gr2": config.NewBytesSources(group2File.Path),
2021-01-19 21:52:24 +01:00
},
}
})
When("List is refreshed", func() {
It("event should be fired", func() {
groupCnt := make(map[string]int)
err := Bus().Subscribe(BlockingCacheGroupChanged, func(listType lists.ListCacheType, group string, cnt int) {
2021-01-19 21:52:24 +01:00
groupCnt[group] = cnt
})
Expect(err).Should(Succeed())
// recreate to trigger a reload
sut, err = NewBlockingResolver(ctx, sutConfig, nil, systemResolverBootstrap)
Expect(err).Should(Succeed())
2021-01-19 21:52:24 +01:00
Eventually(groupCnt, "1s").Should(HaveLen(2))
2021-01-19 21:52:24 +01:00
})
})
2020-05-04 22:20:13 +02:00
})
Describe("Blocking with full-qualified client name", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"gr1": config.NewBytesSources(group1File.Path),
"gr2": config.NewBytesSources(group2File.Path),
},
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
"full.qualified.com": {"gr2"},
},
}
})
When("Full-qualified group name is used", func() {
It("should block request", func() {
m.AnswerFn = func(t dns.Type, qName string) (*dns.Msg, error) {
if t == dns.Type(dns.TypeA) && qName == "full.qualified.com." {
return util.NewMsgWithAnswer(qName, 60*60, A, "192.168.178.39")
}
return nil, nil //nolint:nilnil
}
Bus().Publish(ApplicationStarted, "")
Eventually(func(g Gomega) {
g.Expect(sut.Resolve(ctx, newRequestWithClient("blocked2.com.", A, "192.168.178.39", "client1"))).
Should(And(
BeDNSRecord("blocked2.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 60)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
))
2022-09-23 23:42:18 +02:00
}, "10s", "1s").Should(Succeed())
})
})
})
Describe("Blocking with fast start strategy", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"gr1": {config.TextBytesSource("/regex/")},
},
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
},
2023-04-17 18:21:56 +02:00
Loading: config.SourceLoadingConfig{Strategy: config.StartStrategyTypeFast},
}
})
When("Domain is on the black list", func() {
It("should block request", func() {
Eventually(sut.Resolve).
WithContext(ctx).
WithArguments(newRequestWithClient("regex.com.", dns.Type(dns.TypeA), "1.2.1.2", "client1")).
Should(
SatisfyAll(
BeDNSRecord("regex.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 60)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
))
})
})
})
2020-05-04 22:20:13 +02:00
Describe("Blocking requests", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockTTL: config.Duration(6 * time.Hour),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"gr1": config.NewBytesSources(group1File.Path),
"gr2": config.NewBytesSources(group2File.Path),
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
2020-05-04 22:20:13 +02:00
},
ClientGroupsBlock: map[string][]string{
"Client1": {"gr1"},
"client2,client3": {"gr1"},
"client3": {"gr2"},
"192.168.178.55": {"gr1"},
"altName": {"gr2"},
"10.43.8.67/28": {"gr1"},
"wildcard[0-9]*": {"gr1"},
"default": {"defaultGroup"},
2020-05-04 22:20:13 +02:00
},
BlockType: "ZeroIP",
}
})
When("client name is defined in client groups block", func() {
It("should block the A query if domain is on the black list (single)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "client1"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
It("should block the A query if domain is on the black list (multipart 1)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "client2"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
It("should block the A query if domain is on the black list (multipart 2)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "client3"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
It("should block the A query if domain is on the black list (merged)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked2.com.", A, "1.2.1.2", "client3"))).
Should(
SatisfyAll(
BeDNSRecord("blocked2.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr2)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
2020-05-04 22:20:13 +02:00
It("should block the AAAA query if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", AAAA, "1.2.1.2", "client1"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", AAAA, "::"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
It("should block the HTTPS query if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", HTTPS, "1.2.1.2", "client1"))).
Should(HaveReturnCode(dns.RcodeNameError))
})
It("should block the MX query if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", MX, "1.2.1.2", "client1"))).
Should(HaveReturnCode(dns.RcodeNameError))
})
2020-05-04 22:20:13 +02:00
})
When("Client ip is defined in client groups block", func() {
It("should block the query if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "192.168.178.55", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
When("Client CIDR (10.43.8.64 - 10.43.8.79) is defined in client groups block", func() {
It("should not block the query for 10.43.8.63 if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "10.43.8.63", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
It("should not block the query for 10.43.8.80 if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "10.43.8.80", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
})
When("Client CIDR (10.43.8.64 - 10.43.8.79) is defined in client groups block", func() {
It("should block the query for 10.43.8.64 if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "10.43.8.64", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
It("should block the query for 10.43.8.79 if domain is on the black list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "10.43.8.79", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
})
2020-05-04 22:20:13 +02:00
When("Client has multiple names and for each name a client group block definition exists", func() {
It("should block query if domain is in one group", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "client1", "altname"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
It("should block query if domain is in another group too", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked2.com.", A, "1.2.1.2", "client1", "altName"))).
Should(
SatisfyAll(
BeDNSRecord("blocked2.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr2)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
2020-08-24 22:15:31 +02:00
When("Client name matches wildcard", func() {
It("should block query if domain is in one group", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "wildcard1name"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (gr1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-08-24 22:15:31 +02:00
})
})
2020-05-04 22:20:13 +02:00
When("Default group is defined", func() {
It("should block domains from default group for each client", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
When("BlockType is NxDomain", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
2020-05-04 22:20:13 +02:00
},
ClientGroupsBlock: map[string][]string{
"default": {"defaultGroup"},
},
BlockType: "NxDomain",
}
})
It("should return NXDOMAIN if query is blocked", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeNameError),
HaveReason("BLOCKED (defaultGroup)"),
))
2020-05-04 22:20:13 +02:00
})
})
When("BlockTTL is set", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
},
ClientGroupsBlock: map[string][]string{
"default": {"defaultGroup"},
},
BlockTTL: config.Duration(time.Second * 1234),
}
})
It("should return answer with specified TTL", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 1234)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (defaultGroup)"),
))
})
When("BlockType is custom IP", func() {
BeforeEach(func() {
sutConfig.BlockType = "12.12.12.12"
})
It("should return custom IP with specified TTL", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "12.12.12.12"),
HaveTTL(BeNumerically("==", 1234)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (defaultGroup)"),
))
})
})
})
When("BlockType is custom IP", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockTTL: config.Duration(6 * time.Hour),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
},
ClientGroupsBlock: map[string][]string{
"default": {"defaultGroup"},
},
BlockType: "12.12.12.12, 2001:0db8:85a3:0000:0000:8a2e:0370:7334",
}
})
It("should return ipv4 address for A query if query is blocked", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "12.12.12.12"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (defaultGroup)"),
))
})
It("should return ipv6 address for AAAA query if query is blocked", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", AAAA, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", AAAA, "2001:db8:85a3::8a2e:370:7334"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (defaultGroup)"),
))
})
})
When("BlockType is custom IP only for ipv4", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
},
ClientGroupsBlock: map[string][]string{
"default": {"defaultGroup"},
},
BlockType: "12.12.12.12",
BlockTTL: config.Duration(6 * time.Hour),
}
})
It("should use fallback for ipv6 and return zero ip", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", AAAA, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", AAAA, "::"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (defaultGroup)"),
))
})
})
2020-05-04 22:20:13 +02:00
When("Blacklist contains IP", func() {
When("IP4", func() {
BeforeEach(func() {
// return defined IP as response
mockAnswer, _ = util.NewMsgWithAnswer("example.com.", 300, A, "123.145.123.145")
2020-05-04 22:20:13 +02:00
})
It("should block query, if lookup result contains blacklisted IP", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("example.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED IP (defaultGroup)"),
))
2020-05-04 22:20:13 +02:00
})
})
When("IP6", func() {
BeforeEach(func() {
// return defined IP as response
mockAnswer, _ = util.NewMsgWithAnswer(
"example.com.", 300,
AAAA, "2001:0db8:85a3:08d3::0370:7344",
)
2020-05-04 22:20:13 +02:00
})
It("should block query, if lookup result contains blacklisted IP", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", AAAA, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("example.com.", AAAA, "::"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED IP (defaultGroup)"),
))
2020-05-04 22:20:13 +02:00
})
})
})
When("blacklist contains domain which is CNAME in response", func() {
BeforeEach(func() {
// reconfigure mock, to return CNAMEs
rr1, _ := dns.NewRR("example.com 300 IN CNAME domain.com")
rr2, _ := dns.NewRR("domain.com 300 IN CNAME badcnamedomain.com")
rr3, _ := dns.NewRR("badcnamedomain.com 300 IN A 125.125.125.125")
mockAnswer = new(dns.Msg)
mockAnswer.Answer = []dns.RR{rr1, rr2, rr3}
})
It("should block the query, if response contains a CNAME with domain on a blacklist", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("example.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 21600)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED CNAME (defaultGroup)"),
))
2020-05-04 22:20:13 +02:00
})
})
})
Describe("Whitelisting", func() {
When("Requested domain is on black and white list", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources(group1File.Path)},
WhiteLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources(group1File.Path)},
2020-05-04 22:20:13 +02:00
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
},
}
})
It("Should not be blocked", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
})
When("Only whitelist is defined", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "zeroIP",
BlockTTL: config.Duration(60 * time.Second),
2023-04-17 18:21:56 +02:00
WhiteLists: map[string][]config.BytesSource{
"gr1": config.NewBytesSources(group1File.Path),
"gr2": config.NewBytesSources(group2File.Path),
},
2020-05-04 22:20:13 +02:00
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
"one-client": {"gr1"},
"two-client": {"gr2"},
"all-client": {"gr1", "gr2"},
2020-05-04 22:20:13 +02:00
},
}
})
It("should block everything else except domains on the white list with default group", func() {
2020-05-04 22:20:13 +02:00
By("querying domain on the whitelist", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
By("querying another domain, which is not on the whitelist", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("google.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("google.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 60)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (WHITELIST ONLY)"),
))
2020-05-04 22:20:13 +02:00
Expect(m.Calls).Should(HaveLen(1))
})
})
It("should block everything else except domains on the white list "+
"if multiple white list only groups are defined", func() {
By("querying domain on the whitelist", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "one-client"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
By("querying another domain, which is not on the whitelist", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked2.com.", A, "1.2.1.2", "one-client"))).
Should(
SatisfyAll(
BeDNSRecord("blocked2.com.", A, "0.0.0.0"),
HaveTTL(BeNumerically("==", 60)),
HaveResponseType(ResponseTypeBLOCKED),
HaveReturnCode(dns.RcodeSuccess),
HaveReason("BLOCKED (WHITELIST ONLY)"),
))
Expect(m.Calls).Should(HaveLen(1))
})
})
It("should block everything else except domains on the white list "+
"if multiple white list only groups are defined", func() {
By("querying domain on the whitelist group 1", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "all-client"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
By("querying another domain, which is in the whitelist group 1", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked2.com.", A, "1.2.1.2", "all-client"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
Expect(m.Calls).Should(HaveLen(2))
})
})
2020-05-04 22:20:13 +02:00
})
When("IP address is on black and white list", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources(group1File.Path)},
WhiteLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources(defaultGroupFile.Path)},
2020-05-04 22:20:13 +02:00
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
},
}
mockAnswer, _ = util.NewMsgWithAnswer("example.com.", 300, A, "123.145.123.145")
2020-05-04 22:20:13 +02:00
})
It("should not block if DNS answer contains IP from the white list", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("example.com.", A, "123.145.123.145"),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
})
})
Describe("Delegate request to next resolver", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources(group1File.Path)},
2020-05-04 22:20:13 +02:00
ClientGroupsBlock: map[string][]string{
"default": {"gr1"},
},
}
})
AfterEach(func() {
// was delegated to next resolver
m.AssertExpectations(GinkgoT())
})
When("domain is not on the black list", func() {
It("should delegate to next resolver", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
When("no lists defined", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
}
2020-05-04 22:20:13 +02:00
})
It("should delegate to next resolver", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("example.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
})
Describe("Control status via API", func() {
BeforeEach(func() {
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{
"defaultGroup": config.NewBytesSources(defaultGroupFile.Path),
"group1": config.NewBytesSources(group1File.Path),
2020-05-04 22:20:13 +02:00
},
ClientGroupsBlock: map[string][]string{
"default": {"defaultGroup", "group1"},
2020-05-04 22:20:13 +02:00
},
BlockType: "ZeroIP",
}
})
When("Disable blocking is called", func() {
It("no query should be blocked", func() {
By("Perform query to ensure that the blocking status is active (defaultGroup)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
By("Perform query to ensure that the blocking status is active (group1)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
By("Calling Rest API to deactivate all groups", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err := sut.DisableBlocking(context.TODO(), 0, []string{})
Expect(err).Should(Succeed())
2020-05-04 22:20:13 +02:00
})
By("perform the same query again (defaultGroup)", func() {
2020-05-04 22:20:13 +02:00
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 1)
})
By("perform the same query again (group1)", func() {
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 2)
})
By("Calling Rest API to deactivate only defaultGroup", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err := sut.DisableBlocking(context.TODO(), 0, []string{"defaultGroup"})
Expect(err).Should(Succeed())
})
By("perform the same query again (defaultGroup)", func() {
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 3)
})
By("Perform query to ensure that the blocking status is active (group1)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
2020-05-04 22:20:13 +02:00
})
})
When("Disable blocking for all groups is called with a duration parameter", func() {
2020-05-04 22:20:13 +02:00
It("No query should be blocked only for passed amount of time", func() {
By("Perform query to ensure that the blocking status is active (defaultGroup)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
By("Perform query to ensure that the blocking status is active (group1)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
2020-05-04 22:20:13 +02:00
By("Calling Rest API to deactivate blocking for 0.5 sec", func() {
enabled := make(chan bool, 1)
2021-01-19 21:52:24 +01:00
err := Bus().SubscribeOnce(BlockingEnabledEvent, func(state bool) {
enabled <- state
2021-01-19 21:52:24 +01:00
})
Expect(err).Should(Succeed())
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err = sut.DisableBlocking(context.TODO(), 500*time.Millisecond, []string{})
Expect(err).Should(Succeed())
Eventually(enabled, "1s").Should(Receive(BeFalse()))
})
By("perform the same query again to ensure that this query will not be blocked (defaultGroup)", func() {
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 1)
})
By("perform the same query again to ensure that this query will not be blocked (group1)", func() {
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 2)
})
By("Wait 1 sec and perform the same query again, should be blocked now", func() {
enabled := make(chan bool, 1)
_ = Bus().SubscribeOnce(BlockingEnabledEvent, func(state bool) {
enabled <- state
})
// wait 1 sec
Eventually(enabled, "1s").Should(Receive(BeTrue()))
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
})
})
When("Disable blocking for one group is called with a duration parameter", func() {
It("No query should be blocked only for passed amount of time", func() {
By("Perform query to ensure that the blocking status is active (defaultGroup)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
By("Perform query to ensure that the blocking status is active (group1)", func() {
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
By("Calling Rest API to deactivate blocking for one group for 0.5 sec", func() {
enabled := make(chan bool, 1)
err := Bus().SubscribeOnce(BlockingEnabledEvent, func(state bool) {
enabled <- false
})
Expect(err).Should(Succeed())
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err = sut.DisableBlocking(context.TODO(), 500*time.Millisecond, []string{"group1"})
2021-01-19 21:52:24 +01:00
Expect(err).Should(Succeed())
Eventually(enabled, "1s").Should(Receive(BeFalse()))
2020-05-04 22:20:13 +02:00
})
By("perform the same query again to ensure that this query will not be blocked (defaultGroup)", func() {
2020-05-04 22:20:13 +02:00
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
})
By("perform the same query again to ensure that this query will not be blocked (group1)", func() {
// now is blocking disabled, query the url again
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
HaveNoAnswer(),
HaveResponseType(ResponseTypeRESOLVED),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
m.AssertExpectations(GinkgoT())
m.AssertNumberOfCalls(GinkgoT(), "Resolve", 1)
})
By("Wait 1 sec and perform the same query again, should be blocked now", func() {
enabled := make(chan bool, 1)
2021-01-19 21:52:24 +01:00
_ = Bus().SubscribeOnce(BlockingEnabledEvent, func(state bool) {
enabled <- state
2021-01-19 21:52:24 +01:00
})
2020-05-04 22:20:13 +02:00
// wait 1 sec
Eventually(enabled, "1s").Should(Receive(BeTrue()))
2020-05-04 22:20:13 +02:00
Expect(sut.Resolve(ctx, newRequestWithClient("blocked3.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("blocked3.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (defaultGroup)"),
HaveReturnCode(dns.RcodeSuccess),
))
Expect(sut.Resolve(ctx, newRequestWithClient("domain1.com.", A, "1.2.1.2", "unknown"))).
Should(
SatisfyAll(
BeDNSRecord("domain1.com.", A, "0.0.0.0"),
HaveResponseType(ResponseTypeBLOCKED),
HaveReason("BLOCKED (group1)"),
HaveReturnCode(dns.RcodeSuccess),
))
2020-05-04 22:20:13 +02:00
})
})
})
When("Disable blocking is called with wrong group name", func() {
It("should fail", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err := sut.DisableBlocking(context.TODO(), 500*time.Millisecond, []string{"unknownGroupName"})
Expect(err).Should(HaveOccurred())
})
})
2020-05-04 22:20:13 +02:00
When("Blocking status is called", func() {
It("should return correct status", func() {
By("enable blocking via API", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
sut.EnableBlocking(context.TODO())
2020-05-04 22:20:13 +02:00
})
By("Query blocking status via API should return 'enabled'", func() {
2021-02-04 21:59:41 +01:00
result := sut.BlockingStatus()
2020-05-04 22:20:13 +02:00
Expect(result.Enabled).Should(BeTrue())
})
By("disable blocking via API", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err := sut.DisableBlocking(context.TODO(), 500*time.Millisecond, []string{})
Expect(err).Should(Succeed())
2020-05-04 22:20:13 +02:00
})
By("Query blocking status via API again should return 'disabled'", func() {
2021-02-04 21:59:41 +01:00
result := sut.BlockingStatus()
2020-05-04 22:20:13 +02:00
Expect(result.Enabled).Should(BeFalse())
})
})
})
})
Describe("Create resolver with wrong parameter", func() {
When("Wrong blockType is used", func() {
It("should return error", func() {
2023-11-21 22:27:51 +01:00
_, err := NewBlockingResolver(ctx, config.Blocking{
2020-05-04 22:20:13 +02:00
BlockType: "wrong",
}, nil, systemResolverBootstrap)
2020-05-04 22:20:13 +02:00
Expect(err).Should(
MatchError("unknown blockType 'wrong', please use one of: ZeroIP, NxDomain or specify destination IP address(es)"))
2020-05-04 22:20:13 +02:00
})
})
2023-04-17 18:21:56 +02:00
When("strategy is failOnError", func() {
It("should fail if lists can't be downloaded", func() {
2023-11-21 22:27:51 +01:00
_, err := NewBlockingResolver(ctx, config.Blocking{
2023-04-17 18:21:56 +02:00
BlackLists: map[string][]config.BytesSource{"gr1": config.NewBytesSources("wrongPath")},
WhiteLists: map[string][]config.BytesSource{"whitelist": config.NewBytesSources("wrongPath")},
Loading: config.SourceLoadingConfig{Strategy: config.StartStrategyTypeFailOnError},
BlockType: "zeroIp",
}, nil, systemResolverBootstrap)
Expect(err).Should(HaveOccurred())
})
})
2020-05-04 22:20:13 +02:00
})
Describe("Redis is configured", func() {
var redisServer *miniredis.Miniredis
var redisClient *redis.Client
var err error
JustBeforeEach(func() {
redisServer, err = miniredis.Run()
Expect(err).Should(Succeed())
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
var rcfg config.Redis
err = defaults.Set(&rcfg)
Expect(err).Should(Succeed())
rcfg.Address = redisServer.Addr()
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
redisClient, err = redis.New(context.TODO(), &rcfg)
Expect(err).Should(Succeed())
Expect(redisClient).ShouldNot(BeNil())
2023-11-21 22:27:51 +01:00
sutConfig = config.Blocking{
BlockType: "ZEROIP",
BlockTTL: config.Duration(time.Minute),
}
sut, err = NewBlockingResolver(ctx, sutConfig, redisClient, systemResolverBootstrap)
Expect(err).Should(Succeed())
})
JustAfterEach(func() {
redisServer.Close()
})
When("disable", func() {
It("should return disable", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
sut.EnableBlocking(context.TODO())
redisMockMsg := &redis.EnabledMessage{
State: false,
}
redisClient.EnabledChannel <- redisMockMsg
Eventually(func() bool {
return sut.BlockingStatus().Enabled
}, "5s").Should(BeFalse())
})
})
When("disable", func() {
It("should return disable", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
sut.EnableBlocking(context.TODO())
redisMockMsg := &redis.EnabledMessage{
State: false,
Groups: []string{"unknown"},
}
redisClient.EnabledChannel <- redisMockMsg
Eventually(func() bool {
return sut.BlockingStatus().Enabled
}, "5s").Should(BeTrue())
})
})
When("enable", func() {
It("should return enable", func() {
Refactoring Redis (#1271) * RedisConfig -> Redis * moved redis config to seperate file * bugfix in config test during parallel processing * implement config.Configurable in Redis config * use Context in GetRedisCache * use Context in New * caching resolver test fix * use Context in PublishEnabled * use Context in getResponse * remove ctx field * bugfix in api interface test * propperly close channels * set ruler for go files from 80 to 111 * line break because function length is to long * only execute redis.New if it is enabled in config * stabilized flaky tests * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * Update config/redis_test.go Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com> * fix ruler * redis test refactoring * vscode setting cleanup * removed else if chain * Update redis_test.go * context race fix * test fail on missing seintinel servers * cleanup context usage * cleanup2 * context fixes * added context util * disabled nil context rule for tests * copy paste error ctxSend -> CtxSend * use util.CtxSend * fixed comment * fixed flaky test * failsafe and tests --------- Co-authored-by: ThinkChaos <ThinkChaos@users.noreply.github.com>
2023-11-27 18:08:31 +01:00
err = sut.DisableBlocking(context.TODO(), time.Hour, []string{})
Expect(err).Should(Succeed())
redisMockMsg := &redis.EnabledMessage{
State: true,
}
redisClient.EnabledChannel <- redisMockMsg
Eventually(func() bool {
return sut.BlockingStatus().Enabled
}, "5s").Should(BeTrue())
})
})
})
2020-05-04 22:20:13 +02:00
})