diff --git a/actor/src/UDSActorConfig.py b/actor/src/UDSActorConfig.py
index 87bc8bbd..6b7a250f 100644
--- a/actor/src/UDSActorConfig.py
+++ b/actor/src/UDSActorConfig.py
@@ -88,9 +88,11 @@ class UDSConfigDialog(QDialog):
auth: udsactor.types.AuthenticatorType
for auth in self.api.enumerateAuthenticators():
self.ui.authenticators.addItem(auth.auth, userData=auth)
+ # Last, add "admin" authenticator (for uds root user)
+ self.ui.authenticators.addItem('Administration', userData=udsactor.types.AuthenticatorType('admin', 'admin', 'admin', 'admin', 1, False))
def textChanged(self):
- enableButtons = self.ui.host.text() != '' and self.ui.username.text() != '' and self.ui.password.text() != ''
+ enableButtons = bool(self.ui.host.text() and self.ui.username.text() and self.ui.password.text() and self.ui.authenticators.currentText())
self.ui.registerButton.setEnabled(enableButtons)
def finish(self):
@@ -100,18 +102,24 @@ class UDSConfigDialog(QDialog):
# Get network card. Will fail if no network card is available, but don't mind (not contempled)
data: udsactor.types.InterfaceInfo = next(udsactor.operations.getNetworkInfo())
- key = self.api.register(
- self.ui.authenticators.currentData().auth,
- self.ui.username.text(),
- self.ui.password.text(),
- data.ip or '', # IP
- data.mac or '', # MAC
- self.ui.preCommand.text(),
- self.ui.runonceCommand.text(),
- self.ui.postConfigCommand.text()
- )
+ try:
+ key = self.api.register(
+ self.ui.authenticators.currentData().auth,
+ self.ui.username.text(),
+ self.ui.password.text(),
+ data.ip or '', # IP
+ data.mac or '', # MAC
+ self.ui.preCommand.text(),
+ self.ui.runonceCommand.text(),
+ self.ui.postConfigCommand.text(),
+ (self.ui.logLevelComboBox.currentIndex() + 1) * 10000 # Loglevel
+ )
+ # Store parameters on register for later use, notify user of registration
- print(key)
+ # Inform the user
+ QMessageBox.information(self, 'UDS Registration', 'Registration with UDS completed.', QMessageBox.Ok)
+ except udsactor.rest.RESTError as e:
+ QMessageBox.critical(self, 'UDS Registration', 'UDS Registration error: {}'.format(e), QMessageBox.Ok)
if __name__ == "__main__":
diff --git a/actor/src/designer/setup-dialog.ui b/actor/src/designer/setup-dialog.ui
index 687be286..e9ce3664 100644
--- a/actor/src/designer/setup-dialog.ui
+++ b/actor/src/designer/setup-dialog.ui
@@ -579,6 +579,22 @@
+
+ authenticators
+ currentTextChanged(QString)
+ UdsActorSetupDialog
+ textChanged()
+
+
+ 343
+ 137
+
+
+ 294
+ 153
+
+
+
textChanged()
diff --git a/actor/src/udsactor/rest.py b/actor/src/udsactor/rest.py
index 7105771e..d2ff9b32 100644
--- a/actor/src/udsactor/rest.py
+++ b/actor/src/udsactor/rest.py
@@ -125,7 +125,7 @@ class REST:
pass
- def register(self, auth: str, username: str, password: str, ip: str, mac: str, preCommand: str, runOnceCommand: str, postCommand: str) -> str:
+ def register(self, auth: str, username: str, password: str, ip: str, mac: str, preCommand: str, runOnceCommand: str, postCommand: str, logLevel: int) -> str:
"""
Raises an exception if could not register, or registers and returns the "authorization token"
"""
@@ -133,20 +133,28 @@ class REST:
'username': username,
'ip': ip,
'mac': mac,
- 'preCommand': preCommand,
- 'runOnceCommand': runOnceCommand,
- 'postCommand': postCommand
+ 'pre_command': preCommand,
+ 'run_once_command': runOnceCommand,
+ 'post_command': postCommand,
+ 'log_level': logLevel
}
try:
# First, try to login
authInfo = {'auth': auth, 'username': username, 'password': password }
headers = self.headers
result = requests.post(self.url + 'auth/login', data=json.dumps(authInfo), headers=headers, verify=self.validateCert)
+ if not result.ok or result.json()['result'] == 'error':
+ raise Exception() # Invalid credentials
+ except (requests.ConnectionError, requests.ConnectTimeout) as e:
+ raise RESTConnectionError(str(e))
+ except Exception as e:
+ raise RESTError('Invalid credentials')
+
+ try:
+ headers['X-Auth-Token'] = result.json()['token']
+ result = requests.post(self.url + 'actor/v2/register', data=json.dumps(data), headers=headers, verify=self.validateCert)
if result.ok:
- headers['X-Auth-Token'] = result.json()['token']
- result = requests.post(self.url + 'actor/v2/register', data=json.dumps(data), headers=headers, verify=self.validateCert)
- if result.ok:
- return result.json()['result']
+ return result.json()['result']
except (requests.ConnectionError, requests.ConnectTimeout) as e:
raise RESTConnectionError(str(e))
except Exception as e:
diff --git a/actor/src/ui/setup_dialog_ui.py b/actor/src/ui/setup_dialog_ui.py
index a8192360..29c56494 100644
--- a/actor/src/ui/setup_dialog_ui.py
+++ b/actor/src/ui/setup_dialog_ui.py
@@ -193,6 +193,7 @@ class Ui_UdsActorSetupDialog(object):
self.browsePostConfigButton.clicked.connect(UdsActorSetupDialog.browsePostConfig)
self.browseRunOnceButton.clicked.connect(UdsActorSetupDialog.browseRunOnce)
self.host.editingFinished.connect(UdsActorSetupDialog.updateAuthenticators)
+ self.authenticators.currentTextChanged['QString'].connect(UdsActorSetupDialog.textChanged)
QtCore.QMetaObject.connectSlotsByName(UdsActorSetupDialog)
def retranslateUi(self, UdsActorSetupDialog):
diff --git a/server/src/uds/REST/methods/actor_v2.py b/server/src/uds/REST/methods/actor_v2.py
index d4618eb2..513e1da6 100644
--- a/server/src/uds/REST/methods/actor_v2.py
+++ b/server/src/uds/REST/methods/actor_v2.py
@@ -30,12 +30,12 @@
"""
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
+import secrets
import logging
import typing
-from django.utils.translation import ugettext as _
+from uds.models import getSqlDatetimeAsUnix, getSqlDatetime, ActorToken
-from uds.models.util import getSqlDatetimeAsUnix
from uds.core import VERSION
from ..handlers import Handler
@@ -72,8 +72,6 @@ class ActorV2Action(Handler):
def get(self):
return actorResult('')
-
-
class ActorV2Register(ActorV2Action):
"""
Registers an actor
@@ -81,9 +79,34 @@ class ActorV2Register(ActorV2Action):
authenticated = True
name = 'register'
- def post(self):
- logger.debug('Args: %s, Params: %s', self._args, self._params)
- return actorResult('ok')
+ def post(self) -> typing.MutableMapping[str, typing.Any]:
+ actorToken: ActorToken
+ try:
+ # If already exists a token for this MAC, return it instead of creating a new one, and update the information...
+ actorToken = ActorToken.objects.get(mac=self._params['mac'])
+ # Update parameters
+ actorToken.ip_from = self._request.ip
+ actorToken.ip = self._params['ip']
+ actorToken.pre_command = self._params['pre_command']
+ actorToken.post_command = self._params['post_command']
+ actorToken.runonce_command = self._params['run_once_command']
+ actorToken.log_level = self._params['log_level']
+ actorToken.stamp = getSqlDatetime()
+ actorToken.save()
+ except Exception:
+ actorToken = ActorToken.objects.create(
+ username=self._params['username'],
+ ip_from=self._request.ip,
+ ip=self._params['ip'],
+ mac=self._params['mac'],
+ pre_command=self._params['pre_command'],
+ post_command=self._params['post_command'],
+ runonce_command=self._params['run_once_command'],
+ log_level=self._params['log_level'],
+ token=secrets.token_urlsafe(36),
+ stamp=getSqlDatetime()
+ )
+ return actorResult(actorToken.token)
class ActorV2Initiialize(ActorV2Action):
"""
diff --git a/server/src/uds/models/__init__.py b/server/src/uds/models/__init__.py
index 054741b3..106fa703 100644
--- a/server/src/uds/models/__init__.py
+++ b/server/src/uds/models/__init__.py
@@ -112,4 +112,7 @@ from .tag import Tag
# Utility
from .dbfile import DBFile
+# Actor tokens
+from .actor_token import ActorToken
+
logger = logging.getLogger(__name__)
diff --git a/server/src/uds/web/forms/LoginForm.py b/server/src/uds/web/forms/LoginForm.py
index 2ee133dd..4825a48f 100644
--- a/server/src/uds/web/forms/LoginForm.py
+++ b/server/src/uds/web/forms/LoginForm.py
@@ -42,6 +42,7 @@ class LoginForm(forms.Form):
user = forms.CharField(label=_('Username'), max_length=64, widget=forms.TextInput())
password = forms.CharField(label=_('Password'), widget=forms.PasswordInput(attrs={'title': _('Password')}), required=False)
authenticator = forms.ChoiceField(label=_('Authenticator'), choices=(), required=False)
+ logouturl = forms.CharField(widget=forms.HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
# If an specified login is passed in, retrieve it & remove it from kwargs dict