coppertone 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.travis.yml +7 -0
- data/Gemfile +7 -0
- data/LICENSE +201 -0
- data/README.md +58 -0
- data/Rakefile +140 -0
- data/coppertone.gemspec +27 -0
- data/lib/coppertone/class_builder.rb +20 -0
- data/lib/coppertone/directive.rb +38 -0
- data/lib/coppertone/dns/error.rb +9 -0
- data/lib/coppertone/dns/mock_client.rb +106 -0
- data/lib/coppertone/dns/resolv_client.rb +110 -0
- data/lib/coppertone/dns.rb +3 -0
- data/lib/coppertone/domain_spec.rb +45 -0
- data/lib/coppertone/error.rb +29 -0
- data/lib/coppertone/ip_address_wrapper.rb +75 -0
- data/lib/coppertone/macro_context.rb +67 -0
- data/lib/coppertone/macro_string/macro_expand.rb +84 -0
- data/lib/coppertone/macro_string/macro_literal.rb +24 -0
- data/lib/coppertone/macro_string/macro_parser.rb +62 -0
- data/lib/coppertone/macro_string/macro_static_expand.rb +52 -0
- data/lib/coppertone/macro_string.rb +31 -0
- data/lib/coppertone/mechanism/a.rb +16 -0
- data/lib/coppertone/mechanism/all.rb +24 -0
- data/lib/coppertone/mechanism/cidr_parser.rb +14 -0
- data/lib/coppertone/mechanism/domain_spec_mechanism.rb +18 -0
- data/lib/coppertone/mechanism/domain_spec_optional.rb +46 -0
- data/lib/coppertone/mechanism/domain_spec_required.rb +37 -0
- data/lib/coppertone/mechanism/domain_spec_with_dual_cidr.rb +114 -0
- data/lib/coppertone/mechanism/exists.rb +14 -0
- data/lib/coppertone/mechanism/include.rb +18 -0
- data/lib/coppertone/mechanism/include_matcher.rb +34 -0
- data/lib/coppertone/mechanism/ip4.rb +13 -0
- data/lib/coppertone/mechanism/ip6.rb +13 -0
- data/lib/coppertone/mechanism/ip_mechanism.rb +48 -0
- data/lib/coppertone/mechanism/mx.rb +40 -0
- data/lib/coppertone/mechanism/ptr.rb +17 -0
- data/lib/coppertone/mechanism.rb +32 -0
- data/lib/coppertone/modifier/base.rb +24 -0
- data/lib/coppertone/modifier/exp.rb +34 -0
- data/lib/coppertone/modifier/redirect.rb +17 -0
- data/lib/coppertone/modifier/unknown.rb +16 -0
- data/lib/coppertone/modifier.rb +30 -0
- data/lib/coppertone/qualifier.rb +45 -0
- data/lib/coppertone/record.rb +86 -0
- data/lib/coppertone/record_evaluator.rb +63 -0
- data/lib/coppertone/record_finder.rb +34 -0
- data/lib/coppertone/request.rb +68 -0
- data/lib/coppertone/request_context.rb +67 -0
- data/lib/coppertone/request_count_limiter.rb +36 -0
- data/lib/coppertone/result.rb +50 -0
- data/lib/coppertone/sender_identity.rb +39 -0
- data/lib/coppertone/spf_service.rb +9 -0
- data/lib/coppertone/term.rb +13 -0
- data/lib/coppertone/utils/domain_utils.rb +59 -0
- data/lib/coppertone/utils/host_utils.rb +22 -0
- data/lib/coppertone/utils/ip_in_domain_checker.rb +53 -0
- data/lib/coppertone/utils/validated_domain_finder.rb +40 -0
- data/lib/coppertone/utils.rb +4 -0
- data/lib/coppertone/version.rb +3 -0
- data/lib/coppertone.rb +48 -0
- data/lib/resolv/dns/resource/in/spf.rb +15 -0
- data/spec/directive_spec.rb +41 -0
- data/spec/dns/resolv_client_spec.rb +307 -0
- data/spec/domain_spec_spec.rb +35 -0
- data/spec/ip_address_wrapper_spec.rb +67 -0
- data/spec/macro_context_spec.rb +69 -0
- data/spec/macro_string/macro_expand_spec.rb +79 -0
- data/spec/macro_string/macro_literal_spec.rb +27 -0
- data/spec/macro_string/macro_static_expand_spec.rb +67 -0
- data/spec/macro_string_spec.rb +20 -0
- data/spec/mechanism/a_spec.rb +198 -0
- data/spec/mechanism/all_spec.rb +22 -0
- data/spec/mechanism/exists_spec.rb +91 -0
- data/spec/mechanism/include_spec.rb +43 -0
- data/spec/mechanism/ip4_spec.rb +110 -0
- data/spec/mechanism/ip6_spec.rb +104 -0
- data/spec/mechanism/mx_spec.rb +51 -0
- data/spec/mechanism/ptr_spec.rb +43 -0
- data/spec/mechanism_spec.rb +4 -0
- data/spec/modifier_spec.rb +4 -0
- data/spec/open_spf/ALL_mechanism_syntax_spec.rb +38 -0
- data/spec/open_spf/A_mechanism_syntax_spec.rb +159 -0
- data/spec/open_spf/EXISTS_mechanism_syntax_spec.rb +46 -0
- data/spec/open_spf/IP4_mechanism_syntax_spec.rb +59 -0
- data/spec/open_spf/IP6_mechanism_syntax_spec.rb +60 -0
- data/spec/open_spf/Include_mechanism_semantics_and_syntax_spec.rb +56 -0
- data/spec/open_spf/Initial_processing_spec.rb +77 -0
- data/spec/open_spf/MX_mechanism_syntax_spec.rb +119 -0
- data/spec/open_spf/Macro_expansion_rules_spec.rb +154 -0
- data/spec/open_spf/PTR_mechanism_syntax_spec.rb +42 -0
- data/spec/open_spf/Processing_limits_spec.rb +72 -0
- data/spec/open_spf/Record_evaluation_spec.rb +75 -0
- data/spec/open_spf/Record_lookup_spec.rb +48 -0
- data/spec/open_spf/Selecting_records_spec.rb +61 -0
- data/spec/open_spf/Semantics_of_exp_and_other_modifiers_spec.rb +167 -0
- data/spec/open_spf/Test_cases_from_implementation_bugs_spec.rb +17 -0
- data/spec/qualifier_spec.rb +54 -0
- data/spec/record_evaluator_spec.rb +4 -0
- data/spec/record_finder_spec.rb +4 -0
- data/spec/record_spec.rb +100 -0
- data/spec/request_context_spec.rb +43 -0
- data/spec/request_count_limiter_spec.rb +28 -0
- data/spec/result_spec.rb +4 -0
- data/spec/rfc7208-tests.yml +2548 -0
- data/spec/sender_identity_spec.rb +69 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/term_spec.rb +38 -0
- data/spec/utils/domain_utils_spec.rb +60 -0
- data/spec/utils/host_utils_spec.rb +32 -0
- data/spec/utils/ip_in_domain_checker_spec.rb +4 -0
- data/spec/utils/validated_domain_finder_spec.rb +4 -0
- metadata +306 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::MacroString::MacroLiteral do
|
|
4
|
+
let(:arg) { SecureRandom.hex(10) }
|
|
5
|
+
let(:macro) { Coppertone::MacroString::MacroLiteral.new(arg) }
|
|
6
|
+
|
|
7
|
+
it 'should expand to the argument' do
|
|
8
|
+
expect(macro.expand(double)).to eq(arg)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should reduce to the argument in the macro form' do
|
|
12
|
+
expect(macro.to_s).to eq(arg)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'equality' do
|
|
16
|
+
it 'should treat different MacroLiterals with the same value as equal' do
|
|
17
|
+
expect(macro == Coppertone::MacroString::MacroLiteral.new(arg))
|
|
18
|
+
.to eql(true)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'otherwise should treat different MacroLiterals as unequal' do
|
|
22
|
+
other_arg = SecureRandom.hex(10)
|
|
23
|
+
expect(macro == Coppertone::MacroString::MacroLiteral.new(other_arg))
|
|
24
|
+
.to eql(false)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::MacroString::MacroStaticExpand do
|
|
4
|
+
context '#exists_for?' do
|
|
5
|
+
%w(%% %_ %-).each do |x|
|
|
6
|
+
it "should resolve a macro for the key #{x}" do
|
|
7
|
+
expect(Coppertone::MacroString::MacroStaticExpand.exists_for?(x))
|
|
8
|
+
.to eq(true)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should return false for invalid keys' do
|
|
13
|
+
expect(Coppertone::MacroString::MacroStaticExpand.exists_for?('%a'))
|
|
14
|
+
.to eq(false)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'macro_for' do
|
|
19
|
+
%w(%% %_ %-).each do |x|
|
|
20
|
+
it "should resolve a macro for the key #{x}" do
|
|
21
|
+
expect(Coppertone::MacroString::MacroStaticExpand.macro_for(x))
|
|
22
|
+
.not_to be_nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should raise an error for invalid keys' do
|
|
27
|
+
expect do
|
|
28
|
+
Coppertone::MacroString::MacroStaticExpand.macro_for('%a')
|
|
29
|
+
end.to raise_error(Coppertone::MacroStringParsingError)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should not allow creation of new macros' do
|
|
34
|
+
expect do
|
|
35
|
+
Coppertone::MacroString::MacroStaticExpand.new('a', 'b')
|
|
36
|
+
end.to raise_error(NoMethodError)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'percent macro' do
|
|
40
|
+
let(:macro) { Coppertone::MacroString::MacroStaticExpand::PERCENT_MACRO }
|
|
41
|
+
|
|
42
|
+
it 'should return the expected values' do
|
|
43
|
+
expect(macro.expand(nil)).to eq('%')
|
|
44
|
+
expect(macro.to_s).to eq('%%')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'space macro' do
|
|
49
|
+
let(:macro) { Coppertone::MacroString::MacroStaticExpand::SPACE_MACRO }
|
|
50
|
+
|
|
51
|
+
it 'should return the expected values' do
|
|
52
|
+
expect(macro.expand(nil)).to eq(' ')
|
|
53
|
+
expect(macro.to_s).to eq('%_')
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'url encoded space macro' do
|
|
58
|
+
let(:macro) do
|
|
59
|
+
Coppertone::MacroString::MacroStaticExpand::URL_ENCODED_SPACE_MACRO
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'should return the expected values' do
|
|
63
|
+
expect(macro.expand(nil)).to eq('%20')
|
|
64
|
+
expect(macro.to_s).to eq('%-')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::MacroString do
|
|
4
|
+
context 'equality' do
|
|
5
|
+
it 'should treat different MacroStrings with the same value as equal' do
|
|
6
|
+
arg = 'abc.%{dr-}.%%.test.com'
|
|
7
|
+
macro_string = Coppertone::MacroString.new(arg)
|
|
8
|
+
expect(macro_string == Coppertone::MacroString.new(arg))
|
|
9
|
+
.to eql(true)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should otherwise treat different MacroStrings as unequal' do
|
|
13
|
+
arg = 'abc.%{dr-}.%%.test.com'
|
|
14
|
+
macro_string = Coppertone::MacroString.new(arg)
|
|
15
|
+
other_arg = 'eabc.%{dr-}.%%.test.com'
|
|
16
|
+
expect(macro_string == Coppertone::MacroString.new(other_arg))
|
|
17
|
+
.to eql(false)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::A do
|
|
4
|
+
context '#new' do
|
|
5
|
+
it 'should not fail if called with a nil argument' do
|
|
6
|
+
mech = Coppertone::Mechanism::A.new(nil)
|
|
7
|
+
expect(mech).not_to be_nil
|
|
8
|
+
expect(mech.domain_spec).to be_nil
|
|
9
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
10
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should not fail if called with a blank argument' do
|
|
14
|
+
mech = Coppertone::Mechanism::A.new('')
|
|
15
|
+
expect(mech).not_to be_nil
|
|
16
|
+
expect(mech.domain_spec).to be_nil
|
|
17
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
18
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should fail if called with an invalid macrostring' do
|
|
22
|
+
expect do
|
|
23
|
+
Coppertone::Mechanism::A.new(':abc%:def')
|
|
24
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should parse a domain spec' do
|
|
28
|
+
mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com')
|
|
29
|
+
expect(mech).not_to be_nil
|
|
30
|
+
expect(mech.domain_spec)
|
|
31
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
|
32
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
33
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'should parse a valid IP v4 CIDR length with a domain spec' do
|
|
37
|
+
mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com/28')
|
|
38
|
+
expect(mech).not_to be_nil
|
|
39
|
+
expect(mech.domain_spec)
|
|
40
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
|
41
|
+
expect(mech.ip_v4_cidr_length).to eq('28')
|
|
42
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'should fail if called with an invalid macrostring and IPv4 CIDR' do
|
|
46
|
+
expect do
|
|
47
|
+
Coppertone::Mechanism::A.new(':abc%:def/28')
|
|
48
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'should parse a valid IP v4 CIDR length' do
|
|
52
|
+
mech = Coppertone::Mechanism::A.new('/28')
|
|
53
|
+
expect(mech).not_to be_nil
|
|
54
|
+
expect(mech.domain_spec).to be_nil
|
|
55
|
+
expect(mech.ip_v4_cidr_length).to eq('28')
|
|
56
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'should not parse an invalid IP v4 CIDR length' do
|
|
60
|
+
expect do
|
|
61
|
+
Coppertone::Mechanism::A.new('/36')
|
|
62
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
63
|
+
|
|
64
|
+
expect do
|
|
65
|
+
Coppertone::Mechanism::A.new('/a')
|
|
66
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'should parse a valid IP v6 CIDR length with a domain spec' do
|
|
70
|
+
mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com//64')
|
|
71
|
+
expect(mech).not_to be_nil
|
|
72
|
+
expect(mech.domain_spec)
|
|
73
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
|
74
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
75
|
+
expect(mech.ip_v6_cidr_length).to eq('64')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should fail if called with an invalid macrostring and IPv6 CIDR' do
|
|
79
|
+
expect do
|
|
80
|
+
Coppertone::Mechanism::A.new(':abc%:def//64')
|
|
81
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should parse a valid IP v6 CIDR length' do
|
|
85
|
+
mech = Coppertone::Mechanism::A.new('//64')
|
|
86
|
+
expect(mech).not_to be_nil
|
|
87
|
+
expect(mech.domain_spec).to be_nil
|
|
88
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
89
|
+
expect(mech.ip_v6_cidr_length).to eq('64')
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should not parse an invalid IP v6 CIDR length' do
|
|
93
|
+
expect do
|
|
94
|
+
Coppertone::Mechanism::A.new('//133')
|
|
95
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
96
|
+
|
|
97
|
+
expect do
|
|
98
|
+
Coppertone::Mechanism::A.new('//a')
|
|
99
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'should parse a valid dual CIDR length with a domain spec' do
|
|
103
|
+
mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com/28//64')
|
|
104
|
+
expect(mech).not_to be_nil
|
|
105
|
+
expect(mech.domain_spec)
|
|
106
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
|
107
|
+
expect(mech.ip_v4_cidr_length).to eq('28')
|
|
108
|
+
expect(mech.ip_v6_cidr_length).to eq('64')
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should not parse a invalid dual CIDR length with a domain spec' do
|
|
112
|
+
expect do
|
|
113
|
+
Coppertone::Mechanism::A.new('_spf.%{d}.example.com/28//133')
|
|
114
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
115
|
+
expect do
|
|
116
|
+
Coppertone::Mechanism::A.new('_spf.%{d}.example.com/44//64')
|
|
117
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should fail if called with an invalid macrostring and dual CIDR' do
|
|
121
|
+
expect do
|
|
122
|
+
Coppertone::Mechanism::A.new('abc%:def/28//64')
|
|
123
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context '#create' do
|
|
128
|
+
it 'should fail if called with a nil argument' do
|
|
129
|
+
mech = Coppertone::Mechanism::A.create(nil)
|
|
130
|
+
expect(mech).not_to be_nil
|
|
131
|
+
expect(mech.domain_spec).to be_nil
|
|
132
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
133
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'should fail if called with a blank argument' do
|
|
137
|
+
mech = Coppertone::Mechanism::A.create('')
|
|
138
|
+
expect(mech).not_to be_nil
|
|
139
|
+
expect(mech.domain_spec).to be_nil
|
|
140
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
|
141
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'should fail if called with an argument invalid macrostring' do
|
|
145
|
+
expect do
|
|
146
|
+
Coppertone::Mechanism::A.create('abc%:def')
|
|
147
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context '#match?' do
|
|
152
|
+
context 'simple' do
|
|
153
|
+
let(:mech_domain) { 'gmail.com' }
|
|
154
|
+
let(:mech_arg) { ":#{mech_domain}" }
|
|
155
|
+
let(:gmail_dns_client) do
|
|
156
|
+
dc = double(:dns_client)
|
|
157
|
+
allow(dc).to receive(:fetch_a_records)
|
|
158
|
+
.with(mech_domain).and_return([
|
|
159
|
+
{
|
|
160
|
+
type: 'A',
|
|
161
|
+
address: '74.125.239.117'
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
type: 'A',
|
|
165
|
+
address: '74.125.239.118'
|
|
166
|
+
}
|
|
167
|
+
])
|
|
168
|
+
dc
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
let(:domain) { 'yahoo.com' }
|
|
172
|
+
let(:matching_context) do
|
|
173
|
+
Coppertone::MacroContext.new(domain, '74.125.239.118', 'bob@gmail.com')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
let(:not_matching_context) do
|
|
177
|
+
Coppertone::MacroContext.new(domain, '74.125.249.118', 'bob@gmail.com')
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
before do
|
|
181
|
+
allow(Coppertone::DNS::ResolvClient)
|
|
182
|
+
.to receive(:new).and_return(gmail_dns_client)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'should match when the IP matches the record' do
|
|
186
|
+
mech = Coppertone::Mechanism::A.create(mech_arg)
|
|
187
|
+
expect(mech.match?(matching_context, Coppertone::RequestContext.new))
|
|
188
|
+
.to eq(true)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'should not match when the IP does not match the record' do
|
|
192
|
+
mech = Coppertone::Mechanism::A.create(mech_arg)
|
|
193
|
+
expect(mech.match?(not_matching_context, Coppertone::RequestContext.new))
|
|
194
|
+
.to eq(false)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::All do
|
|
4
|
+
subject { Coppertone::Mechanism::All.instance }
|
|
5
|
+
it 'should always return true regardless of argument' do
|
|
6
|
+
expect(subject.match?(double, double)).to eq(true)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should not allow creation of new instances' do
|
|
10
|
+
expect do
|
|
11
|
+
Coppertone::Mechanism::All.new('')
|
|
12
|
+
end.to raise_error(NoMethodError)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context '#create' do
|
|
16
|
+
it 'should fail if any arguments are passed that are not blank' do
|
|
17
|
+
expect do
|
|
18
|
+
Coppertone::Mechanism::All.create('abcd')
|
|
19
|
+
end.to raise_error(Coppertone::RecordParsingError)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::Exists do
|
|
4
|
+
context '#new' do
|
|
5
|
+
it 'should fail if called with a nil argument' do
|
|
6
|
+
expect do
|
|
7
|
+
Coppertone::Mechanism::Exists.new(nil)
|
|
8
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should fail if called with a blank argument' do
|
|
12
|
+
expect do
|
|
13
|
+
Coppertone::Mechanism::Exists.new('')
|
|
14
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should fail if called with an invalid macrostring' do
|
|
18
|
+
expect do
|
|
19
|
+
Coppertone::Mechanism::Exists.new(':abc%:def')
|
|
20
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context '#create' do
|
|
25
|
+
it 'should fail if called with a nil argument' do
|
|
26
|
+
expect do
|
|
27
|
+
Coppertone::Mechanism::Exists.create(nil)
|
|
28
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should fail if called with a blank argument' do
|
|
32
|
+
expect do
|
|
33
|
+
Coppertone::Mechanism::Exists.create('')
|
|
34
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should fail if called with an invalid macrostring' do
|
|
38
|
+
expect do
|
|
39
|
+
Coppertone::Mechanism::Exists.create(':abc%:def')
|
|
40
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context '#match?' do
|
|
45
|
+
context 'simple' do
|
|
46
|
+
let(:mech_domain) { 'iexist.com' }
|
|
47
|
+
let(:mech_arg) { ":#{mech_domain}" }
|
|
48
|
+
let(:bad_domain) { 'idontexist.com' }
|
|
49
|
+
let(:bad_arg) { ":#{bad_domain}" }
|
|
50
|
+
let(:dns_client) do
|
|
51
|
+
dc = double(:dns_client)
|
|
52
|
+
allow(dc).to receive(:fetch_a_records)
|
|
53
|
+
.with(mech_domain).and_return([
|
|
54
|
+
{
|
|
55
|
+
type: 'A',
|
|
56
|
+
address: '74.125.234.117'
|
|
57
|
+
}
|
|
58
|
+
])
|
|
59
|
+
allow(dc).to receive(:fetch_a_records)
|
|
60
|
+
.with(bad_domain).and_return([])
|
|
61
|
+
dc
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
let(:domain) { 'yahoo.com' }
|
|
65
|
+
let(:matching_context) do
|
|
66
|
+
Coppertone::MacroContext.new(domain, '74.125.239.118', 'bob@gmail.com')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
let(:not_matching_context) do
|
|
70
|
+
Coppertone::MacroContext.new(domain, '74.125.249.118', 'bob@gmail.com')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
before do
|
|
74
|
+
allow(Coppertone::DNS::ResolvClient)
|
|
75
|
+
.to receive(:new).and_return(dns_client)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should match when the domain record for the target name exists' do
|
|
79
|
+
mech = Coppertone::Mechanism::Exists.create(mech_arg)
|
|
80
|
+
expect(mech.match?(matching_context, Coppertone::RequestContext.new))
|
|
81
|
+
.to eq(true)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should match when the domain record for the target name exists' do
|
|
85
|
+
mech = Coppertone::Mechanism::Exists.create(bad_arg)
|
|
86
|
+
expect(mech.match?(matching_context, Coppertone::RequestContext.new))
|
|
87
|
+
.to eq(false)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::Include do
|
|
4
|
+
context '#new' do
|
|
5
|
+
it 'should fail if called with a nil argument' do
|
|
6
|
+
expect do
|
|
7
|
+
Coppertone::Mechanism::Include.new(nil)
|
|
8
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should fail if called with a blank argument' do
|
|
12
|
+
expect do
|
|
13
|
+
Coppertone::Mechanism::Include.new('')
|
|
14
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should fail if called with an invalid macrostring' do
|
|
18
|
+
expect do
|
|
19
|
+
Coppertone::Mechanism::Include.new('abc%:def')
|
|
20
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context '#create' do
|
|
25
|
+
it 'should fail if called with a nil argument' do
|
|
26
|
+
expect do
|
|
27
|
+
Coppertone::Mechanism::Include.create(nil)
|
|
28
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should fail if called with a blank argument' do
|
|
32
|
+
expect do
|
|
33
|
+
Coppertone::Mechanism::Include.create('')
|
|
34
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should fail if called with an argument invalid macrostring' do
|
|
38
|
+
expect do
|
|
39
|
+
Coppertone::Mechanism::Include.create('abc%:def')
|
|
40
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::IP4 do
|
|
4
|
+
context '#new' do
|
|
5
|
+
it 'should fail if called with a nil argument' do
|
|
6
|
+
expect do
|
|
7
|
+
Coppertone::Mechanism::IP4.new(nil)
|
|
8
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should fail if called with a blank argument' do
|
|
12
|
+
expect do
|
|
13
|
+
Coppertone::Mechanism::IP4.new('')
|
|
14
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should fail if called with an invalid IP' do
|
|
18
|
+
expect do
|
|
19
|
+
Coppertone::Mechanism::IP4.new(':not_an_ip')
|
|
20
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should not fail if called with an IP v6' do
|
|
24
|
+
mech = Coppertone::Mechanism::IP4.new(':fe80::202:b3ff:fe1e:8329')
|
|
25
|
+
expect(mech.ip_network).to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should work if called with an IP4' do
|
|
29
|
+
mech = Coppertone::Mechanism::IP4.new(':1.2.3.4')
|
|
30
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should work if called with an IP4 with a pfxlen' do
|
|
34
|
+
mech = Coppertone::Mechanism::IP4.new(':1.2.3.4/4')
|
|
35
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4/4'))
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context '#create' do
|
|
40
|
+
it 'should fail if called with a nil argument' do
|
|
41
|
+
expect do
|
|
42
|
+
Coppertone::Mechanism::IP4.create(nil)
|
|
43
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should fail if called with a blank argument' do
|
|
47
|
+
expect do
|
|
48
|
+
Coppertone::Mechanism::IP4.create('')
|
|
49
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should fail if called with an invalid IP' do
|
|
53
|
+
expect do
|
|
54
|
+
Coppertone::Mechanism::IP4.create(':not_an_ip')
|
|
55
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should not fail if called with an IP v6' do
|
|
59
|
+
mech = Coppertone::Mechanism::IP4.create(':fe80::202:b3ff:fe1e:8329')
|
|
60
|
+
expect(mech.ip_network).to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'should work if called with an IP4' do
|
|
64
|
+
mech = Coppertone::Mechanism::IP4.create(':1.2.3.4')
|
|
65
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should work if called with an IP4 with a pfxlen' do
|
|
69
|
+
mech = Coppertone::Mechanism::IP4.create('1.2.3.4/4')
|
|
70
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4/4'))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should fail if called with an invalid pfxlen' do
|
|
74
|
+
expect do
|
|
75
|
+
Coppertone::Mechanism::IP4.new('1.2.3.4/127')
|
|
76
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context '.match' do
|
|
81
|
+
let(:client_ip) { IPAddr.new('4.5.6.7') }
|
|
82
|
+
|
|
83
|
+
let(:macro_context) do
|
|
84
|
+
mc = double(:macro_context)
|
|
85
|
+
allow(mc).to receive(:ip_v4).and_return(client_ip)
|
|
86
|
+
mc
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
let(:ip_v6_macro_context) do
|
|
90
|
+
mc = double(:macro_context)
|
|
91
|
+
allow(mc).to receive(:ip_v4).and_return(nil)
|
|
92
|
+
mc
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'should return true if the client IP is in the network' do
|
|
96
|
+
mech = Coppertone::Mechanism::IP4.create('4.5.6.0/29')
|
|
97
|
+
expect(mech.match?(macro_context, double)).to eq(true)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should return false if the client IP is not in the network' do
|
|
101
|
+
mech = Coppertone::Mechanism::IP4.create('4.5.6.0/30')
|
|
102
|
+
expect(mech.match?(macro_context, double)).to eq(false)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'should return false if the client IP is v6 only' do
|
|
106
|
+
mech = Coppertone::Mechanism::IP4.create('4.5.6.0/29')
|
|
107
|
+
expect(mech.match?(ip_v6_macro_context, double)).to eq(false)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Coppertone::Mechanism::IP6 do
|
|
4
|
+
context '#new' do
|
|
5
|
+
it 'should fail if called with a nil argument' do
|
|
6
|
+
expect do
|
|
7
|
+
Coppertone::Mechanism::IP6.new(nil)
|
|
8
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should fail if called with a blank argument' do
|
|
12
|
+
expect do
|
|
13
|
+
Coppertone::Mechanism::IP6.new('')
|
|
14
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should fail if called with an invalid IP' do
|
|
18
|
+
expect do
|
|
19
|
+
Coppertone::Mechanism::IP6.new('not_an_ip')
|
|
20
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should not fail if called with an IP v4' do
|
|
24
|
+
mech = Coppertone::Mechanism::IP6.new('1.2.3.4')
|
|
25
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should work if called with an IP6' do
|
|
29
|
+
mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329')
|
|
30
|
+
expect(mech.ip_network)
|
|
31
|
+
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should work if called with an IP6 with a pfxlen' do
|
|
35
|
+
mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/64')
|
|
36
|
+
expect(mech.ip_network)
|
|
37
|
+
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should fail if called with an invalid pfxlen' do
|
|
41
|
+
expect do
|
|
42
|
+
Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/384')
|
|
43
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context '#create' do
|
|
49
|
+
it 'should fail if called with a nil argument' do
|
|
50
|
+
expect do
|
|
51
|
+
Coppertone::Mechanism::IP6.create(nil)
|
|
52
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'should fail if called with a blank argument' do
|
|
56
|
+
expect do
|
|
57
|
+
Coppertone::Mechanism::IP6.create('')
|
|
58
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'should fail if called with an invalid IP' do
|
|
62
|
+
expect do
|
|
63
|
+
Coppertone::Mechanism::IP6.create('not_an_ip')
|
|
64
|
+
end.to raise_error(Coppertone::InvalidMechanismError)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should not fail if called with an IP v4' do
|
|
68
|
+
mech = Coppertone::Mechanism::IP6.create('1.2.3.4')
|
|
69
|
+
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should work if called with an IP6' do
|
|
73
|
+
mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329')
|
|
74
|
+
expect(mech.ip_network)
|
|
75
|
+
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should work if called with an IP6 with a pfxlen' do
|
|
79
|
+
mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329/64')
|
|
80
|
+
expect(mech.ip_network)
|
|
81
|
+
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context '.match' do
|
|
86
|
+
let(:client_ip) { IPAddr.new('fe80::202:b3ff:fe1e:8329') }
|
|
87
|
+
|
|
88
|
+
let(:macro_context) do
|
|
89
|
+
mc = double(:macro_context)
|
|
90
|
+
allow(mc).to receive(:ip_v6).and_return(client_ip)
|
|
91
|
+
mc
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should return true if the client IP is in the network' do
|
|
95
|
+
mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/120')
|
|
96
|
+
expect(mech.match?(macro_context, double)).to eq(true)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should return false if the client IP is not in the network' do
|
|
100
|
+
mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/126')
|
|
101
|
+
expect(mech.match?(macro_context, double)).to eq(false)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|