Compare commits

..

45 Commits
5.1.0 ... main

Author SHA1 Message Date
Natalia Serrano 950b163602 Merge pull request 'refs #2329 write output of launch_browser into a file' (#43) from Popen-stdout into main
Reviewed-on: #43
2025-06-26 12:47:48 +02:00
Natalia Serrano 72b832d654 refs #2329 write output of launch_browser into a file 2025-06-26 12:46:37 +02:00
Natalia Serrano 65c07fea1e Merge pull request 'Crear endpoint de ModificarImagenGit' (#42) from oggit-tls into main
Reviewed-on: #42
2025-06-25 11:54:51 +02:00
Natalia Serrano 9cf7ec5a56 refs #2312 fix changelogs 2025-06-25 11:54:20 +02:00
Vadim Trochinsky 60bab01556 refs #2247 Eliminar parametros sin usar 2025-06-25 11:44:50 +02:00
Vadim vtroshchinskiy b4c86bb175 refs #2312 fix changelog 2025-06-25 11:32:05 +02:00
Vadim Trochinsky 2f5ac81235 refs #2247 Add ModificarImagenGit endpoint 2025-06-25 11:32:05 +02:00
Natalia Serrano b1a67b1191 Merge pull request 'unificar-endpoints' (#41) from unificar-endpoints into main
Reviewed-on: #41
2025-06-23 12:39:52 +02:00
Natalia Serrano 7be441ca99 refs #2281 last commit broke linux--fix 2025-06-23 12:37:42 +02:00
Natalia Serrano bb856e5b63 refs #2281 fix logout on windows 2025-06-23 12:27:45 +02:00
Natalia Serrano 22f7ce0bb9 refs #2257 rename some endpoints 2025-06-23 12:27:03 +02:00
Natalia Serrano 250de7a070 refs #2285 improve failure conditions in EjecutarScript 2025-06-23 12:26:20 +02:00
Natalia Serrano 2feff97a91 refs #2278 change some labels in the windows installer 2025-06-23 09:58:12 +02:00
Natalia Serrano 10349a35f1 Merge pull request 'refs #2217 merge oggit' (#40) from oggit-debian-changelog into main
Reviewed-on: #40
2025-06-16 11:13:42 +02:00
Natalia Serrano a84bed3439 refs #2217 merge oggit 2025-06-16 11:13:22 +02:00
Natalia Serrano 05d2375e21 Merge pull request 'refs #2217 merge oggit' (#39) from oggit-changelog into main
Reviewed-on: #39
2025-06-16 11:11:09 +02:00
Natalia Serrano 8fea0737f2 refs #2217 merge oggit 2025-06-16 11:10:44 +02:00
Natalia Serrano 7128f12049 refs #2217 Merge branch 'oggit' 2025-06-16 09:55:22 +02:00
Natalia Serrano 734df2749b refs #2217 merge oggit 2025-06-16 09:53:46 +02:00
Natalia Serrano 946020d728 Merge pull request 'refs #2208 improve fail condition when no network is detected' (#38) from error-no-net into main
Reviewed-on: #38
2025-06-13 10:03:54 +02:00
Natalia Serrano 1a38999aef refs #2208 improve fail condition when no network is detected 2025-06-13 10:03:24 +02:00
Natalia Serrano 2dd678737b Merge pull request 'ogagentuser-sigterm' (#37) from ogagentuser-sigterm into main
Reviewed-on: #37
2025-06-12 15:39:24 +02:00
Natalia Serrano 165746a94b refs #2211 send logout upon client disconnect 2025-06-12 15:37:17 +02:00
Natalia Serrano 3553aee8ce refs #2179 check that windows-only variable is defined 2025-06-05 12:10:22 +02:00
Natalia Serrano b77b42ec22 refs #2177 correctly handle UNIX signals 2025-06-05 12:09:07 +02:00
Natalia Serrano e20c671c1e Merge pull request 'tls-again' (#36) from tls-again into main
Reviewed-on: #36
2025-05-28 10:53:07 +02:00
Natalia Serrano 15d4f2cf6b refs #2056 #2057 look for certs in a few places 2025-05-28 10:47:40 +02:00
Natalia Serrano e920a3c681 refs #2055 make TLS checks optional for the server 2025-05-21 17:36:13 +02:00
Natalia Serrano 921706e9f0 refs #2054 use a global to specify TLS verification or not 2025-05-21 17:31:33 +02:00
Natalia Serrano 63944cef0e refs #2054 send client cert to ogcore, optionally verify ogcore's cert 2025-05-21 17:30:11 +02:00
Natalia Serrano 3ae4471d5d refs #2055 use proper server cert, demand client cert 2025-05-21 17:21:47 +02:00
Natalia Serrano d1ce3b5cc9 Merge pull request 'refs #2060 launch QT6 browser, use dbus to change URLs' (#35) from browser-nuevo into main
Reviewed-on: #35
2025-05-21 16:05:40 +02:00
Natalia Serrano 1fa2a4f0bb refs #2060 launch QT6 browser, use dbus to change URLs 2025-05-21 16:02:46 +02:00
Natalia Serrano ac9ab7e8f5 refs #2036 downgrade to qt4 browser again 2025-05-19 11:05:43 +02:00
Natalia Serrano 05e0b83b91 Merge pull request 'no-tls' (#34) from no-tls into main
Reviewed-on: #34
2025-05-19 10:52:49 +02:00
Natalia Serrano 9d0589547f refs #2034 disable TLS on request 2025-05-19 10:49:14 +02:00
Natalia Serrano ccb6cdfa54 refs #2034 disable TLS on request 2025-05-19 09:47:07 +02:00
Natalia Serrano 0d375e9aae refs #2034 disable TLS on request 2025-05-19 09:45:43 +02:00
Natalia Serrano 60cc47dd30 Merge pull request 'refs #1998 run the new browser' (#33) from exec-ogbrowser into main
Reviewed-on: #33
2025-05-16 14:53:20 +02:00
Natalia Serrano acc9c2ed07 refs #1998 run the new browser 2025-05-16 14:49:35 +02:00
Vadim vtroshchinskiy 17ec13d77c Soporte de oggit 2025-05-16 09:57:16 +02:00
Natalia Serrano dd445cee65 Merge pull request 'refs #1983 log length of sessions' (#31) from log-sess-len into main
Reviewed-on: #31
2025-05-14 10:46:46 +02:00
Natalia Serrano d231816c0f refs #1983 log length of sessions 2025-05-14 10:45:53 +02:00
Natalia Serrano 0099a05921 Merge pull request 'refs #1952 fix url' (#30) from fix-url into main
Reviewed-on: #30
2025-05-06 13:33:52 +02:00
Natalia Serrano db9f4992be refs #1952 fix url 2025-05-06 13:33:21 +02:00
15 changed files with 537 additions and 46 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -1 +1 @@
5.0.0
6.1.1

View File

@ -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

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 += '/'
@ -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:

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 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):

View File

@ -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:

View File

@ -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:

View File

@ -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':

View File

@ -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')

View File

@ -30,6 +30,7 @@
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
import os
import json
import socket
import time

View File

@ -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)

View File

@ -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

View File

@ -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)"