dns-zonefile 1.1.0 → 1.1.9
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 +5 -5
- data/.gitignore +10 -3
- data/.rspec +2 -0
- data/.travis.yml +8 -2
- data/CONTRIBUTING.md +36 -0
- data/Dockerfile +1 -1
- data/Gemfile +1 -1
- data/README.md +11 -15
- data/Rakefile +2 -7
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +6 -0
- data/dns-zonefile.gemspec +34 -24
- data/examples/basic.rb +12 -0
- data/examples/basic_origin.rb +15 -0
- data/examples/example.com.no-origin.zonefile +16 -0
- data/examples/example.com.zonefile +17 -0
- data/lib/dns/zonefile.rb +197 -200
- data/lib/dns/zonefile.treetop +47 -12
- data/lib/dns/zonefile/version.rb +1 -1
- metadata +57 -36
- data/spec/dns/zonefile_spec.rb +0 -435
- data/spec/spec_helper.rb +0 -2
data/lib/dns/zonefile.treetop
CHANGED
@@ -53,7 +53,7 @@ grammar Zonefile
|
|
53
53
|
end
|
54
54
|
|
55
55
|
rule resource_record
|
56
|
-
record:(a_record / aaaa_record / cname_record / mx_record / naptr_record / ns_record / ptr_record / srv_record / spf_record / txt_record / soa_record) space* comment? linebreak {
|
56
|
+
record:(a_record / aaaa_record / caa_record / cname_record / mx_record / naptr_record / ns_record / ptr_record / srv_record / spf_record / sshfp_record / txt_record / soa_record) space* comment? linebreak {
|
57
57
|
def zone
|
58
58
|
p = parent
|
59
59
|
while p.respond_to?(:parent) && p.parent
|
@@ -128,6 +128,28 @@ grammar Zonefile
|
|
128
128
|
}
|
129
129
|
end
|
130
130
|
|
131
|
+
rule caa_record
|
132
|
+
(
|
133
|
+
host space ms_age ttl klass "CAA" space flags:integer space tag:unquoted_string space value:caa_value
|
134
|
+
) {
|
135
|
+
def to_s
|
136
|
+
"#{host} #{ttl} #{klass} CAA #{flags} #{tag} #{value}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def record_type
|
140
|
+
"CAA"
|
141
|
+
end
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
rule caa_value
|
146
|
+
(quoted_string / unquoted_string) {
|
147
|
+
def to_s
|
148
|
+
text_value
|
149
|
+
end
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
131
153
|
rule cname_record
|
132
154
|
(
|
133
155
|
host space ms_age ttl klass "CNAME" space target:host /
|
@@ -221,7 +243,7 @@ grammar Zonefile
|
|
221
243
|
end
|
222
244
|
}
|
223
245
|
end
|
224
|
-
|
246
|
+
|
225
247
|
rule spf_record
|
226
248
|
host space ms_age ttl klass "SPF" space data:txt_data {
|
227
249
|
def to_s
|
@@ -233,7 +255,19 @@ grammar Zonefile
|
|
233
255
|
end
|
234
256
|
}
|
235
257
|
end
|
236
|
-
|
258
|
+
|
259
|
+
rule sshfp_record
|
260
|
+
host space ms_age ttl klass "SSHFP" space alg:integer space fptype:integer space fp:fingerprint {
|
261
|
+
def to_s
|
262
|
+
"#{host} #{ttl} #{klass} SSHFP #{alg} #{fptype} #{fp}"
|
263
|
+
end
|
264
|
+
|
265
|
+
def record_type
|
266
|
+
"SSHFP"
|
267
|
+
end
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
237
271
|
rule txt_record
|
238
272
|
host space ms_age ttl klass "TXT" space data:ms_txt_data {
|
239
273
|
def to_s
|
@@ -436,14 +470,15 @@ grammar Zonefile
|
|
436
470
|
rule host
|
437
471
|
( ([*a-zA-Z0-9\-\._]+) / "@" / ' ' / "\t" ) {
|
438
472
|
def to_s
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
473
|
+
text_value
|
474
|
+
end
|
475
|
+
}
|
476
|
+
end
|
477
|
+
|
478
|
+
rule fingerprint
|
479
|
+
[a-fA-Z0-9:]+ {
|
480
|
+
def to_s
|
481
|
+
text_value.strip
|
447
482
|
end
|
448
483
|
}
|
449
484
|
end
|
@@ -492,7 +527,7 @@ grammar Zonefile
|
|
492
527
|
end
|
493
528
|
|
494
529
|
rule unquoted_string
|
495
|
-
[a-zA-Z0-9]+ {
|
530
|
+
[a-zA-Z0-9=_]+ {
|
496
531
|
def to_s
|
497
532
|
text_value
|
498
533
|
end
|
data/lib/dns/zonefile/version.rb
CHANGED
metadata
CHANGED
@@ -1,72 +1,87 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dns-zonefile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig R Webster
|
8
|
+
- Anthony Eden
|
8
9
|
autorequire:
|
9
|
-
bindir:
|
10
|
+
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: treetop
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - "
|
18
|
+
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
20
|
+
version: '1.6'
|
21
|
+
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - "
|
25
|
+
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
+
version: '1.6'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
+
name: polyglot
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- - "
|
32
|
+
- - "~>"
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
+
version: '0.3'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.3'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: bundler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.1'
|
34
49
|
type: :development
|
35
50
|
prerelease: false
|
36
51
|
version_requirements: !ruby/object:Gem::Requirement
|
37
52
|
requirements:
|
38
|
-
- - "
|
53
|
+
- - "~>"
|
39
54
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
55
|
+
version: '2.1'
|
41
56
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
57
|
+
name: rake
|
43
58
|
requirement: !ruby/object:Gem::Requirement
|
44
59
|
requirements:
|
45
|
-
- - "
|
60
|
+
- - "~>"
|
46
61
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :
|
62
|
+
version: '13.0'
|
63
|
+
type: :development
|
49
64
|
prerelease: false
|
50
65
|
version_requirements: !ruby/object:Gem::Requirement
|
51
66
|
requirements:
|
52
|
-
- - "
|
67
|
+
- - "~>"
|
53
68
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
69
|
+
version: '13.0'
|
55
70
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
71
|
+
name: rspec
|
57
72
|
requirement: !ruby/object:Gem::Requirement
|
58
73
|
requirements:
|
59
|
-
- - "
|
74
|
+
- - "~>"
|
60
75
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :
|
76
|
+
version: '3.0'
|
77
|
+
type: :development
|
63
78
|
prerelease: false
|
64
79
|
version_requirements: !ruby/object:Gem::Requirement
|
65
80
|
requirements:
|
66
|
-
- - "
|
81
|
+
- - "~>"
|
67
82
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
description:
|
83
|
+
version: '3.0'
|
84
|
+
description: |
|
70
85
|
The format of a DNS Zonefile is defined in RFC 1035 section 5 and RFC
|
71
86
|
1034 section 3.6.1. To anyone who's using BIND they'll look very
|
72
87
|
familiar.
|
@@ -76,32 +91,41 @@ description: |-
|
|
76
91
|
some canonical form.
|
77
92
|
email:
|
78
93
|
- craig@barkingiguana.com
|
94
|
+
- anthonyeden@gmail.com
|
79
95
|
executables: []
|
80
96
|
extensions: []
|
81
97
|
extra_rdoc_files: []
|
82
98
|
files:
|
83
99
|
- ".gitignore"
|
100
|
+
- ".rspec"
|
84
101
|
- ".travis.yml"
|
102
|
+
- CONTRIBUTING.md
|
85
103
|
- Dockerfile
|
86
104
|
- Gemfile
|
87
105
|
- LICENCE
|
88
106
|
- README.md
|
89
107
|
- Rakefile
|
90
108
|
- TODO
|
109
|
+
- bin/console
|
110
|
+
- bin/setup
|
111
|
+
- circle.yml
|
91
112
|
- dns-zonefile.gemspec
|
92
113
|
- doc/example.com.zone
|
93
114
|
- doc/example2.com.zone
|
94
115
|
- doc/example3.com.zone
|
95
116
|
- doc/zonefile.example
|
96
117
|
- docker-compose.yml
|
118
|
+
- examples/basic.rb
|
119
|
+
- examples/basic_origin.rb
|
120
|
+
- examples/example.com.no-origin.zonefile
|
121
|
+
- examples/example.com.zonefile
|
97
122
|
- lib/dns/zonefile.rb
|
98
123
|
- lib/dns/zonefile.treetop
|
99
124
|
- lib/dns/zonefile/version.rb
|
100
|
-
|
101
|
-
- spec/spec_helper.rb
|
102
|
-
homepage: ''
|
125
|
+
homepage: https://github.com/craigw/dns-zonefile
|
103
126
|
licenses: []
|
104
|
-
metadata:
|
127
|
+
metadata:
|
128
|
+
allowed_push_host: https://rubygems.org
|
105
129
|
post_install_message:
|
106
130
|
rdoc_options: []
|
107
131
|
require_paths:
|
@@ -117,11 +141,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
141
|
- !ruby/object:Gem::Version
|
118
142
|
version: '0'
|
119
143
|
requirements: []
|
120
|
-
|
121
|
-
rubygems_version: 2.4.5.1
|
144
|
+
rubygems_version: 3.1.2
|
122
145
|
signing_key:
|
123
146
|
specification_version: 4
|
124
147
|
summary: Work with zonefiles (RFC 1035 section 5 and RFC 1034 section 3.6.1)
|
125
|
-
test_files:
|
126
|
-
- spec/dns/zonefile_spec.rb
|
127
|
-
- spec/spec_helper.rb
|
148
|
+
test_files: []
|
data/spec/dns/zonefile_spec.rb
DELETED
@@ -1,435 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'dns/zonefile'
|
3
|
-
|
4
|
-
RSpec.describe "DNS::Zonefile" do
|
5
|
-
it "should be versioned" do
|
6
|
-
expect { DNS::Zonefile.const_get(:VERSION) }.to_not raise_error
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should provide a way of parsing a string" do
|
10
|
-
expect(DNS::Zonefile).to respond_to(:parse)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "parsing a zonefile string" do
|
14
|
-
before(:each) do
|
15
|
-
@zonefile =<<-ZONE
|
16
|
-
; Hi! I'm an example zonefile.
|
17
|
-
$ORIGIN example.com.
|
18
|
-
$TTL 86400; expire in 1 day.
|
19
|
-
$OTHER abc
|
20
|
-
; line above has spaces at the end, but no comment
|
21
|
-
@ IN SOA ns.example.com. hostmaster\\.awesome.example.com. (
|
22
|
-
;
|
23
|
-
2007120710 ; serial number of this zone file
|
24
|
-
;two
|
25
|
-
;comments
|
26
|
-
1d ; slave refresh (1 day)
|
27
|
-
1d ; slave retry time in case of a problem (1 day)
|
28
|
-
4W ; slave expiration time (4 weeks)
|
29
|
-
3600 ; minimum caching time in case of failed lookups (1 hour)
|
30
|
-
)
|
31
|
-
; That's the SOA part done.
|
32
|
-
|
33
|
-
; Next comment line has nothing after the semi-colon.
|
34
|
-
;
|
35
|
-
|
36
|
-
; Let's start the resource records.
|
37
|
-
example.com. NS ns ; ns.example.com is the nameserver for example.com
|
38
|
-
example.com. NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
|
39
|
-
example.com. A 10.0.0.1 ; ip address for "example.com". next line has spaces after the IP, but no actual comment.
|
40
|
-
@ A 10.0.0.11
|
41
|
-
A 10.0.0.12 ; tertiary ip for "example.com"
|
42
|
-
ns A 10.0.0.2 ; ip address for "ns.example.com"
|
43
|
-
60 A 10.0.0.21 ; secondary ip for "ns.example.com" with TTL
|
44
|
-
* A 10.0.0.100 ; wildcard
|
45
|
-
*.sub A 10.0.0.101 ; subdomain wildcard
|
46
|
-
with-class IN A 10.0.0.3 ; record that includes the class type of IN
|
47
|
-
with-ttl 60 A 10.0.0.5 ; with a specified TTL
|
48
|
-
ttl-class 60 IN A 10.0.0.6 ; with TTL and class type
|
49
|
-
www CNAME ns ; "www.example.com" is an alias for "ns.example.com"
|
50
|
-
wwwtest CNAME www ; "wwwtest.example.com" is another alias for "www.example.com"
|
51
|
-
www2 CNAME ns.example.com. ; yet another alias, with FQDN target
|
52
|
-
|
53
|
-
; Email... that'll be fun then
|
54
|
-
example.com. MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
|
55
|
-
@ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
|
56
|
-
@ MX 50 mail3 ; Similar to above line, but using a host within this domain
|
57
|
-
|
58
|
-
@ AAAA 2001:db8:a::1 ; IPv6, lowercase
|
59
|
-
ns AAAA 2001:DB8:B::1 ; IPv6, uppercase
|
60
|
-
mail AAAA 2001:db8:c::10.0.0.4 ; IPv6, with trailing IPv4-type address
|
61
|
-
|
62
|
-
sip NAPTR 100 10 "U" "E2U+sip" "!^.*$!sip:cs@example.com!i" . ; NAPTR record
|
63
|
-
sip2 NAPTR 100 10 "" "" "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i" . ; another one
|
64
|
-
|
65
|
-
_xmpp-server._tcp SRV 5 0 5269 xmpp-server.l.google.com. ; SRV record
|
66
|
-
|
67
|
-
; TXT record, with embedded semicolons
|
68
|
-
_domainkey TXT "v=DKIM1\\;g=*\\;k=rsa\\; p=4tkw1bbkfa0ahfjgnbewr2ttkvahvfmfizowl9s4g0h28io76ndow25snl9iumpcv0jwxr2k"
|
69
|
-
with_ms_txt TXT ( "Some text" )
|
70
|
-
|
71
|
-
@ TXT "some other \\"message\\" goes here" ; embedded quotes
|
72
|
-
long TXT "a multi-segment TXT record" "usually used for really long TXT records" "since each segment can only span 255 chars"
|
73
|
-
unquoted TXT some text data
|
74
|
-
|
75
|
-
multiline TXT "A TXT record
|
76
|
-
split across multiple lines
|
77
|
-
with LF and CRLF line endings"
|
78
|
-
|
79
|
-
; Microsoft AD DNS Examples with Aging.
|
80
|
-
with-age [AGE:999992222] 60 A 10.0.0.7 ; with a specified AGE
|
81
|
-
with-age-aaaa [AGE:999992222] 60 AAAA 10.0.0.8 ; with a specified AGE
|
82
|
-
_ldap._tcp.pupy._sites.dc._msdcs [AGE:3636525] 600 SRV 0 100 389 host01.ad
|
83
|
-
P229392922 [AGE:3636449] 172800 CNAME printer01.ad
|
84
|
-
|
85
|
-
@ SPF "v=spf1 a a:other.domain.com ~all"
|
86
|
-
|
87
|
-
45 IN PTR @
|
88
|
-
|
89
|
-
|
90
|
-
eam 900 IN SRV 5 0 5269 www
|
91
|
-
eam IN 900 SRV 5 0 5269 www
|
92
|
-
eam IN SRV 5 0 5269 www
|
93
|
-
eam 900 SRV 5 0 5269 www
|
94
|
-
eam SRV 5 0 5269 www
|
95
|
-
|
96
|
-
eam 900 IN CNAME www
|
97
|
-
eam IN 900 CNAME www
|
98
|
-
eam IN CNAME www
|
99
|
-
eam 900 CNAME www
|
100
|
-
eam CNAME www
|
101
|
-
|
102
|
-
$ORIGIN test.example.com.
|
103
|
-
$TTL 3600; expire in 1 day.
|
104
|
-
@ A 10.1.0.1 ; Test with alternate origin
|
105
|
-
MX 10 mail.example.com.
|
106
|
-
www A 10.1.0.2 ; www.test.example.com.
|
107
|
-
|
108
|
-
ZONE
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should set the origin correctly" do
|
112
|
-
zone = DNS::Zonefile.parse(@zonefile)
|
113
|
-
expect(zone.origin).to eq('@')
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should interpret the origin correctly" do
|
117
|
-
zone = DNS::Zonefile.load(@zonefile)
|
118
|
-
expect(zone.soa.origin).to eq('example.com.')
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should set the zone variables correctly" do
|
122
|
-
zone = DNS::Zonefile.parse(@zonefile)
|
123
|
-
expect(zone.variables['TTL']).to eq('86400')
|
124
|
-
expect(zone.variables['ORIGIN']).to eq('example.com.')
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should interpret the SOA correctly" do
|
128
|
-
zone = DNS::Zonefile.load(@zonefile)
|
129
|
-
soa = zone.soa
|
130
|
-
expect(soa.klass).to eq('IN')
|
131
|
-
expect(soa.ttl).to eq(86400)
|
132
|
-
expect(soa.nameserver).to eq('ns.example.com.')
|
133
|
-
expect(soa.responsible_party).to eq('hostmaster\.awesome.example.com.')
|
134
|
-
expect(soa.serial).to eq(2007120710)
|
135
|
-
expect(soa.refresh_time).to eq(86400)
|
136
|
-
expect(soa.retry_time).to eq(86400)
|
137
|
-
expect(soa.expiry_time).to eq(2419200)
|
138
|
-
expect(soa.nxttl).to eq(3600)
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should build the correct number of resource records" do
|
142
|
-
zone = DNS::Zonefile.parse(@zonefile)
|
143
|
-
expect(zone.rr.size).to eq(49)
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should build the correct NS records" do
|
147
|
-
zone = DNS::Zonefile.load(@zonefile)
|
148
|
-
ns_records = zone.records_of DNS::Zonefile::NS
|
149
|
-
expect(ns_records.size).to eq(2)
|
150
|
-
|
151
|
-
expect(ns_records.detect { |ns|
|
152
|
-
ns.host == "example.com." && ns.nameserver == "ns.example.com."
|
153
|
-
}).to_not be_nil
|
154
|
-
|
155
|
-
expect(ns_records.detect { |ns|
|
156
|
-
ns.host == "example.com." && ns.nameserver == "ns.somewhere.com." && ns.ttl == 86400
|
157
|
-
}).to_not be_nil
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should build the correct A records" do
|
161
|
-
zone = DNS::Zonefile.load(@zonefile)
|
162
|
-
a_records = zone.records_of DNS::Zonefile::A
|
163
|
-
expect(a_records.size).to eq(13)
|
164
|
-
|
165
|
-
expect(a_records.detect { |a|
|
166
|
-
a.host == "example.com." && a.address == "10.0.0.1"
|
167
|
-
}).to_not be_nil
|
168
|
-
|
169
|
-
expect(a_records.detect { |a|
|
170
|
-
a.host == "example.com." && a.address == "10.0.0.11"
|
171
|
-
}).to_not be_nil
|
172
|
-
|
173
|
-
expect(a_records.detect { |a|
|
174
|
-
a.host == "example.com." && a.address == "10.0.0.12"
|
175
|
-
}).to_not be_nil
|
176
|
-
|
177
|
-
expect(a_records.detect { |a|
|
178
|
-
a.host == "ns.example.com." && a.address == "10.0.0.2" && a.ttl == 86400
|
179
|
-
}).to_not be_nil
|
180
|
-
|
181
|
-
expect(a_records.detect { |a|
|
182
|
-
a.host == "ns.example.com." && a.address == "10.0.0.21" && a.ttl == 60
|
183
|
-
}).to_not be_nil
|
184
|
-
|
185
|
-
expect(a_records.detect { |a|
|
186
|
-
a.host == "*.example.com." && a.address == "10.0.0.100"
|
187
|
-
}).to_not be_nil
|
188
|
-
|
189
|
-
expect(a_records.detect { |a|
|
190
|
-
a.host == "*.sub.example.com." && a.address == "10.0.0.101"
|
191
|
-
}).to_not be_nil
|
192
|
-
|
193
|
-
expect(a_records.detect { |a|
|
194
|
-
a.host == "with-class.example.com." && a.address == "10.0.0.3" && a.ttl == 86400
|
195
|
-
}).to_not be_nil
|
196
|
-
|
197
|
-
expect(a_records.detect { |a|
|
198
|
-
a.host == "with-ttl.example.com." && a.address == "10.0.0.5" && a.ttl == 60
|
199
|
-
}).to_not be_nil
|
200
|
-
|
201
|
-
expect(a_records.detect { |a|
|
202
|
-
a.host == "with-age.example.com." && a.address == "10.0.0.7" && a.ttl == 60
|
203
|
-
}).to_not be_nil
|
204
|
-
|
205
|
-
expect(a_records.detect { |a|
|
206
|
-
a.host == "ttl-class.example.com." && a.address == "10.0.0.6" && a.ttl == 60
|
207
|
-
}).to_not be_nil
|
208
|
-
|
209
|
-
expect(a_records.detect { |a|
|
210
|
-
a.host == "test.example.com." && a.address == "10.1.0.1" && a.ttl == 3600
|
211
|
-
}).to_not be_nil
|
212
|
-
|
213
|
-
expect(a_records.detect { |a|
|
214
|
-
a.host == "www.test.example.com." && a.address == "10.1.0.2" && a.ttl == 3600
|
215
|
-
}).to_not be_nil
|
216
|
-
end
|
217
|
-
|
218
|
-
it "should build the correct CNAME records" do
|
219
|
-
zone = DNS::Zonefile.load(@zonefile)
|
220
|
-
cname_records = zone.records_of DNS::Zonefile::CNAME
|
221
|
-
expect(cname_records.size).to eq(9)
|
222
|
-
|
223
|
-
expect(cname_records.detect { |cname|
|
224
|
-
cname.host == "www.example.com." && cname.target == "ns.example.com."
|
225
|
-
}).to_not be_nil
|
226
|
-
|
227
|
-
expect(cname_records.detect { |cname|
|
228
|
-
cname.host == "wwwtest.example.com." && cname.domainname == "www.example.com."
|
229
|
-
}).to_not be_nil
|
230
|
-
|
231
|
-
expect(cname_records.detect { |cname|
|
232
|
-
cname.host == "www2.example.com." && cname.domainname == "ns.example.com." && cname.ttl == 86400
|
233
|
-
}).to_not be_nil
|
234
|
-
|
235
|
-
expect(cname_records.detect { |cname|
|
236
|
-
cname.host == "P229392922.example.com." && cname.domainname == "printer01.ad.example.com." && cname.ttl == 172800
|
237
|
-
}).to_not be_nil
|
238
|
-
|
239
|
-
eam_records = cname_records.select { |c| c.host =~ /eam\./ }
|
240
|
-
|
241
|
-
expect(eam_records.length).to eq(5)
|
242
|
-
|
243
|
-
eam_records.each { |cname|
|
244
|
-
expect(cname.target).to eq("www.example.com.")
|
245
|
-
}
|
246
|
-
|
247
|
-
r = eam_records.group_by { |c| c.ttl }
|
248
|
-
expect(r[900].length).to eq(3)
|
249
|
-
expect(r[86400].length).to eq(2)
|
250
|
-
end
|
251
|
-
|
252
|
-
it "should build the correct MX records" do
|
253
|
-
zone = DNS::Zonefile.load(@zonefile)
|
254
|
-
mx_records = zone.records_of DNS::Zonefile::MX
|
255
|
-
expect(mx_records.length).to eq(4)
|
256
|
-
|
257
|
-
expect(mx_records.detect { |mx|
|
258
|
-
mx.host == "example.com." && mx.priority == 10 && mx.exchanger == 'mail.example.com.'
|
259
|
-
}).to_not be_nil
|
260
|
-
|
261
|
-
expect(mx_records.detect { |mx|
|
262
|
-
mx.host == "example.com." && mx.priority == 20 && mx.exchange == 'mail2.example.com.'
|
263
|
-
}).to_not be_nil
|
264
|
-
|
265
|
-
expect(mx_records.detect { |mx|
|
266
|
-
mx.host == "example.com." && mx.priority == 50 && mx.domainname == 'mail3.example.com.' && mx.ttl == 86400
|
267
|
-
}).to_not be_nil
|
268
|
-
|
269
|
-
expect(mx_records.detect { |mx|
|
270
|
-
mx.host == "test.example.com." && mx.priority == 10 && mx.domainname == 'mail.example.com.' && mx.ttl == 3600
|
271
|
-
}).to_not be_nil
|
272
|
-
end
|
273
|
-
|
274
|
-
it "should build the correct AAAA records" do
|
275
|
-
zone = DNS::Zonefile.load(@zonefile)
|
276
|
-
aaaa_records = zone.records_of DNS::Zonefile::AAAA
|
277
|
-
expect(aaaa_records.length).to eq(4)
|
278
|
-
|
279
|
-
expect(aaaa_records.detect { |a|
|
280
|
-
a.host == "example.com." && a.address == "2001:db8:a::1"
|
281
|
-
}).to_not be_nil
|
282
|
-
|
283
|
-
expect(aaaa_records.detect { |a|
|
284
|
-
a.host == "ns.example.com." && a.address == "2001:db8:b::1"
|
285
|
-
}).to_not be_nil
|
286
|
-
|
287
|
-
expect(aaaa_records.detect { |a|
|
288
|
-
a.host == "mail.example.com." && a.address == "2001:db8:c::10.0.0.4" && a.ttl == 86400
|
289
|
-
}).to_not be_nil
|
290
|
-
|
291
|
-
expect(aaaa_records.detect { |a|
|
292
|
-
a.host == "with-age-aaaa.example.com." && a.address == "10.0.0.8" && a.ttl == 60
|
293
|
-
}).to_not be_nil
|
294
|
-
|
295
|
-
end
|
296
|
-
|
297
|
-
it "should build the correct NAPTR records" do
|
298
|
-
zone = DNS::Zonefile.load(@zonefile)
|
299
|
-
naptr_records = zone.records_of DNS::Zonefile::NAPTR
|
300
|
-
expect(naptr_records.length).to eq(2)
|
301
|
-
|
302
|
-
expect(naptr_records.detect { |r|
|
303
|
-
r.host == "sip.example.com." && r.data == '100 10 "U" "E2U+sip" "!^.*$!sip:cs@example.com!i" .'
|
304
|
-
}).to_not be_nil
|
305
|
-
|
306
|
-
expect(naptr_records.detect { |r|
|
307
|
-
r.host == "sip2.example.com." && r.data == %q{100 10 "" "" "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i" .} && r.ttl == 86400
|
308
|
-
}).to_not be_nil
|
309
|
-
end
|
310
|
-
|
311
|
-
it "should build the correct SRV records" do
|
312
|
-
zone = DNS::Zonefile.load(@zonefile)
|
313
|
-
srv_records = zone.records_of DNS::Zonefile::SRV
|
314
|
-
expect(srv_records.length).to eq(7)
|
315
|
-
|
316
|
-
expect(srv_records.detect { |r|
|
317
|
-
r.host == "_xmpp-server._tcp.example.com." && r.priority == 5 && r.weight == 0 && r.port == 5269 && r.target == 'xmpp-server.l.google.com.' && r.ttl == 86400
|
318
|
-
}).to_not be_nil
|
319
|
-
|
320
|
-
expect(srv_records.detect { |r|
|
321
|
-
r.host == "_ldap._tcp.pupy._sites.dc._msdcs.example.com." && r.priority == 0 && r.weight == 100 && r.port == 389 && r.target == 'host01.ad.example.com.' && r.ttl == 600
|
322
|
-
}).to_not be_nil
|
323
|
-
|
324
|
-
eam_records = srv_records.select { |s| s.host =~ /eam\./ }
|
325
|
-
expect(eam_records.length).to eq(5)
|
326
|
-
eam_records.each { |srv|
|
327
|
-
expect(srv.target).to eq("www.example.com.")
|
328
|
-
expect(srv.priority).to eq(5)
|
329
|
-
expect(srv.port).to eq(5269)
|
330
|
-
expect(srv.weight).to eq(0)
|
331
|
-
}
|
332
|
-
|
333
|
-
r = eam_records.group_by { |c| c.ttl }
|
334
|
-
expect(r[900].length).to eq(3)
|
335
|
-
expect(r[86400].length).to eq(2)
|
336
|
-
end
|
337
|
-
|
338
|
-
it "should build the correct TXT records" do
|
339
|
-
zone = DNS::Zonefile.load(@zonefile)
|
340
|
-
txt_records = zone.records_of DNS::Zonefile::TXT
|
341
|
-
expect(txt_records.size).to eq(6)
|
342
|
-
|
343
|
-
expect(txt_records.detect { |r|
|
344
|
-
r.host == "_domainkey.example.com." && r.data == '"v=DKIM1\;g=*\;k=rsa\; p=4tkw1bbkfa0ahfjgnbewr2ttkvahvfmfizowl9s4g0h28io76ndow25snl9iumpcv0jwxr2k"'
|
345
|
-
}).to_not be_nil
|
346
|
-
|
347
|
-
expect(txt_records.detect { |r|
|
348
|
-
r.host == "with_ms_txt.example.com." && r.data == '"Some text"'
|
349
|
-
}).to_not be_nil
|
350
|
-
|
351
|
-
expect(txt_records.detect { |r|
|
352
|
-
r.host == "example.com." && r.data == '"some other \"message\" goes here"' && r.ttl == 86400
|
353
|
-
}).to_not be_nil
|
354
|
-
|
355
|
-
expect(txt_records.detect { |r|
|
356
|
-
r.host == "long.example.com." && r.data == '"a multi-segment TXT record" "usually used for really long TXT records" "since each segment can only span 255 chars"'
|
357
|
-
}).to_not be_nil
|
358
|
-
|
359
|
-
expect(txt_records.detect { |r|
|
360
|
-
r.host == "unquoted.example.com." && r.data == 'some text data'
|
361
|
-
}).to_not be_nil
|
362
|
-
|
363
|
-
expect(txt_records.detect { |r|
|
364
|
-
r.host == "multiline.example.com." && r.data == "\"A TXT record\nsplit across multiple lines\nwith LF and CRLF line endings\""
|
365
|
-
}).to_not be_nil
|
366
|
-
end
|
367
|
-
|
368
|
-
it "should build the correct SPF records" do
|
369
|
-
zone = DNS::Zonefile.load(@zonefile)
|
370
|
-
spf_records = zone.records_of DNS::Zonefile::SPF
|
371
|
-
expect(spf_records.length).to eq(1)
|
372
|
-
|
373
|
-
expect(spf_records.detect { |r|
|
374
|
-
r.host == "example.com." && r.data == '"v=spf1 a a:other.domain.com ~all"' && r.ttl == 86400
|
375
|
-
}).to_not be_nil
|
376
|
-
end
|
377
|
-
|
378
|
-
it "should build the correct PTR records" do
|
379
|
-
zone = DNS::Zonefile.load(@zonefile)
|
380
|
-
ptr_records = zone.records_of DNS::Zonefile::PTR
|
381
|
-
expect(ptr_records.length).to eq(1)
|
382
|
-
|
383
|
-
expect(ptr_records.detect { |r|
|
384
|
-
r.host == "45.example.com." && r.target == 'example.com.' && r.ttl == 86400
|
385
|
-
}).to_not be_nil
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
describe "parsing an SOA without parens" do
|
390
|
-
before(:each) do
|
391
|
-
@zonefile =<<-ZONE
|
392
|
-
example.com. 86400 IN SOA ns0.example.com. hostmaster.example.com. 2006010558 43200 3600 1209600 180
|
393
|
-
example.com. 3600 IN A 1.2.3.4
|
394
|
-
example.com. 86400 IN SOA ns0.example.com. hostmaster.example.com. 2006010558 43200 3600 1209600 180
|
395
|
-
|
396
|
-
ZONE
|
397
|
-
end
|
398
|
-
|
399
|
-
it "should parse the SOA record correctly" do
|
400
|
-
zone = DNS::Zonefile.load(@zonefile)
|
401
|
-
soa = zone.soa
|
402
|
-
expect(soa.klass).to eql('IN')
|
403
|
-
expect(soa.ttl).to eql(86400)
|
404
|
-
expect(soa.nameserver).to eql('ns0.example.com.')
|
405
|
-
expect(soa.responsible_party).to eql('hostmaster.example.com.')
|
406
|
-
expect(soa.serial).to eql(2006010558)
|
407
|
-
expect(soa.refresh_time).to eql(43200)
|
408
|
-
expect(soa.retry_time).to eql(3600)
|
409
|
-
expect(soa.expiry_time).to eql(1209600)
|
410
|
-
expect(soa.nxttl).to eql(180)
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
describe "parsing an SOA with just . for responsible party" do
|
415
|
-
before(:each) do
|
416
|
-
@zonefile =<<-ZONE
|
417
|
-
@ IN SOA ns.domain.example.com. . (
|
418
|
-
2007120710 ; serial number of this zone file
|
419
|
-
1d ; slave refresh (1 day)
|
420
|
-
1d ; slave retry time in case of a problem (1 day)
|
421
|
-
4W ; slave expiration time (4 weeks)
|
422
|
-
3600 ; minimum caching time in case of failed lookups (1 hour)
|
423
|
-
)
|
424
|
-
ZONE
|
425
|
-
end
|
426
|
-
|
427
|
-
it "should parse the SOA record correctly" do
|
428
|
-
zone = DNS::Zonefile.load(@zonefile)
|
429
|
-
soa = zone.soa
|
430
|
-
expect(soa.klass).to eql('IN')
|
431
|
-
expect(soa.nameserver).to eql('ns.domain.example.com.')
|
432
|
-
expect(soa.responsible_party).to eql('.')
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|