I need to get the serial
of the zone in a local file (I don't have dig
on the target server). But dnsutil.parse_zone
fails.
Here's a part of my zonefile:
[...]
@ SOA ns1.XXX.com. hostmaster.XXX.com. (
2015071501 ; serial
2H ; refresh
1H ; retry
2W ; expire
1H ; minimum
)
[...]
And the output of salt-call -l debug dnsutil.parse_zone zonefile=/path/to/myzonefile
:
[...]
DEBUG ] LazyLoaded dnsutil.parse_zone
[ERROR ] An un-handled exception was caught by salt's global exception handler:
IndexError: list index out of range
Traceback (most recent call last):
File "/usr/local/bin/salt-call", line 9, in <module>
load_entry_point('salt==2015.5.3', 'console_scripts', 'salt-call')()
File "/usr/local/lib/python2.7/site-packages/salt/scripts.py", line 227, in salt_call
client.run()
File "/usr/local/lib/python2.7/site-packages/salt/cli/call.py", line 69, in run
caller.run()
File "/usr/local/lib/python2.7/site-packages/salt/cli/caller.py", line 236, in run
ret = self.call()
File "/usr/local/lib/python2.7/site-packages/salt/cli/caller.py", line 138, in call
ret['return'] = func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/salt/modules/dnsutil.py", line 173, in parse_zone
zonedict['EXPIRE'] = _to_seconds(comps[8])
IndexError: list index out of range
Traceback (most recent call last):
File "/usr/local/bin/salt-call", line 9, in <module>
load_entry_point('salt==2015.5.3', 'console_scripts', 'salt-call')()
File "/usr/local/lib/python2.7/site-packages/salt/scripts.py", line 227, in salt_call
client.run()
File "/usr/local/lib/python2.7/site-packages/salt/cli/call.py", line 69, in run
caller.run()
File "/usr/local/lib/python2.7/site-packages/salt/cli/caller.py", line 236, in run
ret = self.call()
File "/usr/local/lib/python2.7/site-packages/salt/cli/caller.py", line 138, in call
ret['return'] = func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/salt/modules/dnsutil.py", line 173, in parse_zone
zonedict['EXPIRE'] = _to_seconds(comps[8])
IndexError: list index out of range
Is it my zone's SOA record syntax error or some "imperfection" in parse_zone
function?
@yermulnik, I am no zone expert, but salt shouldn't error out on an incorrect file format. If it is wrong, it should tell you why. :-)
And it doesn't error out on an incorrect file format =) The format is right. Salt just erroneously counts fields of SOA
record in my zone file example, I guess.
Here's a bit of code from dnsutil.py
:
if 'SOA' in line:
if comps[1] != 'IN':
comps.pop(1)
zonedict['ORIGIN'] = comps[0]
zonedict['NETWORK'] = comps[1]
zonedict['SOURCE'] = comps[3]
zonedict['CONTACT'] = comps[4].replace('.', '@', 1)
zonedict['SERIAL'] = comps[5]
zonedict['REFRESH'] = _to_seconds(comps[6])
zonedict['RETRY'] = _to_seconds(comps[7])
zonedict['EXPIRE'] = _to_seconds(comps[8])
zonedict['MINTTL'] = _to_seconds(comps[9])
continue
According to code from dnsutil.py
SOA
record in my zone is parsed in a wrong way: it pops field SOA
and as a result comps
has another fields list and count as dnsutil.py
expects it to be.
By the way second field in a SOA
record according to RFC can be TTL
or CLASS
. Both of them are optional. And CLASS
can be not only IN
, but CH
or HS
as well (though its a rare case).
So, I guess, that condition in a mentioned code should be rewritten. Hope someone could do that =)
Zone SOA
record format reference: http://www.zytrax.com/books/dns/ch8/soa.html
Thanks @yermulnik. If salt needs to parse zone files, it shouldn't fail on a correctly formatted file.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.
Well, if this function is not that popular, I can close this ticket unresolved =(
This patch solves the described issues for me (salt 3000.3):
--- /usr/lib/python3/dist-packages/salt/modules/dnsutil.py 2020-05-07 14:37:42.000000000 +0000
+++ /usr/lib/python3/dist-packages/salt/modules/dnsutil-fix.py 2020-08-21 15:07:44.049898578 +0000
@@ -165,17 +165,22 @@
else:
comps = line.split()
if 'SOA' in line:
- if comps[1] != 'IN':
+ zonedict['NETWORK'] = 'IN'
+ for network in ['CH', 'CS', 'HS', 'IN']:
+ if network in comps:
+ zonedict['NETWORK'] = network
+ comps.pop(comps.index(network))
+ if comps[2] == 'SOA':
+ # an optional TTL is present
comps.pop(1)
zonedict['ORIGIN'] = comps[0]
- zonedict['NETWORK'] = comps[1]
- zonedict['SOURCE'] = comps[3]
- zonedict['CONTACT'] = comps[4].replace('.', '@', 1)
- zonedict['SERIAL'] = comps[5]
- zonedict['REFRESH'] = _to_seconds(comps[6])
- zonedict['RETRY'] = _to_seconds(comps[7])
- zonedict['EXPIRE'] = _to_seconds(comps[8])
- zonedict['MINTTL'] = _to_seconds(comps[9])
+ zonedict['SOURCE'] = comps[2]
+ zonedict['CONTACT'] = comps[3].replace('.', '@', 1)
+ zonedict['SERIAL'] = comps[4]
+ zonedict['REFRESH'] = _to_seconds(comps[5])
+ zonedict['RETRY'] = _to_seconds(comps[6])
+ zonedict['EXPIRE'] = _to_seconds(comps[7])
+ zonedict['MINTTL'] = _to_seconds(comps[8])
continue
if comps[0] == 'IN':
comps.insert(0, zonedict['ORIGIN'])
Most helpful comment
This patch solves the described issues for me (salt 3000.3):