parent
e920a3c681
commit
15d4f2cf6b
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.6.0
|
||||
5.7.0
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -96,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 += '/'
|
||||
|
@ -114,18 +115,43 @@ class REST(object):
|
|||
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')
|
||||
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
|
||||
|
||||
self.ca_file = ca_file
|
||||
self.crt_file = crt_file
|
||||
self.key_file = key_file
|
||||
self.verify_tls = VERIFY_TLS
|
||||
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)
|
||||
|
@ -159,12 +185,10 @@ class REST(object):
|
|||
if self.newerRequestLib:
|
||||
if self.use_tls:
|
||||
if self.verify_tls:
|
||||
logger.debug ('nati: using TLS for GET')
|
||||
v = self.ca_file
|
||||
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')
|
||||
v = False
|
||||
r = requests.get(url, cert=(self.crt_file, self.key_file), verify=v, timeout=TIMEOUT)
|
||||
r = requests.get(url, verify=False, timeout=TIMEOUT)
|
||||
else:
|
||||
r = requests.get(url, timeout=TIMEOUT)
|
||||
else:
|
||||
|
@ -174,12 +198,10 @@ class REST(object):
|
|||
if self.newerRequestLib:
|
||||
if self.use_tls:
|
||||
if self.verify_tls:
|
||||
logger.debug ('nati: using TLS for POST')
|
||||
v = self.ca_file
|
||||
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')
|
||||
v = False
|
||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, cert=(self.crt_file, self.key_file), verify=v, timeout=TIMEOUT)
|
||||
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:
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from tempfile import gettempdir
|
||||
from os.path import exists, join
|
||||
|
||||
CERTFILE = 'OGAgent.pem'
|
||||
|
||||
|
||||
def createSelfSignedCert(force=False):
|
||||
|
||||
certFile = join(gettempdir(), CERTFILE)
|
||||
|
||||
if exists(certFile) and not force:
|
||||
return certFile
|
||||
|
||||
certData = '''-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCb50K3mIznNklz
|
||||
yVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxbfxHbeRnoYTWV2nKk4+tHqmvz
|
||||
ujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqCfItWgL5pJopDpNHFul9Rn3ds
|
||||
PMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPmVLdF4uJ3Tuz8TSy2gWLs5aSr
|
||||
5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuDUGNBvBQFac1G7qUcMReeu8Zr
|
||||
DUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDqDUK1Oqs9X35yOQfDOAFYHiix
|
||||
PX0IsXOZAgMBAAECggEBAJi3000RrIUZUp6Ph0gzPMuCjDEEwWiQA7CPNX1gpb8O
|
||||
dp0WhkDhUroWIaICYPSXtOwUTtVjRqivMoxPy1Thg3EIoGC/rdeSdlXRHMEGicwJ
|
||||
yVyalFnatr5Xzg5wkxVh4XMd0zeDt7e3JD7s0QLo5lm1CEzd77qz6lhzFic5/1KX
|
||||
bzdULtTlq60dazg2hEbcS4OmM1UMCtRVDAsOIUIZPL0M9j1C1d1iEdYnh2xshKeG
|
||||
/GOfo95xsgdMlGjtv3hUT5ryKVoEsu+36rGb4VfhPfUvvoVbRx5QZpW+QvxaYh5E
|
||||
Fi0JEROozFwG31Y++8El7J3yQko8cFBa1lYYUwwpNAECgYEAykT+GiM2YxJ4uVF1
|
||||
OoKiE9BD53i0IG5j87lGPnWqzEwYBwnqjEKDTou+uzMGz3MDV56UEFNho7wUWh28
|
||||
LpEkjJB9QgbsugjxIBr4JoL/rYk036e/6+U8I95lvYWrzb+rBMIkRDYI7kbQD/mQ
|
||||
piYUpuCkTymNAu2RisK6bBzJslkCgYEAxVE23OQvkCeOV8hJNPZGpJ1mDS+TiOow
|
||||
oOScMZmZpail181eYbAfMsCr7ri812lSj98NvA2GNVLpddil6LtS1cQ5p36lFBtV
|
||||
xQUMZiFz4qVbEak+izL+vPaev/mXXsOcibAIQ+qI/0txFpNhJjpaaSy6vRCBYFmc
|
||||
8pgSoBnBI0ECgYAUKCn2atnpp5aWSTLYgNosBU4vDA1PShD14dnJMaqyr0aZtPhF
|
||||
v/8b3btFJoGgPMLxgWEZ+2U4ju6sSFhPf7FXvLJu2QfQRkHZRDbEh7t5DLpTK4Fp
|
||||
va9vl6Ml7uM/HsGpOLuqfIQJUs87OFCc7iCSvMJDDU37I7ekT2GKkpfbCQKBgBrE
|
||||
0NeY0WcSJrp7/oqD2sOcYurpCG/rrZs2SIZmGzUhMxaa0vIXzbO59dlWELB8pmnE
|
||||
Tf20K//x9qA5OxDe0PcVPukdQlH+/1zSOYNliG44FqnHtyd1TJ/gKVtMBiAiE4uO
|
||||
aSClod5Yosf4SJbCFd/s5Iyfv52NqsAyp1w3Aj/BAoGAVCnEiGUfyHlIR+UH4zZW
|
||||
GXJMeqdZLfcEIszMxLePkml4gUQhoq9oIs/Kw+L1DDxUwzkXN4BNTlFbOSu9gzK1
|
||||
dhuIUGfS6RPL88U+ivC3A0y2jT43oUMqe3hiRt360UQ1GXzp2dMnR9odSRB1wHoO
|
||||
IOjEBZ8341/c9ZHc5PCGAG8=
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID7zCCAtegAwIBAgIJAIrEIthCfxUCMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
|
||||
VQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMREwDwYDVQQHDAhBbGNvcmNvbjEMMAoG
|
||||
A1UECgwDVURTMQ4wDAYDVQQLDAVBY3RvcjESMBAGA1UEAwwJVURTIEFjdG9yMSgw
|
||||
JgYJKoZIhvcNAQkBFhlzdXBwb3J0QHVkc2VudGVycHJpc2UuY29tMB4XDTE0MTAy
|
||||
NjIzNDEyNFoXDTI0MTAyMzIzNDEyNFowgY0xCzAJBgNVBAYTAkVTMQ8wDQYDVQQI
|
||||
DAZNYWRyaWQxETAPBgNVBAcMCEFsY29yY29uMQwwCgYDVQQKDANVRFMxDjAMBgNV
|
||||
BAsMBUFjdG9yMRIwEAYDVQQDDAlVRFMgQWN0b3IxKDAmBgkqhkiG9w0BCQEWGXN1
|
||||
cHBvcnRAdWRzZW50ZXJwcmlzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQCb50K3mIznNklzyVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxb
|
||||
fxHbeRnoYTWV2nKk4+tHqmvzujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqC
|
||||
fItWgL5pJopDpNHFul9Rn3dsPMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPm
|
||||
VLdF4uJ3Tuz8TSy2gWLs5aSr5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuD
|
||||
UGNBvBQFac1G7qUcMReeu8ZrDUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDq
|
||||
DUK1Oqs9X35yOQfDOAFYHiixPX0IsXOZAgMBAAGjUDBOMB0GA1UdDgQWBBRShS90
|
||||
5lJTNvYPIEqP3GxWwG5iiDAfBgNVHSMEGDAWgBRShS905lJTNvYPIEqP3GxWwG5i
|
||||
iDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAU0Sp4gXhQmRVzq+7+
|
||||
vRFUkQuPj4Ga/d9r5Wrbg3hck3+5pwe9/7APoq0P/M0DBhQpiJKjrD6ydUevC+Y/
|
||||
43ZOJPhMlNw0o6TdQxOkX6FDwQanLLs7sfvJvqtVzYn3nuRFKT3dvl7Zg44QMw2M
|
||||
ay42q59fAcpB4LaDx/i7gOYSS5eca3lYW7j7YSr/+ozXK2KlgUkuCUHN95lOq+dF
|
||||
trmV9mjzM4CNPZqKSE7kpHRywgrXGPCO000NvEGSYf82AtgRSFKiU8NWLQSEPdcB
|
||||
k//2dsQZw2cRZ8DrC2B6Tb3M+3+CA6wVyqfqZh1SZva3LfGvq/C+u+ItguzPqNpI
|
||||
xtvM
|
||||
-----END CERTIFICATE-----'''
|
||||
with open(certFile, "wt") as f:
|
||||
f.write(certData)
|
||||
|
||||
return certFile
|
|
@ -40,6 +40,7 @@ from six.moves.BaseHTTPServer import HTTPServer # @UnresolvedImport
|
|||
from six.moves.urllib.parse import unquote # @UnresolvedImport
|
||||
|
||||
from .utils import exceptionToMessage
|
||||
from .certs import createSelfSignedCert
|
||||
from .log import logger
|
||||
|
||||
VERIFY_TLS=True
|
||||
|
@ -153,13 +154,34 @@ 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.server = HTTPThreadingServer(address, HTTPServerHandler)
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
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')
|
||||
|
||||
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
|
||||
|
@ -168,8 +190,8 @@ class HTTPServerThread(threading.Thread):
|
|||
context.verify_flags &= ~ssl.VERIFY_X509_STRICT
|
||||
|
||||
s = context.cert_store_stats()
|
||||
if 'x509_ca' in s: logger.debug (f'{s['x509_ca']} CAs loaded')
|
||||
if 'x509' in s: logger.debug (f'{s['x509']} certs loaded')
|
||||
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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue