Compare commits
45 Commits
Author | SHA1 | Date |
---|---|---|
|
950b163602 | |
|
72b832d654 | |
|
65c07fea1e | |
|
9cf7ec5a56 | |
|
60bab01556 | |
|
b4c86bb175 | |
|
2f5ac81235 | |
|
b1a67b1191 | |
|
7be441ca99 | |
|
bb856e5b63 | |
|
22f7ce0bb9 | |
|
250de7a070 | |
|
2feff97a91 | |
|
10349a35f1 | |
|
a84bed3439 | |
|
05d2375e21 | |
|
8fea0737f2 | |
|
7128f12049 | |
|
734df2749b | |
|
946020d728 | |
|
1a38999aef | |
|
2dd678737b | |
|
165746a94b | |
|
3553aee8ce | |
|
b77b42ec22 | |
|
e20c671c1e | |
|
15d4f2cf6b | |
|
e920a3c681 | |
|
921706e9f0 | |
|
63944cef0e | |
|
3ae4471d5d | |
|
d1ce3b5cc9 | |
|
1fa2a4f0bb | |
|
ac9ab7e8f5 | |
|
05e0b83b91 | |
|
9d0589547f | |
|
ccb6cdfa54 | |
|
0d375e9aae | |
|
60cc47dd30 | |
|
acc9c2ed07 | |
|
17ec13d77c | |
|
dd445cee65 | |
|
d231816c0f | |
|
0099a05921 | |
|
db9f4992be |
86
CHANGELOG.md
86
CHANGELOG.md
|
@ -6,6 +6,92 @@ 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).
|
||||
|
||||
## [6.1.1] - 2025-06-26
|
||||
|
||||
### Changed
|
||||
|
||||
- Write output of launch_browser into a file
|
||||
|
||||
## [6.1.0] - 2025-06-25
|
||||
|
||||
### Added
|
||||
|
||||
- Added ModificarImagenGit
|
||||
|
||||
## [6.0.0] - 2025-06-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed the names of some endpoints for consistency between oglive and OS
|
||||
- Changed label in the windows installer
|
||||
|
||||
## [5.9.0] - 2025-06-16
|
||||
|
||||
### Added
|
||||
|
||||
- Added changes for oggit
|
||||
|
||||
## [5.8.1] - 2025-06-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improve fail condition when no network is detected
|
||||
|
||||
## [5.8.0] - 2025-06-12
|
||||
|
||||
### Changed
|
||||
|
||||
- Agents aren't being sent any signals on user logout. On the server side, assume that client disconnection == logout
|
||||
|
||||
## [5.7.1] - 2025-06-05
|
||||
|
||||
### Fixed
|
||||
|
||||
- Correcly handle UNIX signals in the user instance of the agent
|
||||
|
||||
## [5.7.0] - 2025-05-27
|
||||
|
||||
### Changed
|
||||
|
||||
- Use TLS again
|
||||
|
||||
## [5.6.0] - 2025-05-21
|
||||
|
||||
### Changed
|
||||
|
||||
- Launch QT6 browser
|
||||
- Change URLs using dbus
|
||||
|
||||
## [5.5.0] - 2025-05-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Revert to the QT4 browser again
|
||||
|
||||
## [5.4.0] - 2025-05-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Disabled TLS on request
|
||||
|
||||
## [5.3.0] - 2025-05-16
|
||||
|
||||
### Changed
|
||||
|
||||
- Execute 'launch_browser' rather than 'browser'
|
||||
|
||||
## [5.2.0] - 2025-05-14
|
||||
|
||||
### Added
|
||||
|
||||
- Log duration of user sessions
|
||||
|
||||
## [5.1.1] - 2025-05-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed URL for notifying stop to ogcore
|
||||
|
||||
## [5.1.0] - 2025-05-06
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,3 +1,95 @@
|
|||
ogagent (6.1.1-1) stable; urgency=medium
|
||||
|
||||
* Write output of launch_browser into a file
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 26 Jun 2025 12:45:19 +0200
|
||||
|
||||
ogagent (6.1.0-1) stable; urgency=medium
|
||||
|
||||
* Add ModificarImagenGit
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 25 Jun 2025 10:26:42 +0200
|
||||
|
||||
ogagent (6.0.0-1) stable; urgency=medium
|
||||
|
||||
* Unify API methods for poweroff, reboot and run script
|
||||
* Change label in the windows installer
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Fri, 20 Jun 2025 10:03:15 +0200
|
||||
|
||||
ogagent (5.9.0-1) stable; urgency=medium
|
||||
|
||||
* Add changes for oggit
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 16 Jun 2025 11:12:55 +0200
|
||||
|
||||
ogagent (5.8.1-1) stable; urgency=medium
|
||||
|
||||
* Improve fail condition when no network is detected
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Fri, 13 Jun 2025 10:01:43 +0200
|
||||
|
||||
ogagent (5.8.0-1) stable; urgency=medium
|
||||
|
||||
* When client disconnect, assume that the user logged out
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 12 Jun 2025 15:30:50 +0200
|
||||
|
||||
ogagent (5.7.1-1) stable; urgency=medium
|
||||
|
||||
* Correctly handle UNIX signals
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 05 Jun 2025 12:07:30 +0200
|
||||
|
||||
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'
|
||||
* Change URLs using dbus
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 21 May 2025 15:06:52 +0200
|
||||
|
||||
ogagent (5.5.0-1) stable; urgency=medium
|
||||
|
||||
* Return to the QT4 browser again
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 19 May 2025 10:57:37 +0200
|
||||
|
||||
ogagent (5.4.0-1) stable; urgency=medium
|
||||
|
||||
* Disable TLS on request
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 19 May 2025 09:46:42 +0200
|
||||
|
||||
ogagent (5.3.0-1) stable; urgency=medium
|
||||
|
||||
* Execute 'launch_browser' rather than 'browser'
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 14 May 2025 10:50:15 +0200
|
||||
|
||||
ogagent (5.2.0-1) stable; urgency=medium
|
||||
|
||||
* Log length of user sessions
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 12 May 2025 11:38:27 +0200
|
||||
|
||||
ogagent (5.1.1-1) stable; urgency=medium
|
||||
|
||||
* Fix URL for notifying stop to ogcore
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 06 May 2025 13:31:48 +0200
|
||||
|
||||
ogagent (5.1.0-1) stable; urgency=medium
|
||||
|
||||
* Include powershell helper script for logging out of windows
|
||||
|
||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 06 May 2025 13:30:59 +0200
|
||||
|
||||
ogagent (5.0.0-1) stable; urgency=medium
|
||||
|
||||
* Use TLS
|
||||
|
|
|
@ -35,6 +35,8 @@ import json
|
|||
import sys
|
||||
import time
|
||||
import os
|
||||
import socket
|
||||
import signal
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from about_dialog_ui import Ui_OGAAboutDialog
|
||||
|
@ -328,6 +330,29 @@ if __name__ == '__main__':
|
|||
trayIcon.quit()
|
||||
sys.exit(1)
|
||||
|
||||
## begin SIGTERM handling
|
||||
signal_socket = socket.socketpair()
|
||||
signal_socket[0].setblocking(False)
|
||||
signal_socket[1].setblocking(False)
|
||||
signal.set_wakeup_fd(signal_socket[0].fileno())
|
||||
|
||||
def signal_handler(signum, frame):
|
||||
#print (f"Received signal {signum}")
|
||||
pass
|
||||
|
||||
def qt_signal_handler():
|
||||
data = signal_socket[1].recv(1)
|
||||
#print(f"Signal ({data}) received via socket, shutting down gracefully...")
|
||||
if trayIcon:
|
||||
trayIcon.quit()
|
||||
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
notifier = QtCore.QSocketNotifier(signal_socket[1].fileno(), QtCore.QSocketNotifier.Type.Read)
|
||||
notifier.activated.connect(qt_signal_handler)
|
||||
## end SIGTERM handling
|
||||
|
||||
app.aboutToQuit.connect(trayIcon.cleanup)
|
||||
trayIcon.show()
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.0.0
|
||||
6.1.1
|
||||
|
|
|
@ -7,7 +7,7 @@ port=8000
|
|||
#path=test_modules/server,more_modules/server
|
||||
|
||||
# Remote OpenGnsys Service
|
||||
remote=https://192.168.2.1/opengnsys/rest
|
||||
remote=https://192.168.2.1:8443/opengnsys/rest
|
||||
# Alternate OpenGnsys Service (comment out to enable this option)
|
||||
#altremote=https://10.0.2.2/opengnsys/rest
|
||||
|
||||
|
@ -17,10 +17,14 @@ level=full
|
|||
# Log Level, if omitted, will be set to INFO
|
||||
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
|
||||
|
|
|
@ -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 += '/'
|
||||
|
@ -113,17 +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
|
||||
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, cert=(self.crt_file, self.key_file), verify=self.ca_file, 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'}, cert=(self.crt_file, self.key_file), verify=self.ca_file, 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:
|
||||
|
@ -173,7 +209,7 @@ class REST(object):
|
|||
|
||||
r.raise_for_status()
|
||||
ct = r.headers['Content-Type']
|
||||
if 'application/json' != ct:
|
||||
if len(ct) < 16 or 'application/json' != ct[0:16]:
|
||||
raise Exception (f'response content-type is not "application/json" but "{ct}"')
|
||||
r = json.loads(r.content) # Using instead of r.json() to make compatible with old requests lib versions
|
||||
except requests.exceptions.RequestException as e:
|
||||
|
|
|
@ -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 pf and 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):
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"""
|
||||
|
||||
|
||||
import os
|
||||
import json
|
||||
import queue
|
||||
import socket
|
||||
|
@ -164,6 +165,9 @@ class ClientProcessor(threading.Thread):
|
|||
logger.debug('Got invalid message from request: {}, state: {}'.format(buf, state))
|
||||
except socket.error as e:
|
||||
# If no data is present, no problem at all, pass to check messages
|
||||
if '[WinError 10054]' in str(e):
|
||||
## windows: client disconnected
|
||||
self.running = False
|
||||
pass
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
|
@ -193,6 +197,8 @@ class ClientProcessor(threading.Thread):
|
|||
logger.error('Invalid message in queue: {}'.format(e))
|
||||
|
||||
logger.debug('Client processor stopped')
|
||||
if os.path.exists ('/windows/temp'): open ('/windows/temp/ogagentuser_died', 'w').close()
|
||||
else: open ( '/tmp/ogagentuser_died', 'w').close()
|
||||
try:
|
||||
self.clientSocket.close()
|
||||
except Exception:
|
||||
|
|
|
@ -39,6 +39,7 @@ from opengnsys.log import logger
|
|||
|
||||
from opengnsys.linux.daemon import Daemon
|
||||
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import json
|
||||
|
@ -71,6 +72,13 @@ class OGAgentSvc(Daemon, CommonService):
|
|||
# example
|
||||
try:
|
||||
while self.isAlive:
|
||||
client_died=False
|
||||
if os.path.exists ('/tmp/ogagentuser_died'):
|
||||
os.unlink ('/tmp/ogagentuser_died')
|
||||
client_died=True
|
||||
if client_died:
|
||||
self.notifyLogout (b'')
|
||||
|
||||
# In milliseconds, will break
|
||||
self.doWait(1000)
|
||||
except (KeyboardInterrupt, SystemExit) as e:
|
||||
|
|
|
@ -112,7 +112,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
"iph": self.interface.ip,
|
||||
"timestamp": int (time.time()),
|
||||
}
|
||||
logger.debug (f'about to send ping ({body})')
|
||||
#logger.debug (f'about to send ping ({body})')
|
||||
self.REST.sendMessage ('clients/status/webhook', body)
|
||||
|
||||
def onActivation(self):
|
||||
|
@ -147,7 +147,11 @@ class OpenGnSysWorker(ServerWorker):
|
|||
for t in range(0, 300):
|
||||
try:
|
||||
# Get the first network interface
|
||||
self.interface = list(operations.getNetworkInfo())[0]
|
||||
nets = list (operations.getNetworkInfo())
|
||||
if 0 == len (nets):
|
||||
logger.error ('No network interfaces found')
|
||||
raise Exception ('No network interfaces found')
|
||||
self.interface = nets[0]
|
||||
except Exception as e:
|
||||
# Wait 1 sec. and retry
|
||||
logger.warn (e)
|
||||
|
@ -213,6 +217,10 @@ class OpenGnSysWorker(ServerWorker):
|
|||
"""
|
||||
Sends OGAgent stopping notification to OpenGnsys server
|
||||
"""
|
||||
now = time.time()
|
||||
for elem in self.user:
|
||||
sess_len = now - elem['login_ts']
|
||||
logger.debug ('Session of logged in user {} took {} seconds'.format (elem['username'], int (sess_len)))
|
||||
logger.debug('onDeactivation')
|
||||
self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'ostype': operations.os_type, 'osversion': operations.os_version})
|
||||
|
@ -223,7 +231,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
"""
|
||||
user, language, self.session_type = tuple(data.split(','))
|
||||
logger.debug('Received login for {0} using {2} with language {1}'.format(user, language, self.session_type))
|
||||
self.user.append(user)
|
||||
self.user.append ({'username': user, 'login_ts': time.time() })
|
||||
self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language,
|
||||
'session': self.session_type,
|
||||
'ostype': operations.os_type, 'osversion': operations.os_version})
|
||||
|
@ -232,7 +240,11 @@ class OpenGnSysWorker(ServerWorker):
|
|||
"""
|
||||
Sends session logout notification to OpenGnsys server
|
||||
"""
|
||||
logger.debug('Received logout for {}'.format(user))
|
||||
sess_len = 0
|
||||
for elem in self.user:
|
||||
if user != elem['username']: continue
|
||||
sess_len = time.time() - elem['login_ts']
|
||||
logger.debug ('Received logout for {}, session length {} seconds'.format (user, int (sess_len)))
|
||||
try:
|
||||
self.user.pop()
|
||||
except IndexError:
|
||||
|
@ -288,7 +300,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
if get_params.get('detail', 'false') == 'true':
|
||||
res.update({'agent_version': VERSION, 'os_version': operations.os_version, 'sys_load': os.getloadavg()})
|
||||
if res['loggedin']:
|
||||
res.update({'sessions': len(self.user), 'current_user': self.user[-1]})
|
||||
res.update({'sessions': len(self.user), 'current_user': self.user[-1]['username']})
|
||||
except KeyError:
|
||||
# Unknown operating system
|
||||
res = {'status': 'UNK'}
|
||||
|
@ -296,7 +308,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
|
||||
@execution_level('halt')
|
||||
@check_secret
|
||||
def process_reboot(self, path, get_params, post_params, server):
|
||||
def process_Reiniciar(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Launches a system reboot operation
|
||||
:param path:
|
||||
|
@ -315,7 +327,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
|
||||
@execution_level('halt')
|
||||
@check_secret
|
||||
def process_poweroff(self, path, get_params, post_params, server):
|
||||
def process_Apagar(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Launches a system power off operation
|
||||
:param path:
|
||||
|
@ -335,7 +347,7 @@ class OpenGnSysWorker(ServerWorker):
|
|||
|
||||
@execution_level('full')
|
||||
@check_secret
|
||||
def process_script(self, path, get_params, post_params, server):
|
||||
def process_EjecutarScript(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Processes an script execution (script should be encoded in base64)
|
||||
:param path:
|
||||
|
@ -346,7 +358,14 @@ class OpenGnSysWorker(ServerWorker):
|
|||
"""
|
||||
logger.debug('Processing script request')
|
||||
# Decoding script
|
||||
script = urllib.parse.unquote(base64.b64decode(post_params.get('script')).decode('utf-8'))
|
||||
param_script = post_params.get('script')
|
||||
if not param_script:
|
||||
return {'op': 'error', 'err': 'Required parameter "script" is missing or empty'}
|
||||
try:
|
||||
b64decoded = base64.b64decode (param_script)
|
||||
except Exception as e:
|
||||
return {'op': 'error', 'err': f'Failed to decode base64: {e}'}
|
||||
script = urllib.parse.unquote (b64decoded.decode ('utf-8'))
|
||||
logger.debug('received script "{}"'.format(script))
|
||||
|
||||
if post_params.get('client', 'false') == 'false':
|
||||
|
|
|
@ -95,8 +95,8 @@ class ogAdmClientWorker (ogLiveWorker):
|
|||
Sends OGAgent stopping notification to OpenGnsys server
|
||||
"""
|
||||
logger.debug ('onDeactivation')
|
||||
self.REST.sendMessage ('ogAdmClient/stopped', {'mac': self.mac, 'ip': self.IPlocal, 'idcentro': self.idcentro, 'idaula': self.idaula,
|
||||
'idordenador': self.idordenador, 'nombreordenador': self.nombreordenador})
|
||||
self.REST.sendMessage ('ogagent/stopped', {'mac': self.mac, 'ip': self.IPlocal, 'idcentro': self.idcentro, 'idaula': self.idaula,
|
||||
'idordenador': self.idordenador, 'nombreordenador': self.nombreordenador})
|
||||
|
||||
|
||||
|
||||
|
@ -360,6 +360,106 @@ class ogAdmClientWorker (ogLiveWorker):
|
|||
}
|
||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||
|
||||
def do_CrearImagenGit (self, post_params):
|
||||
for k in ['dsk', 'par', 'nci', 'ipr', 'nfn', 'ids']:
|
||||
if k not in post_params:
|
||||
logger.error (f'required parameter ({k}) not in POST params')
|
||||
return {}
|
||||
|
||||
dsk = post_params['dsk'] ## Disco
|
||||
par = post_params['par'] ## Número de partición
|
||||
nci = post_params['nci'] ## Nombre canónico de la imagen
|
||||
ipr = post_params['ipr'] ## Ip del repositorio
|
||||
nfn = post_params['nfn']
|
||||
ids = post_params['ids']
|
||||
tag = post_params['tag'] ## Tag a crear en git una vez hecho el commit
|
||||
|
||||
self.muestraMensaje (7)
|
||||
|
||||
try:
|
||||
res = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') ## Crea inventario Software previamente
|
||||
except:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
return {}
|
||||
|
||||
if res['contents']:
|
||||
self.muestraMensaje (2)
|
||||
inv_sft = res['contents']
|
||||
try:
|
||||
self.interfaceAdmin (nfn, [dsk, par, nci, ipr, tag])
|
||||
self.muestraMensaje (9)
|
||||
herror = 0
|
||||
except:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
self.muestraMensaje (10)
|
||||
herror = 1
|
||||
else:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
herror = 1
|
||||
inv_sft = ''
|
||||
|
||||
self.muestraMenu()
|
||||
|
||||
cmd = {
|
||||
'nfn': 'RESPUESTA_CrearImagenGit',
|
||||
'dsk': dsk, ## Número de disco
|
||||
'par': par, ## Número de partición de donde se creó
|
||||
'ipr': ipr, ## Ip del repositorio donde se alojó
|
||||
'inv_sft': inv_sft
|
||||
}
|
||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||
|
||||
|
||||
def do_ModificarImagenGit (self, post_params):
|
||||
for k in ['dsk', 'par', 'nci', 'ipr', 'nfn', 'ids', 'msg']:
|
||||
if k not in post_params:
|
||||
logger.error (f'required parameter ({k}) not in POST params')
|
||||
return {}
|
||||
|
||||
dsk = post_params['dsk'] ## Disco
|
||||
par = post_params['par'] ## Número de partición
|
||||
nci = post_params['nci'] ## Nombre canónico de la imagen
|
||||
ipr = post_params['ipr'] ## Ip del repositorio
|
||||
nfn = post_params['nfn']
|
||||
ids = post_params['ids']
|
||||
msg = post_params['msg'] ## Mensaje de commit
|
||||
|
||||
self.muestraMensaje (7)
|
||||
|
||||
try:
|
||||
res = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') ## Crea inventario Software previamente
|
||||
except:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
return {}
|
||||
|
||||
if res['contents']:
|
||||
self.muestraMensaje (2)
|
||||
inv_sft = res['contents']
|
||||
try:
|
||||
self.interfaceAdmin (nfn, [dsk, par, nci, msg])
|
||||
self.muestraMensaje (9)
|
||||
herror = 0
|
||||
except:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
self.muestraMensaje (10)
|
||||
herror = 1
|
||||
else:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
herror = 1
|
||||
inv_sft = ''
|
||||
|
||||
self.muestraMenu()
|
||||
|
||||
cmd = {
|
||||
'nfn': 'RESPUESTA_ModificarImagenGit',
|
||||
'dsk': dsk, ## Número de disco
|
||||
'par': par, ## Número de partición de donde se creó
|
||||
'ipr': ipr, ## Ip del repositorio donde se alojó
|
||||
'inv_sft': inv_sft
|
||||
}
|
||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||
|
||||
|
||||
def do_RestaurarImagen (self, post_params):
|
||||
for k in ['dsk', 'par', 'idi', 'ipr', 'nci', 'ifs', 'ptc', 'nfn', 'ids']:
|
||||
if k not in post_params:
|
||||
|
@ -406,6 +506,50 @@ class ogAdmClientWorker (ogLiveWorker):
|
|||
}
|
||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||
|
||||
def do_RestaurarImagenGit (self, post_params):
|
||||
for k in ['dsk', 'par', 'ipr', 'nci', 'ptc', 'nfn', 'ids', 'ref']:
|
||||
if k not in post_params:
|
||||
logger.error (f'required parameter ({k}) not in POST params')
|
||||
return {}
|
||||
|
||||
dsk = post_params['dsk']
|
||||
par = post_params['par']
|
||||
ipr = post_params['ipr']
|
||||
nci = post_params['nci']
|
||||
ptc = post_params['ptc'] ## Protocolo de clonación: Unicast, Multicast, Torrent
|
||||
nfn = post_params['nfn']
|
||||
ids = post_params['ids']
|
||||
ref = post_params['ref'] ## Referencia de git a restaurar
|
||||
|
||||
self.muestraMensaje (3)
|
||||
|
||||
try:
|
||||
## the ptc.split() is useless right now, since interfaceAdmin() does ' '.join(params) in order to spawn a shell
|
||||
## however we're going to need it in the future (when everything gets translated into python), plus it's harmless now. So let's do it
|
||||
#self.interfaceAdmin (nfn, [dsk, par, nci, ipr, ptc])
|
||||
self.interfaceAdmin (nfn, [dsk, par, nci, ipr, ref] + ptc.split())
|
||||
self.muestraMensaje (11)
|
||||
herror = 0
|
||||
except:
|
||||
logger.warning ('Error al ejecutar el comando')
|
||||
self.muestraMensaje (12)
|
||||
herror = 1
|
||||
|
||||
cfg = self.LeeConfiguracion()
|
||||
if not cfg:
|
||||
logger.warning ('No se ha podido recuperar la configuración de las particiones del disco')
|
||||
|
||||
self.muestraMenu()
|
||||
|
||||
cmd = {
|
||||
'nfn': 'RESPUESTA_RestaurarImagenGit',
|
||||
'dsk': dsk, ## Número de disco
|
||||
'par': par, ## Número de partición
|
||||
'cfg': self.cfg2obj(cfg), ## Configuración de discos
|
||||
}
|
||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||
|
||||
|
||||
def do_Configurar (self, post_params):
|
||||
for k in ['nfn', 'dsk', 'cfg', 'ids']:
|
||||
if k not in post_params:
|
||||
|
@ -422,7 +566,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
|||
params = []
|
||||
disk_info = cfg.pop (0)
|
||||
logger.debug (f'disk_info ({disk_info})')
|
||||
for k in ['dis', 'tch']:
|
||||
for k in ['dis']:
|
||||
params.append (f'{k}={disk_info[k]}')
|
||||
disk_info_str = '*'.join (params)
|
||||
|
||||
|
@ -816,6 +960,21 @@ class ogAdmClientWorker (ogLiveWorker):
|
|||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||
return self._long_running_job ('CrearImagen', self.do_CrearImagen, args=(post_params,))
|
||||
|
||||
def process_CrearImagenGit (self, path, get_params, post_params, server):
|
||||
logger.debug ('in process_CrearImagenGit, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||
return self._long_running_job ('CrearImagenGit', self.do_CrearImagenGit, args=(post_params,))
|
||||
|
||||
def process_ModificarImagenGit (self, path, get_params, post_params, server):
|
||||
logger.debug ('in process_ModificarImagenGit, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||
return self._long_running_job ('ModificarImagenGit', self.do_ModificarImagenGit, args=(post_params,))
|
||||
|
||||
def process_RestaurarImagenGit (self, path, get_params, post_params, server):
|
||||
logger.debug ('in process_RestaurarImagenGit, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||
return self._long_running_job ('RestaurarImagenGit', self.do_RestaurarImagenGit, args=(post_params,))
|
||||
|
||||
#def process_CrearImagenBasica (self, path, get_params, post_params, server):
|
||||
# logger.debug ('in process_CrearImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||
# logger.warning ('this method has been removed')
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import socket
|
||||
import time
|
||||
|
|
|
@ -106,6 +106,13 @@ class OGAgentSvc(win32serviceutil.ServiceFramework, CommonService):
|
|||
# *********************
|
||||
try:
|
||||
while self.isAlive:
|
||||
client_died=False
|
||||
if os.path.exists ('/windows/temp/ogagentuser_died'):
|
||||
os.unlink ('/windows/temp/ogagentuser_died')
|
||||
client_died=True
|
||||
if client_died:
|
||||
self.notifyLogout (b'')
|
||||
|
||||
# Pumps & processes any waiting messages
|
||||
pythoncom.PumpWaitingMessages()
|
||||
win32event.WaitForSingleObject(self.hWaitStop, 1000)
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
import os
|
||||
import re
|
||||
import time
|
||||
try: import dbus ## don't fail on windows (the worker will later refuse to load anyway)
|
||||
except: pass
|
||||
import random
|
||||
import subprocess
|
||||
import threading
|
||||
|
@ -257,7 +259,7 @@ class ogLiveWorker(ServerWorker):
|
|||
self.REST.sendMessage ('clients/status/webhook', body)
|
||||
|
||||
def interfaceAdmin (self, method, parametros=[]):
|
||||
if method in ['Apagar', 'CambiarAcceso', 'Configurar', 'CrearImagen', 'EjecutarScript', 'getConfiguration', 'getIpAddress', 'IniciarSesion', 'InventarioHardware', 'InventarioSoftware', 'Reiniciar', 'RestaurarImagen']:
|
||||
if method in ['Apagar', 'CambiarAcceso', 'Configurar', 'CrearImagen', 'CrearImagenGit', 'ModificarImagenGit', 'EjecutarScript', 'getConfiguration', 'getIpAddress', 'IniciarSesion', 'InventarioHardware', 'InventarioSoftware', 'Reiniciar', 'RestaurarImagen', 'RestaurarImagenGit']:
|
||||
## python
|
||||
logger.debug (f'({method}) is a python method')
|
||||
exe = '{}/{}.py'.format (self.pathinterface, method)
|
||||
|
@ -369,15 +371,27 @@ class ogLiveWorker(ServerWorker):
|
|||
|
||||
def cargaPaginaWeb (self, url=None):
|
||||
if (not url): url = self.urlMenu
|
||||
os.system ('pkill -9 browser')
|
||||
|
||||
p = subprocess.Popen (['/usr/bin/browser', '-qws', url])
|
||||
dbus_address = os.environ.get ('DBUS_SESSION_BUS_ADDRESS')
|
||||
if not dbus_address: logger.warning ('env var DBUS_SESSION_BUS_ADDRESS not set, cargaPaginaWeb() will likely not work')
|
||||
|
||||
b = dbus.SystemBus()
|
||||
dest = 'es.opengnsys.OGBrowser.browser'
|
||||
path = '/'
|
||||
interface = None
|
||||
method = 'setURL'
|
||||
signature = 's'
|
||||
try:
|
||||
p.wait (2) ## if the process dies before 2 seconds...
|
||||
logger.error ('Error al ejecutar browser, return code "{}"'.format (p.returncode))
|
||||
return False
|
||||
except subprocess.TimeoutExpired:
|
||||
pass
|
||||
b.call_blocking (dest, path, interface, method, 's', [url])
|
||||
except Exception as e:
|
||||
if 'ServiceUnknown' in str(e):
|
||||
logger.warning ('browser is not running, launching a new one')
|
||||
browser_log_fd = open ('/var/log/launch_browser.log', 'a')
|
||||
subprocess.Popen (['/usr/bin/launch_browser', url], stdout=browser_log_fd, stderr=subprocess.STDOUT)
|
||||
browser_log_fd.close()
|
||||
else:
|
||||
logger.error (f'Error al cambiar URL: ({e})')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ FunctionEnd
|
|||
Function GetParameters
|
||||
${GetOptions} $CMDLINE "/server" $SERVERIP_VALUE
|
||||
${If} $SERVERIP_VALUE == ""
|
||||
StrCpy $SERVERIP_VALUE "192.168.2.10"
|
||||
StrCpy $SERVERIP_VALUE "192.168.2.1:8443"
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
|
@ -226,10 +226,12 @@ LangString PARAMS_TITLE ${LANG_ENGLISH} "Setup parameters"
|
|||
LangString PARAMS_TITLE ${LANG_SPANISH} "Parametros de configuracion"
|
||||
LangString PARAMS_TITLE ${LANG_FRENCH} "Parametres de configuration"
|
||||
LangString PARAMS_TITLE ${LANG_GERMAN} "Setup-Parameter"
|
||||
LangString SERVER_LABEL ${LANG_ENGLISH} "OpenGnsys Server IP Address"
|
||||
LangString SERVER_LABEL ${LANG_SPANISH} "Direccion IP del Servidor OpenGnsys"
|
||||
LangString SERVER_LABEL ${LANG_FRENCH} "Adresse IP du Serveur OpenGnsys"
|
||||
LangString SERVER_LABEL ${LANG_GERMAN} "OpenGnsys-Server-IP-Adresse"
|
||||
|
||||
LangString SERVER_LABEL ${LANG_ENGLISH} "OpenGnsys Server IP Address and port (eg. 192.168.98.99:8443)"
|
||||
LangString SERVER_LABEL ${LANG_SPANISH} "Direccion IP y puerto del Servidor OpenGnsys (p. ej. 192.168.98.99:8443)"
|
||||
LangString SERVER_LABEL ${LANG_FRENCH} "Adresse IP et port du Serveur OpenGnsys (ex. 192.168.98.99:8443)"
|
||||
LangString SERVER_LABEL ${LANG_GERMAN} "OpenGnsys Server IP-Adresse und Port (z. B. 192.168.98.99:8443)"
|
||||
|
||||
LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall $(^Name)"
|
||||
LangString ^UninstallLink ${LANG_SPANISH} "Desinstalar $(^Name)"
|
||||
LangString ^UninstallLink ${LANG_FRENCH} "D<>sinstaller $(^Name)"
|
||||
|
|
Loading…
Reference in New Issue