forked from shaba/openuds
Started to implement a mechanism to allow a secure sso.
We have started a way for pass the credentials from UDS directly to VM, without passing it to UDS. Currently we are working on a credential provider for windows, that will interact with UDS. We will release this provider as soon as it is functional ;-)
This commit is contained in:
parent
2683fddfc1
commit
3f7fb77086
@ -65,6 +65,9 @@ ERR_HOST_NOT_MANAGED = 2
|
||||
ERR_USER_SERVICE_NOT_FOUND = 3
|
||||
ERR_OSMANAGER_ERROR = 4
|
||||
|
||||
# Constants for tickets
|
||||
OWNER = 'ACTOR'
|
||||
SECURE_OWNER = 'SACTOR'
|
||||
|
||||
# Enclosed methods under /actor path
|
||||
class Actor(Handler):
|
||||
@ -132,17 +135,24 @@ class Actor(Handler):
|
||||
raise RequestError('Invalid request')
|
||||
|
||||
try:
|
||||
return Actor.result(TicketStore.get(self._args[1], invalidate=True, secure=secure))
|
||||
return Actor.result(TicketStore.get(self._args[1], invalidate=True, owner=SECURE_OWNER if secure else OWNER))
|
||||
except Exception:
|
||||
return Actor.result({})
|
||||
|
||||
def getSecureTicket(self):
|
||||
'''
|
||||
Processes get request for SECURE tickets request, i.e. tickets that can only be got by actors with valid credentials
|
||||
GET /rest/actor/sticket/[ticketId]?key=[master key]
|
||||
'''
|
||||
logger.debug('Get secure ticket value for {}'.format(self._args))
|
||||
v = self.validateRequestKey()
|
||||
if v is not None:
|
||||
return v
|
||||
# v = self.validateRequestKey()
|
||||
# if v is not None:
|
||||
# return v
|
||||
|
||||
return self.getTicket(secure=True)
|
||||
# TODO: Remove this, is just for testings
|
||||
# return Actor.result({'username': 'user', 'password': 'password', 'domain': None})
|
||||
# return self.getTicket(secure=True)
|
||||
raise RequestError('Invalid request')
|
||||
|
||||
def get(self):
|
||||
'''
|
||||
@ -156,7 +166,7 @@ class Actor(Handler):
|
||||
if self._args[0] == 'ticket':
|
||||
return self.getTicket()
|
||||
|
||||
if self._args[0] == 'secureTicket':
|
||||
if self._args[0] == 'sticket':
|
||||
return self.getSecureTicket()
|
||||
|
||||
if self._args[0] == 'testn': # Test, but without master key
|
||||
@ -174,6 +184,7 @@ class Actor(Handler):
|
||||
actorVersion = self._params.get('version', 'unknown')
|
||||
service = self.getUserServiceByIds()
|
||||
if service is None:
|
||||
logger.info('Unmanaged host request: {}'.format(self._args))
|
||||
return Actor.result(_('Unmanaged host'), error=ERR_HOST_NOT_MANAGED)
|
||||
else:
|
||||
# Set last seen actor version
|
||||
@ -212,6 +223,10 @@ class Actor(Handler):
|
||||
logger.debug('Setting comms url to {}'.format(data))
|
||||
service.setCommsUrl(data)
|
||||
return Actor.result('ok')
|
||||
elif message == 'ssoAvailable':
|
||||
logger.debug('Setting that SSO is available')
|
||||
service.setProperty('sso_available', 1)
|
||||
return Actor.result('ok')
|
||||
elif message == 'version':
|
||||
version = self._params.get('version', 'unknown')
|
||||
logger.debug('Got notified version {}'.format(version))
|
||||
|
@ -36,6 +36,7 @@ from django.conf import settings
|
||||
from Crypto.PublicKey import RSA
|
||||
from OpenSSL import crypto
|
||||
from Crypto.Random import atfork
|
||||
|
||||
import hashlib
|
||||
import array
|
||||
import uuid
|
||||
@ -58,6 +59,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class CryptoManager(object):
|
||||
CODEC = 'base64'
|
||||
INITIAL_VECTOR = 'UDS AES Initial.'
|
||||
|
||||
instance = None
|
||||
|
||||
|
20
server/src/uds/migrations/0022_ticketstore_owner.py
Normal file
20
server/src/uds/migrations/0022_ticketstore_owner.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.5 on 2016-06-15 09:24
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('uds', '0021_auto_20160405_0429'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ticketstore',
|
||||
name='owner',
|
||||
field=models.CharField(blank=True, default=None, max_length=8, null=True),
|
||||
),
|
||||
]
|
@ -45,7 +45,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2016-06-15'
|
||||
__updated__ = '2016-06-17'
|
||||
|
||||
|
||||
class TicketStore(UUIDModel):
|
||||
@ -57,6 +57,7 @@ class TicketStore(UUIDModel):
|
||||
MAX_VALIDITY = 60 * 60 * 12
|
||||
# Cleanup will purge all elements that have been created MAX_VALIDITY ago
|
||||
|
||||
owner = models.CharField(null=True, blank=True, default=None, max_length=8)
|
||||
stamp = models.DateTimeField() # Date creation or validation of this entry
|
||||
validity = models.IntegerField(default=60) # Duration allowed for this ticket to be valid, in seconds
|
||||
|
||||
@ -78,46 +79,49 @@ class TicketStore(UUIDModel):
|
||||
|
||||
@staticmethod
|
||||
def generateUuid():
|
||||
# more secure is this:
|
||||
# more owner is this:
|
||||
# ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(40))
|
||||
return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(40))
|
||||
return cryptoManager().randomString(40)
|
||||
|
||||
@staticmethod
|
||||
def create(data, validator=None, validity=DEFAULT_VALIDITY, secure=False):
|
||||
def create(data, validator=None, validity=DEFAULT_VALIDITY, owner=None, secure=False):
|
||||
'''
|
||||
validity is in seconds
|
||||
'''
|
||||
if validator is not None:
|
||||
validator = pickle.dumps(validator)
|
||||
uuid = TicketStore.objects.create(stamp=getSqlDatetime(), data=pickle.dumps(data), validator=validator, validity=validity).uuid
|
||||
if secure is False:
|
||||
return uuid
|
||||
else:
|
||||
return cryptoManager().encrypt(uuid)[:-2]
|
||||
data = pickle.dumps(data)
|
||||
if secure:
|
||||
data = cryptoManager().encrypt(data)
|
||||
|
||||
return TicketStore.objects.create(stamp=getSqlDatetime(), data=data, validator=validator, validity=validity, owner=owner).uuid
|
||||
|
||||
@staticmethod
|
||||
def store(uuid, data, validator=None, validity=DEFAULT_VALIDITY):
|
||||
def store(uuid, data, validator=None, validity=DEFAULT_VALIDITY, owner=owner, secure=False):
|
||||
'''
|
||||
Stores an ticketstore. If one with this uuid already exists, replaces it. Else, creates a new one
|
||||
validity is in seconds
|
||||
'''
|
||||
if validator is not None:
|
||||
validator = pickle.dumps(validator)
|
||||
|
||||
data = pickle.dumps(data)
|
||||
if secure:
|
||||
data = cryptoManager().encrypt()
|
||||
|
||||
try:
|
||||
t = TicketStore.objects.get(uuid=uuid)
|
||||
t.data = pickle.dumps(data)
|
||||
t = TicketStore.objects.get(uuid=uuid, owner=owner)
|
||||
t.data = data
|
||||
t.stamp = getSqlDatetime()
|
||||
t.validity = validity
|
||||
t.save()
|
||||
except TicketStore.DoesNotExist:
|
||||
t = TicketStore.objects.create(uuid=uuid, stamp=getSqlDatetime(), data=pickle.dumps(data), validator=validator, validity=validity)
|
||||
t = TicketStore.objects.create(uuid=uuid, stamp=getSqlDatetime(), data=data, validator=validator, validity=validity, owner=owner)
|
||||
|
||||
@staticmethod
|
||||
def get(uuid, invalidate=True, secure=False):
|
||||
if secure:
|
||||
uuid = cryptoManager().decrypt(uuid + "=\n")
|
||||
def get(uuid, invalidate=True, owner=None, secure=False):
|
||||
try:
|
||||
t = TicketStore.objects.get(uuid=uuid)
|
||||
t = TicketStore.objects.get(uuid=uuid, owner=owner)
|
||||
validity = datetime.timedelta(seconds=t.validity)
|
||||
now = getSqlDatetime()
|
||||
|
||||
@ -125,7 +129,10 @@ class TicketStore(UUIDModel):
|
||||
if t.stamp + validity < now:
|
||||
raise TicketStore.InvalidTicket('Not valid anymore')
|
||||
|
||||
data = pickle.loads(t.data)
|
||||
if secure is True:
|
||||
data = pickle.loads(cryptoManager().decrypt(t.data))
|
||||
else:
|
||||
data = pickle.loads(t.data)
|
||||
|
||||
# If has validator, execute it
|
||||
if t.validator is not None:
|
||||
@ -143,9 +150,9 @@ class TicketStore(UUIDModel):
|
||||
raise TicketStore.InvalidTicket('Does not exists')
|
||||
|
||||
@staticmethod
|
||||
def revalidate(uuid, validity=None):
|
||||
def revalidate(uuid, validity=None, owner=None):
|
||||
try:
|
||||
t = TicketStore.objects.get(uuid=uuid)
|
||||
t = TicketStore.objects.get(uuid=uuid, owner=owner)
|
||||
t.stamp = getSqlDatetime()
|
||||
if validity is not None:
|
||||
t.validity = validity
|
||||
@ -166,4 +173,4 @@ class TicketStore(UUIDModel):
|
||||
else:
|
||||
validator = None
|
||||
|
||||
return 'Ticket id: {}, Stamp: {}, Validity: {}, Validator: {}, Data: {}'.format(self.uuid, self.stamp, self.validity, validator, pickle.loads(self.data))
|
||||
return 'Ticket id: {}, Secure: {}, Stamp: {}, Validity: {}, Validator: {}, Data: {}'.format(self.uuid, self.owner, self.stamp, self.validity, validator, pickle.loads(self.data))
|
||||
|
Loading…
Reference in New Issue
Block a user