increased security by encrypting with own key, different on each instalation

This commit is contained in:
Adolfo Gómez García 2022-10-27 14:46:34 +02:00
parent ad269b3c28
commit 7bd0d571e6
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
2 changed files with 81 additions and 40 deletions

View File

@ -40,13 +40,14 @@ import logging
from collections import abc
from django.utils.translation import get_language, ugettext as _, ugettext_noop
from django.conf import settings
from uds.core.managers import cryptoManager
logger = logging.getLogger(__name__)
UDSB = b'udsprotect'
UDSB = b'udsprotect' # UDS base key, old
UDSK = settings.SECRET_KEY[8:24].encode() # UDS key, new
class gui:
"""
@ -1080,8 +1081,9 @@ class UserInterface(metaclass=UserInterfaceType):
# logger.debug('Serializing value {0}'.format(v.value))
val = b'\001' + pickle.dumps(v.value, protocol=0)
elif v.isType(gui.InfoField.PASSWORD_TYPE):
val = b'\004' + cryptoManager().AESCrypt(
v.value.encode('utf8'), UDSB, True
# Old \004 field type is not used anymore, is for old "udsprotect" encryption
val = b'\005' + cryptoManager().AESCrypt(
v.value.encode('utf8'), UDSK, True
)
elif v.isType(gui.InputField.NUMERIC_TYPE):
val = str(int(v.num())).encode('utf8')
@ -1132,6 +1134,8 @@ class UserInterface(metaclass=UserInterfaceType):
val = pickle.loads(v[1:])
elif v and v[0] == 4:
val = cryptoManager().AESDecrypt(v[1:], UDSB, True).decode()
elif v and v[0] == 5:
val = cryptoManager().AESDecrypt(v[1:], UDSK, True).decode()
else:
val = v
# Ensure "legacy bytes" values are loaded correctly as unicode

View File

@ -30,12 +30,14 @@
"""
Author: Adolfo Gómez, dkmaster at dkmon dot com
"""
from functools import reduce
import logging
import operator
import typing
import csv
import yaml
from django.core.management.base import BaseCommand
from django.db.models import Q
from uds import models
@ -195,12 +197,46 @@ def osmanager_exporter(osmanager: models.OSManager) -> typing.Dict[str, typing.A
o = managed_object_exporter(osmanager)
return o
def calendar_exporter(calendar: models.Calendar) -> typing.Dict[str, typing.Any]:
"""
Exports a calendar to a dict
"""
c = uuid_object_exporter(calendar)
c.update(
{
'name': calendar.name,
'comments': calendar.comments,
'modified': calendar.modified,
}
)
return c
def calendar_rule_exporter(calendar_rule: models.CalendarRule) -> typing.Dict[str, typing.Any]:
"""
Exports a calendar rule to a dict
"""
c = uuid_object_exporter(calendar_rule)
c.update(
{
'calendar': calendar_rule.calendar.uuid,
'name': calendar_rule.name,
'comments': calendar_rule.comments,
'start': calendar_rule.start,
'end': calendar_rule.end,
'frequency': calendar_rule.frequency,
'interval': calendar_rule.interval,
'duration': calendar_rule.duration,
'duration_unit': calendar_rule.duration_unit,
}
)
return c
class Command(BaseCommand):
help = 'Export entities from UDS to be imported in another UDS instance'
VALID_ENTITIES: typing.Mapping[str, typing.Callable[[], str]]
verbose: bool = True
filter_args: typing.List[typing.Tuple[str, str]] = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -234,21 +270,21 @@ class Command(BaseCommand):
help='Output file name. Defaults to /tmp/export.yaml',
)
# Filter ALL entities by name
# Filter ALL entities by name, multiple names can be specified
parser.add_argument(
'--filter-name',
action='store',
action='append',
dest='filter_name',
default=None,
default=[],
help='Filter ALL entities by name',
)
# filter ALL entities by uuid
# Filter ALL entities by uuid, multiple uuids can be specified
parser.add_argument(
'--filter-uuid',
action='store',
action='append',
dest='filter_uuid',
default=None,
default=[],
help='Filter ALL entities by uuid',
)
@ -268,14 +304,11 @@ class Command(BaseCommand):
self.stderr.write(f'Exporting entities: {",".join(options["entities"])}')
# Compose filter name for kwargs
filter_kwargs = {}
for i in options['filter_name']:
self.filter_args.append(('name__icontains', i))
if options['filter_name']:
filter_kwargs['name__icontains'] = options['filter_name']
if options['filter_uuid']:
filter_kwargs['uuid__icontains'] = options['filter_uuid']
for i in options['filter_uuid']:
self.filter_args.append(('uuid', i))
# some entities are redundant, so remove them from the list
entities = self.remove_reduntant_entities(options['entities'])
@ -284,23 +317,27 @@ class Command(BaseCommand):
with open(options['output'], 'w') as f:
for entity in entities:
self.stderr.write(f'Exporting {entity}')
f.write(self.VALID_ENTITIES[entity](**filter_kwargs))
f.write(self.VALID_ENTITIES[entity]())
f.write('')
if self.verbose:
self.stderr.write(f'Exported to {options["output"]}')
def apply_filter(
self, model: typing.Type[ModelType], **kwargs: str
self, model: typing.Type[ModelType]
) -> typing.Iterable[ModelType]:
"""
Applies a filter to a model
"""
if self.verbose:
# Explit xxx__icontains=yyy to xxx=yyy
values = [f'{k.split("__")[0]}={v}' for k, v in kwargs.items()]
self.stderr.write(f'Filtering {model.__name__} by {",".join(values)}')
yield from model.objects.all().filter(**kwargs)
# Filter is a filter name, and an array of values
values = [f'{k.split("__")[0]}={v}' for k, v in self.filter_args]
self.stderr.write(f'Filtering {model.__name__}: \n ', ending='')
self.stderr.write("\n ".join(values))
# Generate "OR" filter with all kwargs
if self.filter_args:
return model.objects.filter(reduce(operator.or_, (Q(**{k: v}) for k, v in self.filter_args)))
return model.objects.all()
def output_count(
self, message: str, iterable: typing.Iterable[T]
@ -318,19 +355,19 @@ class Command(BaseCommand):
if self.verbose:
self.stderr.write('\n') # New line after count
def export_providers(self, **kwargs: str) -> str:
def export_providers(self) -> str:
"""
Exports all providers to a list of dicts
"""
return '# Providers\n' + yaml.safe_dump(
[provider_exporter(p) for p in self.apply_filter(models.Provider, **kwargs)]
[provider_exporter(p) for p in self.apply_filter(models.Provider)]
)
def export_services(self, **kwargs: str) -> str:
def export_services(self) -> str:
# First, locate providers for services with the filter
services_list = list(
self.output_count(
'Filtering services', self.apply_filter(models.Service, **kwargs)
'Filtering services', self.apply_filter(models.Service)
)
)
providers_list = set(
@ -358,7 +395,7 @@ class Command(BaseCommand):
+ yaml.safe_dump(services)
)
def export_authenticators(self, **kwargs: str) -> str:
def export_authenticators(self) -> str:
"""
Exports all authenticators to a list of dicts
"""
@ -367,19 +404,19 @@ class Command(BaseCommand):
authenticator_exporter(a)
for a in self.output_count(
'Saving authenticators',
self.apply_filter(models.Authenticator, **kwargs),
self.apply_filter(models.Authenticator),
)
]
)
def export_users(self, **kwargs: str) -> str:
def export_users(self) -> str:
"""
Exports all users to a list of dicts
"""
# first, locate authenticators for users with the filter
users_list = list(
self.output_count(
'Filtering users', self.apply_filter(models.User, **kwargs)
'Filtering users', self.apply_filter(models.User)
)
)
authenticators_list = set(
@ -417,14 +454,14 @@ class Command(BaseCommand):
+ yaml.safe_dump(users)
)
def export_groups(self, **kwargs: str) -> str:
def export_groups(self) -> str:
"""
Exports all groups to a list of dicts
"""
# First export authenticators for groups with the filter
groups_list = list(
self.output_count(
'Filtering groups', self.apply_filter(models.Group, **kwargs)
'Filtering groups', self.apply_filter(models.Group)
)
)
authenticators_list = set(
@ -450,7 +487,7 @@ class Command(BaseCommand):
+ yaml.safe_dump(groups)
)
def export_networks(self, **kwargs: str) -> str:
def export_networks(self) -> str:
"""
Exports all networks to a list of dicts
"""
@ -458,19 +495,19 @@ class Command(BaseCommand):
[
network_exporter(n)
for n in self.output_count(
'Saving networks', self.apply_filter(models.Network, **kwargs)
'Saving networks', self.apply_filter(models.Network)
)
]
)
def export_transports(self, **kwargs: str) -> str:
def export_transports(self) -> str:
"""
Exports all transports to a list of dicts
"""
# First, export networks for transports with the filter
transports_list = list(
self.output_count(
'Filtering transports', self.apply_filter(models.Transport, **kwargs)
'Filtering transports', self.apply_filter(models.Transport)
)
)
networks_list = set()
@ -494,7 +531,7 @@ class Command(BaseCommand):
+ yaml.safe_dump(transports)
)
def export_osmanagers(self, **kwargs: str) -> str:
def export_osmanagers(self) -> str:
"""
Exports all osmanagers to a list of dicts
"""
@ -502,7 +539,7 @@ class Command(BaseCommand):
[
osmanager_exporter(o)
for o in self.output_count(
'Saving osmanagers', self.apply_filter(models.OSManager, **kwargs)
'Saving osmanagers', self.apply_filter(models.OSManager)
)
]
)