Commit f7d8281d authored by Vincent Pelletier's avatar Vincent Pelletier

client: Close http connection after each request.

Make python3 resource leak detector happy.
parent bd633a1e
0.9.10 (not released yet)
===================
* Add caucase.client.CaucaseClient.close method.
0.9.9 (2021-03-02) 0.9.9 (2021-03-02)
================== ==================
* Add AuthorityKeyIdentifier extension in CRLs. * Add AuthorityKeyIdentifier extension in CRLs.
......
...@@ -113,6 +113,18 @@ class CLICaucaseClient(object): ...@@ -113,6 +113,18 @@ class CLICaucaseClient(object):
kw.setdefault('file', self._stdout) kw.setdefault('file', self._stdout)
print(*args, **kw) print(*args, **kw)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def close(self):
"""
Tell client to close any open connection.
"""
self._client.close()
def putCSR(self, csr_path_list): def putCSR(self, csr_path_list):
""" """
--send-csr --send-csr
...@@ -610,7 +622,7 @@ def main(argv=None, stdout=sys.stdout, stderr=sys.stderr): ...@@ -610,7 +622,7 @@ def main(argv=None, stdout=sys.stdout, stderr=sys.stderr):
if args.update_user or args.mode == MODE_USER: if args.update_user or args.mode == MODE_USER:
updated |= CaucaseClient.updateCAFile(cau_url, args.user_ca_crt) updated |= CaucaseClient.updateCAFile(cau_url, args.user_ca_crt)
client = CLICaucaseClient( with CLICaucaseClient(
client=CaucaseClient( client=CaucaseClient(
ca_url={ ca_url={
MODE_SERVICE: cas_url, MODE_SERVICE: cas_url,
...@@ -621,37 +633,37 @@ def main(argv=None, stdout=sys.stdout, stderr=sys.stderr): ...@@ -621,37 +633,37 @@ def main(argv=None, stdout=sys.stdout, stderr=sys.stderr):
), ),
stdout=stdout, stdout=stdout,
stderr=stderr, stderr=stderr,
) ) as client:
ca_list = [ ca_list = [
utils.load_ca_certificate(x) utils.load_ca_certificate(x)
for x in utils.getCertList({ for x in utils.getCertList({
MODE_SERVICE: args.ca_crt, MODE_SERVICE: args.ca_crt,
MODE_USER: args.user_ca_crt, MODE_USER: args.user_ca_crt,
}[args.mode]) }[args.mode])
] ]
client.putCSR(args.send_csr) client.putCSR(args.send_csr)
client.getCSR(args.get_csr) client.getCSR(args.get_csr)
warning, error = client.getCRT(warning, error, args.get_crt, ca_list) warning, error = client.getCRT(warning, error, args.get_crt, ca_list)
error = client.revokeCRT(error, args.revoke_crt) error = client.revokeCRT(error, args.revoke_crt)
updated, error = client.renewCRT( updated, error = client.renewCRT(
crt_key_list=args.renew_crt, crt_key_list=args.renew_crt,
renewal_deadline=datetime.datetime.utcnow() + datetime.timedelta( renewal_deadline=datetime.datetime.utcnow() + datetime.timedelta(
args.threshold, args.threshold,
0, 0,
), ),
key_len=args.key_len, key_len=args.key_len,
ca_certificate_list=ca_list, ca_certificate_list=ca_list,
updated=updated, updated=updated,
error=error, error=error,
) )
client.signCSR(args.sign_csr) client.signCSR(args.sign_csr)
client.signCSRWith(args.sign_csr_with) client.signCSRWith(args.sign_csr_with)
client.rejectCSR(args.reject_csr) client.rejectCSR(args.reject_csr)
client.revokeOtherCRT(args.revoke_other_crt) client.revokeOtherCRT(args.revoke_other_crt)
client.revokeSerial(args.revoke_serial) client.revokeSerial(args.revoke_serial)
# show latest CSR list status # show latest CSR list status
if args.list_csr: if args.list_csr:
client.listCSR(args.mode) client.listCSR(args.mode)
# update our CRL after all revocations we were requested # update our CRL after all revocations we were requested
updated |= CaucaseClient.updateCRLFile(cas_url, args.crl, [ updated |= CaucaseClient.updateCRLFile(cas_url, args.crl, [
utils.load_ca_certificate(x) utils.load_ca_certificate(x)
...@@ -695,17 +707,16 @@ def probe(argv=None): ...@@ -695,17 +707,16 @@ def probe(argv=None):
) )
ca_url, = parser.parse_args(argv).ca_url ca_url, = parser.parse_args(argv).ca_url
cas_url = ca_url + '/cas' cas_url = ca_url + '/cas'
http_client = CaucaseClient( with CaucaseClient(ca_url=cas_url) as http_client:
ca_url=cas_url, http_ca_pem = http_client.getCACertificate()
) with HTTPSOnlyCaucaseClient(
http_ca_pem = http_client.getCACertificate() ca_url=cas_url,
https_ca_pem = HTTPSOnlyCaucaseClient( ca_crt_pem_list=[http_ca_pem],
ca_url=cas_url, ) as https_client:
ca_crt_pem_list=[http_ca_pem], https_ca_pem = https_client.getCACertificate()
).getCACertificate() # Retrieve again in case there was a renewal between both calls - we do
# Retrieve again in case there was a renewal between both calls - we do # not expect 2 renewals in very short succession.
# not expect 2 renewals in very short succession. http2_ca_pem = http_client.getCACertificate()
http2_ca_pem = http_client.getCACertificate()
if https_ca_pem not in (http_ca_pem, http2_ca_pem): if https_ca_pem not in (http_ca_pem, http2_ca_pem):
raise ValueError('http and https do not serve the same caucase database') raise ValueError('http and https do not serve the same caucase database')
...@@ -837,6 +848,7 @@ def updater(argv=None, until=utils.until): ...@@ -837,6 +848,7 @@ def updater(argv=None, until=utils.until):
'Will be maintained up-to-date.' 'Will be maintained up-to-date.'
) )
args = parser.parse_args(argv) args = parser.parse_args(argv)
client = None
try: try:
cas_url = args.ca_url + '/cas' cas_url = args.ca_url + '/cas'
ca_url = { ca_url = {
...@@ -892,6 +904,7 @@ def updater(argv=None, until=utils.until): ...@@ -892,6 +904,7 @@ def updater(argv=None, until=utils.until):
cas_url, cas_url,
args.cas_ca, args.cas_ca,
): ):
client.close()
client = RetryingCaucaseClient( client = RetryingCaucaseClient(
ca_url=ca_url, ca_url=ca_url,
ca_crt_pem_list=utils.getCertList(args.cas_ca) ca_crt_pem_list=utils.getCertList(args.cas_ca)
...@@ -962,6 +975,9 @@ def updater(argv=None, until=utils.until): ...@@ -962,6 +975,9 @@ def updater(argv=None, until=utils.until):
# Not intercepting KeyboardInterrupt so interrupting outside of # Not intercepting KeyboardInterrupt so interrupting outside of
# interruptibleSleep shows where the script got interrupted. # interruptibleSleep shows where the script got interrupted.
pass pass
finally:
if client is not None:
client.close()
def rerequest(argv=None): def rerequest(argv=None):
""" """
......
...@@ -88,8 +88,8 @@ class CaucaseClient(object): ...@@ -88,8 +88,8 @@ class CaucaseClient(object):
""" """
loaded_ca_pem_list = utils.getCertList(ca_crt_path) loaded_ca_pem_list = utils.getCertList(ca_crt_path)
if not loaded_ca_pem_list: if not loaded_ca_pem_list:
ca_pem = cls(ca_url=url).getCACertificate() with cls(ca_url=url) as client:
utils.saveCertList(ca_crt_path, [ca_pem]) utils.saveCertList(ca_crt_path, [client.getCACertificate()])
updated = True updated = True
# Note: reloading from file instead of using ca_pem, to exercise the # Note: reloading from file instead of using ca_pem, to exercise the
# same code path as future executions, to apply the same checks. # same code path as future executions, to apply the same checks.
...@@ -102,9 +102,8 @@ class CaucaseClient(object): ...@@ -102,9 +102,8 @@ class CaucaseClient(object):
for x in loaded_ca_pem_list for x in loaded_ca_pem_list
if utils.load_ca_certificate(x).not_valid_after > now if utils.load_ca_certificate(x).not_valid_after > now
] ]
ca_pem_list.extend( with cls(ca_url=url, ca_crt_pem_list=ca_pem_list) as client:
cls(ca_url=url, ca_crt_pem_list=ca_pem_list).getCACertificateChain(), ca_pem_list.extend(client.getCACertificateChain())
)
if ca_pem_list != loaded_ca_pem_list: if ca_pem_list != loaded_ca_pem_list:
utils.saveCertList(ca_crt_path, ca_pem_list) utils.saveCertList(ca_crt_path, ca_pem_list)
updated = True updated = True
...@@ -143,8 +142,11 @@ class CaucaseClient(object): ...@@ -143,8 +142,11 @@ class CaucaseClient(object):
updated = True updated = True
else: else:
updated = len(local_crl_list) != len(local_crl_dict) updated = len(local_crl_list) != len(local_crl_dict)
server_crl_list = cls(ca_url=url).getCertificateRevocationListList() with cls(ca_url=url) as client:
for ca_key_id, crl_pem in _asCRLDict(crl_list=server_crl_list).iteritems(): server_crl_list = client.getCertificateRevocationListList()
for ca_key_id, crl_pem in _asCRLDict(
crl_pem_list=server_crl_list,
).iteritems():
updated |= local_crl_dict.pop(ca_key_id, None) != crl_pem updated |= local_crl_dict.pop(ca_key_id, None) != crl_pem
updated |= bool(local_crl_dict) updated |= bool(local_crl_dict)
if updated: if updated:
...@@ -221,6 +223,19 @@ class CaucaseClient(object): ...@@ -221,6 +223,19 @@ class CaucaseClient(object):
def _https(self, method, url, body=None, headers=None): def _https(self, method, url, body=None, headers=None):
return self._request(self._https_connection, method, url, body, headers) return self._request(self._https_connection, method, url, body, headers)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def close(self):
"""
Close any open connection.
"""
self._http_connection.close()
self._https_connection.close()
def getCertificateRevocationList(self, authority_key_identifier): def getCertificateRevocationList(self, authority_key_identifier):
""" """
[ANONYMOUS] Retrieve latest CRL for given integer authority key [ANONYMOUS] Retrieve latest CRL for given integer authority key
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment