diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/README.md b/README.md index c0987a4..efb743b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ You need Python 3 and [Requests](http://python-requests.org/). You can install R Then, copy the script `check_expire` and the file `ianardap.py`to the directory of local plugins. +The use of a cache directory is not mandatory, but highly recommended. It can be either `$XDG_CACHE_HOME/ianardap` or `$HOME/.ianardapcaches` depending on the environment variables set. + ## Icinga configuration If you use Icinga, here is a possible definition of the command: @@ -35,6 +37,7 @@ object CheckCommand "expiration" { "-v" = { set_if = "$expiration_verbose$" } } + env.XDG_CACHE_HOME = "/var/cache/nagios" } apply Service "expiration" { @@ -60,6 +63,13 @@ object Host "bortzmeyer-org" { } ``` +If needed, create the cache directory accordingly: + +``` +mkdir /var/cache/nagios +chown nagios: /var/cache/nagios +``` + ## Zabbix configuration For monitoring systems that do not rely on exit codes but on calculation mechanism based on the metric they receive you can use the `-u` option that will only return the expiration date in unixtime format. diff --git a/check_expire b/check_expire index 329304e..2fca3ad 100755 --- a/check_expire +++ b/check_expire @@ -53,6 +53,8 @@ def usage(msg=None): print("") def details(): + if database and not database.cachefile: + print(" (WARNING: no cache directory used, please set environement variable XDG_CACHE_HOME or HOME.)", end="") if verbose: print(" RDAP database \"%s\", version %s published on %s, retrieved on %s, RDAP server is %s" % \ (database.description, database.version, database.publication, database.retrieved, server)) diff --git a/ianardap.py b/ianardap.py index 473aa56..5bd1796 100755 --- a/ianardap.py +++ b/ianardap.py @@ -21,7 +21,8 @@ IANABASES = {"domains": "https://data.iana.org/rdap/dns.json", "v6prefixes": "https://data.iana.org/rdap/ipv6.json", "as": "https://data.iana.org/rdap/asn.json", "objects": "https://data.iana.org/rdap/object-tags.json"} -CACHE = os.environ["HOME"] + "/.ianardapcaches" +CACHE = os.environ["XDG_CACHE_HOME"] + "/ianardap" if "XDG_CACHE_HOME" in os.environ else \ + (os.environ["HOME"] + "/.ianardapcaches" if "HOME" in os.environ else None) MAXAGE = 24 # Hours. Used only if the server no longer gives the information. IANATIMEOUT = 10 # Seconds MAXTESTS = 3 # Maximum attempts to get the database @@ -60,28 +61,33 @@ file (see the documentation of the module). """ cache_valid = False - if not os.path.exists(cachedir): - os.mkdir(cachedir) self.category = category - cachefile = os.path.join(cachedir, category) - if pickleformat: - self.cachefile = cachefile + ".pickle" - else: - self.cachefile = cachefile + ".json" - self.lockname = self.cachefile + ".lock" - self.expirationfile = self.cachefile + ".expires" + self.cachefile = None + self.lockname = None + self.expirationfile = None + if cachedir: + if not os.path.exists(cachedir): + os.mkdir(cachedir) + cachefile = os.path.join(cachedir, category) + if pickleformat: + self.cachefile = cachefile + ".pickle" + else: + self.cachefile = cachefile + ".json" + self.lockname = self.cachefile + ".lock" + self.expirationfile = self.cachefile + ".expires" if maxage is not None: - with open(self.expirationfile, 'w'): - self.expirationtime = time.mktime((datetime.datetime.now() + \ - datetime.timedelta(hours=maxage)).timetuple()) - os.utime(self.expirationfile, - times = (self.expirationtime, self.expirationtime)) + self.expirationtime = time.mktime((datetime.datetime.now() + \ + datetime.timedelta(hours=maxage)).timetuple()) + if self.expirationfile: + with open(self.expirationfile, 'w'): + os.utime(self.expirationfile, + times = (self.expirationtime, self.expirationtime)) loaded = False tests = 0 errmsg = "No error" while not loaded and tests < MAXTESTS: self.lock() - if os.path.exists(self.cachefile) and \ + if self.cachefile and os.path.exists(self.cachefile) and \ (pathlib.Path(self.expirationfile).exists() and \ datetime.datetime.fromtimestamp(os.path.getmtime(self.expirationfile)) > \ datetime.datetime.now()): @@ -139,9 +145,10 @@ file (see the documentation of the module). try: content = response.content database = json.loads(content) - with open(self.expirationfile, 'w'): - os.utime(self.expirationfile, - times = (self.expirationtime, self.expirationtime)) + if self.expirationfile: + with open(self.expirationfile, 'w'): + os.utime(self.expirationfile, + times = (self.expirationtime, self.expirationtime)) except json.decoder.JSONDecodeError: tests += 1 errmsg = "Invalid JSON retrieved from %s" % IANABASE @@ -173,7 +180,7 @@ file (see the documentation of the module). else: # IP addresses will be complicated, because of the # longest prefix rule. raise Exception("Unsupported category %s" % self.category) - if not cache_valid: + if self.cachefile and not cache_valid: self.lock() cache = open(self.cachefile, "wb") if pickleformat: @@ -184,12 +191,14 @@ file (see the documentation of the module). self.unlock() def lock(self): - self.lockhandle = open(self.lockname, 'w') - fcntl.lockf(self.lockhandle, fcntl.LOCK_EX) + if self.lockname: + self.lockhandle = open(self.lockname, 'w') + fcntl.lockf(self.lockhandle, fcntl.LOCK_EX) def unlock(self): - fcntl.lockf(self.lockhandle, fcntl.LOCK_UN) - self.lockhandle.close() + if self.lockname: + fcntl.lockf(self.lockhandle, fcntl.LOCK_UN) + self.lockhandle.close() def find(self, id): """Get the RDAP server(s), as an array, for a given identifier. None diff --git a/test_ianardap.py b/test_ianardap.py index 0dfdb88..f2910ec 100644 --- a/test_ianardap.py +++ b/test_ianardap.py @@ -29,8 +29,9 @@ def test_refresh(): # Force a resfresh database = ianardap.IanaRDAPDatabase(maxage=0) assert (database.retrieved > (datetime.datetime.now() - datetime.timedelta(minutes=1))) and \ + ((not database.cachefile) or \ (datetime.datetime.fromtimestamp(os.path.getmtime(database.cachefile)) > \ - (datetime.datetime.now() - datetime.timedelta(minutes=1))) + (datetime.datetime.now() - datetime.timedelta(minutes=1)))) def test_find_exists(): database = ianardap.IanaRDAPDatabase()