Merge pull request 'tls-again' (#36) from tls-again into main

Reviewed-on: #36
main 5.7.0
Natalia Serrano 2025-05-28 10:53:07 +02:00
commit e20c671c1e
7 changed files with 108 additions and 25 deletions

View File

@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [5.7.0] - 2025-05-27
### Changed
- Use TLS again
## [5.6.0] - 2025-05-21
### Changed

View File

@ -1,3 +1,9 @@
ogagent (5.7.0-1) stable; urgency=medium
* Use TLS again
-- OpenGnsys developers <info@opengnsys.es> Wed, 21 May 2025 17:39:13 +0200
ogagent (5.6.0-1) stable; urgency=medium
* Execute 'launch_browser' rather than 'browser'

View File

@ -1 +1 @@
5.6.0
5.7.0

View File

@ -20,9 +20,11 @@ log=DEBUG
imgname=
# TLS
ca=C:\Program Files (x86)\OGagent\ca.crt
crt=C:\Program Files (x86)\OGagent\ogagent.crt
key=C:\Program Files (x86)\OGagent\ogagent.key
# The agent will look for these files in /opt/opengnsys/etc, /usr/share/OGAgent,
# windows "Program Files (x86)" and the current working directory
ca=ca.crt
crt=ogagent.crt
key=ogagent.key
# Module specific

View File

@ -45,6 +45,7 @@ from .log import logger
from .utils import exceptionToMessage
TIMEOUT = 5 # Connection timout, in seconds
VERIFY_TLS=True
class RESTError(Exception):
@ -95,6 +96,7 @@ class REST(object):
@param url The url of the REST API Base. The trailing '/' can be included or omitted, as desired.
"""
self.endpoint = url
global VERIFY_TLS
if self.endpoint[-1] != '/':
self.endpoint += '/'
@ -109,21 +111,47 @@ class REST(object):
logger.debug ('TLS not available: python requests library is old')
self.use_tls = url.startswith ('https')
#if self.use_tls:
# if not ca_file or not crt_file or not key_file:
# raise Exception ('missing TLS parameters in REST constructor')
#
# errs = 0
# for f in [ca_file, crt_file, key_file]:
# if not os.path.exists (f):
# logger.error (f'{f}: No such file or directory')
# errs += 1
# if errs:
# raise Exception ('TLS files not found')
#
#self.ca_file = ca_file
#self.crt_file = crt_file
#self.key_file = key_file
if self.use_tls:
if not ca_file or not crt_file or not key_file:
raise Exception ('missing TLS parameters in REST constructor')
certs_dirs = ['/opt/opengnsys/etc', '/usr/share/OGAgent']
pf = os.environ.get ('PROGRAMFILES(X86)')
if pf: certs_dirs.append (os.path.join (pf, 'OGAgent'))
certs_dirs.append (os.getcwd())
certs_dir = None
for sp in certs_dirs:
if os.path.exists (sp):
logger.debug (f'Looking for TLS files in ({sp})')
certs_dir = sp
break
if not certs_dir:
logger.debug ("Don't know where to look for TLS files")
errs = 1
else:
errs = 0
for f in [ca_file, crt_file, key_file]:
if os.path.exists (f'{certs_dir}/{f}'):
logger.debug (f'{certs_dir}/{f}: found')
else:
logger.error (f'{f}: No such file or directory')
errs += 1
if errs:
self.verify_tls = False
logger.debug ('HTTP client: using insecure TLS to talk to ogcore due to missing files')
else:
self.ca_file = f'{certs_dir}/{ca_file}'
self.crt_file = f'{certs_dir}/{crt_file}'
self.key_file = f'{certs_dir}/{key_file}'
self.verify_tls = VERIFY_TLS
if self.verify_tls:
logger.debug ('HTTP client: using TLS to talk to ogcore')
else:
logger.debug ('HTTP client: using insecure TLS as requested to talk to ogcore')
else:
logger.debug ('HTTP client: not using TLS to talk to ogcore')
# Disable logging requests messages except for errors, ...
logging.getLogger("requests").setLevel(logging.CRITICAL)
@ -156,7 +184,11 @@ class REST(object):
# Old requests version does not support verify, but it do not checks ssl certificate by default
if self.newerRequestLib:
if self.use_tls:
r = requests.get(url, verify=False, timeout=TIMEOUT)
if self.verify_tls:
r = requests.get(url, cert=(self.crt_file, self.key_file), verify=self.ca_file, timeout=TIMEOUT)
else:
logger.warning ('using insecure TLS for GET')
r = requests.get(url, verify=False, timeout=TIMEOUT)
else:
r = requests.get(url, timeout=TIMEOUT)
else:
@ -165,7 +197,11 @@ class REST(object):
logger.debug('Requesting using POST {}, data: {}'.format(url, data))
if self.newerRequestLib:
if self.use_tls:
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=False, timeout=TIMEOUT)
if self.verify_tls:
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, cert=(self.crt_file, self.key_file), verify=self.ca_file, timeout=TIMEOUT)
else:
logger.warning ('using insecure TLS for POST')
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=False, timeout=TIMEOUT)
else:
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, timeout=TIMEOUT)
else:

View File

@ -43,6 +43,7 @@ from .utils import exceptionToMessage
from .certs import createSelfSignedCert
from .log import logger
VERIFY_TLS=True
class HTTPServerHandler(BaseHTTPRequestHandler):
service = None
@ -153,15 +154,46 @@ class HTTPThreadingServer(ThreadingMixIn, HTTPServer):
class HTTPServerThread(threading.Thread):
def __init__(self, address, service):
super(self.__class__, self).__init__()
global VERIFY_TLS
HTTPServerHandler.service = service # Keep tracking of service so we can intercact with it
self.certFile = createSelfSignedCert()
self.server = HTTPThreadingServer(address, HTTPServerHandler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=self.certFile)
pf = os.environ.get ('PROGRAMFILES(X86)')
if pf: pf = os.path.join (pf, 'OGAgent')
if os.path.exists ('/opt/opengnsys/etc/ogagent.crt') and os.path.exists ('/opt/opengnsys/etc/ogagent.key') and os.path.exists ('/opt/opengnsys/etc/ca.crt'):
logger.debug ('HTTP server: using certificate/CA from /opt/opengnsys/etc')
context.load_cert_chain (certfile='/opt/opengnsys/etc/ogagent.crt', keyfile='/opt/opengnsys/etc/ogagent.key')
context.load_verify_locations (cafile='/opt/opengnsys/etc/ca.crt')
elif os.path.exists (os.path.join (pf, 'ogagent.crt')) and os.path.exists (os.path.join (pf, 'ogagent.key')) and os.path.exists (os.path.join (pf, 'ca.crt')):
logger.debug (f'HTTP server: using certificate/CA from the installation path ({pf})')
context.load_cert_chain (certfile=os.path.join (pf, 'ogagent.crt'), keyfile=os.path.join (pf, 'ogagent.key'))
context.load_verify_locations (cafile=os.path.join (pf, 'ca.crt'))
elif os.path.exists ('./ogagent.crt') and os.path.exists ('./ogagent.key') and os.path.exists ('./ca.crt'):
cwd = os.getcwd()
logger.debug (f'HTTP server: using certificate/CA from the current working directory ({cwd})')
context.load_cert_chain (certfile=f'{cwd}/ogagent.crt', keyfile=f'{cwd}/ogagent.key')
context.load_verify_locations (cafile=f'{cwd}/ca.crt')
else:
logger.debug ('HTTP server: using a self-signed certificate')
self.certFile = createSelfSignedCert()
context.load_cert_chain (certfile=self.certFile)
VERIFY_TLS = False
if VERIFY_TLS:
context.verify_mode = ssl.CERT_REQUIRED
context.verify_flags &= ssl.VERIFY_X509_STRICT
else:
context.verify_mode = ssl.CERT_NONE
context.verify_flags &= ~ssl.VERIFY_X509_STRICT
s = context.cert_store_stats()
if 'x509_ca' in s: logger.debug (f'HTTP server: {s['x509_ca']} CAs loaded')
if 'x509' in s: logger.debug (f'HTTP server: {s['x509']} certs loaded')
self.server.socket = context.wrap_socket(self.server.socket, server_side=True)
logger.debug('Initialized HTTPS Server thread on {}'.format(address))
def getServerUrl(self):

View File

@ -33,7 +33,8 @@
import os
import re
import time
import dbus
try: import dbus ## don't fail on windows (the worker will later refuse to load anyway)
except: pass
import random
import subprocess
import threading