Initial commit
Signed-off-by: Alarig Le Lay <alarig@swordarmor.fr>
This commit is contained in:
commit
5d3fff24f7
53
README.md
Normal file
53
README.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
Script intented to check a domain expiration with a query to the corresponding
|
||||
RDAP server.
|
||||
|
||||
This script is inspired from
|
||||
https://raw.githubusercontent.com/buanzo/check_expiration_rdap/main/src/nagios_check_domain_expiration_rdap/nagios_check_domain_expiration_rdap.py
|
||||
and `/usr/lib/python3.11/site-packages/nagiosplugin/examples/`
|
||||
|
||||
The script assumes that the TLD has only one label while looking for the RDAP
|
||||
server from the IANA JSON. If it’s not the case it will fail.
|
||||
|
||||
I don’t understand half of what I wrote
|
||||
|
||||
Have fun.
|
||||
|
||||
Here are the tested cases:
|
||||
```shell
|
||||
# expired domain
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py found.com.br
|
||||
EXPIRATION CRITICAL - -31 days until domain expires (outside range @~:15) | daystoexpiration=-31d;@15:30;@~:15
|
||||
zsh: exit 2 ./check_domain_expiration_rdap.py found.com.br
|
||||
|
||||
# not reachable rdap server
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py 美しい.世界
|
||||
EXPIRATION UNKNOWN - The connection to the RDAP server failed: HTTPSConnectionPool(host='rdap.teleinfo.cn', port=443): Max retries exceeded with url: /xn--rhqv96g/domain/xn--n8jub8754b.xn--rhqv96g (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f92a5d24650>: Failed to establish a new connection: [Errno 111] Connection refused'))
|
||||
zsh: exit 3 ./check_domain_expiration_rdap.py 美しい.世界
|
||||
|
||||
# unexistant domain name
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py foundnotfound.fr
|
||||
EXPIRATION UNKNOWN - The domain foundnotfound.fr has not been found
|
||||
zsh: exit 3 ./check_domain_expiration_rdap.py foundnotfound.fr
|
||||
|
||||
# tld without rdap server
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py c.pt
|
||||
EXPIRATION UNKNOWN - The TLD pt does not have an RDAP server
|
||||
zsh: exit 3 ./check_domain_expiration_rdap.py c.pt
|
||||
|
||||
# domain with more than two labels
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py demarches.gouv.fr
|
||||
EXPIRATION OK - 113 days until domain expires | daystoexpiration=113d;@15:30;@~:15
|
||||
|
||||
# unicode domain
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py こっち.みんな
|
||||
EXPIRATION OK - 268 days until domain expires | daystoexpiration=268d;@15:30;@~:15
|
||||
|
||||
# near expiration domain
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py hostux.ninja
|
||||
EXPIRATION WARNING - 17 days until domain expires (outside range @15:30) | daystoexpiration=17d;@15:30;@~:15
|
||||
zsh: exit 1 ./check_domain_expiration_rdap.py hostux.ninja
|
||||
|
||||
# very far expiration domain
|
||||
alarig@x280 nagios-check_domain_expiration_rdap % (master *+%) ./check_domain_expiration_rdap.py swordarmor.fr
|
||||
EXPIRATION OK - 3615 days until domain expires | daystoexpiration=3615d;@15:30;@~:15
|
||||
```
|
137
check_domain_expiration_rdap.py
Executable file
137
check_domain_expiration_rdap.py
Executable file
|
@ -0,0 +1,137 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import logging
|
||||
import requests
|
||||
|
||||
import nagiosplugin
|
||||
import pandas
|
||||
import pyunycode
|
||||
import requests_cache
|
||||
|
||||
_log = logging.getLogger('nagiosplugin')
|
||||
|
||||
list2dict = []
|
||||
|
||||
session = requests_cache.CachedSession(
|
||||
'/tmp/iana_rdap_cache',
|
||||
cache_control=True
|
||||
)
|
||||
req = session.get('https://data.iana.org/rdap/dns.json')
|
||||
for list_of_list in req.json()['services']:
|
||||
k,v = list_of_list
|
||||
for x in k:
|
||||
list2dict.append({'name':x, 'url':v[0]})
|
||||
|
||||
df = pandas.DataFrame(list2dict)
|
||||
|
||||
def expiration(domain):
|
||||
domain = pyunycode.convert(domain)
|
||||
tld = domain.split('.')[-1]
|
||||
try:
|
||||
url = df[df.name == (tld)].iloc[0].url
|
||||
# no rdap on tld
|
||||
except IndexError:
|
||||
raise nagiosplugin.CheckError(
|
||||
f'The TLD {tld} does not have an RDAP server'
|
||||
)
|
||||
|
||||
req_rdap = requests.get(f'{url}domain/{domain}')
|
||||
|
||||
raw_expiration = [
|
||||
event.get('eventDate', False)
|
||||
for event in req_rdap.json().get('events', {})
|
||||
if event.get('eventAction', {}) == 'expiration'
|
||||
]
|
||||
|
||||
try:
|
||||
fecha = raw_expiration[0].split('T')[0]
|
||||
except IndexError:
|
||||
raise nagiosplugin.CheckError(
|
||||
f'The domain {domain} has not been found'
|
||||
)
|
||||
|
||||
today = datetime.datetime.now()
|
||||
delta = datetime.datetime.strptime(fecha, '%Y-%m-%d') - today
|
||||
return(delta.days)
|
||||
|
||||
|
||||
# data acquisition
|
||||
|
||||
class Expiration(nagiosplugin.Resource):
|
||||
"""Domain model: domain expiration
|
||||
|
||||
Get the expiration date from RDAP.
|
||||
The RDAP server is extracted from https://data.iana.org/rdap/dns.json which
|
||||
cached to avoid useless fetching; but the JSON from the registry RDAP isn’t
|
||||
cached because we can’t presume of the data lifetime.
|
||||
"""
|
||||
|
||||
def __init__(self, domain):
|
||||
self.domain = domain
|
||||
|
||||
def probe(self):
|
||||
try:
|
||||
days_to_expiration = expiration(self.domain)
|
||||
except requests.exceptions.ConnectionError as err:
|
||||
raise nagiosplugin.CheckError(
|
||||
f'The connection to the RDAP server failed: {err}'
|
||||
)
|
||||
|
||||
return [nagiosplugin.Metric(
|
||||
'daystoexpiration',
|
||||
days_to_expiration,
|
||||
uom='d'
|
||||
)]
|
||||
|
||||
|
||||
# data presentation
|
||||
|
||||
class ExpirationSummary(nagiosplugin.Summary):
|
||||
"""Status line conveying expiration information.
|
||||
"""
|
||||
|
||||
def __init__(self, domain):
|
||||
self.domain = domain
|
||||
|
||||
pass
|
||||
|
||||
|
||||
# runtime environment and data evaluation
|
||||
|
||||
@nagiosplugin.guarded
|
||||
def main():
|
||||
argp = argparse.ArgumentParser(description=__doc__)
|
||||
argp.add_argument(
|
||||
'-w', '--warning', metavar='int', default='30',
|
||||
help='warning expiration max days. Default=30'
|
||||
)
|
||||
argp.add_argument(
|
||||
'-c', '--critical', metavar='range', default='15',
|
||||
help='critical expiration max days. Default=15'
|
||||
)
|
||||
argp.add_argument(
|
||||
'-v', '--verbose', action='count', default=0, help='be more verbose'
|
||||
)
|
||||
argp.add_argument('domain')
|
||||
args = argp.parse_args()
|
||||
wrange = f'@{args.critical}:{args.warning}'
|
||||
crange = f'@~:{args.critical}'
|
||||
fmetric = '{value} days until domain expires'
|
||||
|
||||
check = nagiosplugin.Check(
|
||||
Expiration(args.domain),
|
||||
nagiosplugin.ScalarContext(
|
||||
'daystoexpiration',
|
||||
warning=wrange,
|
||||
critical=crange,
|
||||
fmt_metric=fmetric
|
||||
),
|
||||
ExpirationSummary(args.domain)
|
||||
)
|
||||
check.main(verbose=args.verbose)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
4
requirements.txt
Normal file
4
requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
nagiosplugin
|
||||
pandas
|
||||
pyunycode
|
||||
requests_cache
|
Loading…
Reference in a new issue