mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -06:00
Closes #985: Added preserve_key to get-session-key endpoint
This commit is contained in:
parent
cf3e7f90d6
commit
5d022a575a
@ -1,7 +1,6 @@
|
|||||||
import base64
|
import base64
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.http import HttpResponseBadRequest
|
from django.http import HttpResponseBadRequest
|
||||||
|
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
@ -9,7 +8,7 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ModelViewSet, ViewSet
|
from rest_framework.viewsets import ModelViewSet, ViewSet
|
||||||
|
|
||||||
from secrets.exceptions import InvalidSessionKey
|
from secrets.exceptions import InvalidKey
|
||||||
from secrets.filters import SecretFilter
|
from secrets.filters import SecretFilter
|
||||||
from secrets.models import Secret, SecretRole, SessionKey, UserKey
|
from secrets.models import Secret, SecretRole, SessionKey, UserKey
|
||||||
from utilities.api import WritableSerializerMixin
|
from utilities.api import WritableSerializerMixin
|
||||||
@ -84,7 +83,7 @@ class SecretViewSet(WritableSerializerMixin, ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
sk = SessionKey.objects.get(userkey__user=request.user)
|
sk = SessionKey.objects.get(userkey__user=request.user)
|
||||||
self.master_key = sk.get_master_key(session_key)
|
self.master_key = sk.get_master_key(session_key)
|
||||||
except (SessionKey.DoesNotExist, InvalidSessionKey):
|
except (SessionKey.DoesNotExist, InvalidKey):
|
||||||
raise ValidationError("Invalid session key.")
|
raise ValidationError("Invalid session key.")
|
||||||
|
|
||||||
def retrieve(self, request, *args, **kwargs):
|
def retrieve(self, request, *args, **kwargs):
|
||||||
@ -140,6 +139,9 @@ class GetSessionKeyViewSet(ViewSet):
|
|||||||
{
|
{
|
||||||
"session_key": "+8t4SI6XikgVmB5+/urhozx9O5qCQANyOk1MNe6taRf="
|
"session_key": "+8t4SI6XikgVmB5+/urhozx9O5qCQANyOk1MNe6taRf="
|
||||||
}
|
}
|
||||||
|
|
||||||
|
This endpoint accepts one optional parameter: `preserve_key`. If True and a session key exists, the existing session
|
||||||
|
key will be returned instead of a new one.
|
||||||
"""
|
"""
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
@ -163,14 +165,26 @@ class GetSessionKeyViewSet(ViewSet):
|
|||||||
if master_key is None:
|
if master_key is None:
|
||||||
return HttpResponseBadRequest(ERR_PRIVKEY_INVALID)
|
return HttpResponseBadRequest(ERR_PRIVKEY_INVALID)
|
||||||
|
|
||||||
# Delete the existing SessionKey for this user if one exists
|
try:
|
||||||
SessionKey.objects.filter(userkey__user=request.user).delete()
|
current_session_key = SessionKey.objects.get(userkey__user_id=request.user.pk)
|
||||||
|
except SessionKey.DoesNotExist:
|
||||||
|
current_session_key = None
|
||||||
|
|
||||||
# Create a new SessionKey
|
if current_session_key and request.GET.get('preserve_key', False):
|
||||||
sk = SessionKey(userkey=user_key)
|
|
||||||
sk.save(master_key=master_key)
|
# Retrieve the existing session key
|
||||||
encoded_key = base64.b64encode(sk.key)
|
key = current_session_key.get_session_key(master_key)
|
||||||
# b64decode() returns a bytestring under Python 3
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Create a new SessionKey
|
||||||
|
SessionKey.objects.filter(userkey__user=request.user).delete()
|
||||||
|
sk = SessionKey(userkey=user_key)
|
||||||
|
sk.save(master_key=master_key)
|
||||||
|
key = sk.key
|
||||||
|
|
||||||
|
# Encode the key using base64. (b64decode() returns a bytestring under Python 3.)
|
||||||
|
encoded_key = base64.b64encode(key)
|
||||||
if not isinstance(encoded_key, str):
|
if not isinstance(encoded_key, str):
|
||||||
encoded_key = encoded_key.decode()
|
encoded_key = encoded_key.decode()
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class InvalidSessionKey(Exception):
|
class InvalidKey(Exception):
|
||||||
"""
|
"""
|
||||||
Raised when the a provided session key is invalid.
|
Raised when a provided key is invalid.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
@ -13,7 +13,7 @@ from django.utils.encoding import force_bytes, python_2_unicode_compatible
|
|||||||
from dcim.models import Device
|
from dcim.models import Device
|
||||||
from utilities.models import CreatedUpdatedModel
|
from utilities.models import CreatedUpdatedModel
|
||||||
|
|
||||||
from .exceptions import InvalidSessionKey
|
from .exceptions import InvalidKey
|
||||||
from .hashers import SecretValidationHasher
|
from .hashers import SecretValidationHasher
|
||||||
|
|
||||||
|
|
||||||
@ -221,13 +221,24 @@ class SessionKey(models.Model):
|
|||||||
|
|
||||||
# Validate the provided session key
|
# Validate the provided session key
|
||||||
if not check_password(session_key, self.hash):
|
if not check_password(session_key, self.hash):
|
||||||
raise InvalidSessionKey()
|
raise InvalidKey("Invalid session key")
|
||||||
|
|
||||||
# Decrypt master key using provided session key
|
# Decrypt master key using provided session key
|
||||||
master_key = xor_keys(session_key, bytes(self.cipher))
|
master_key = xor_keys(session_key, bytes(self.cipher))
|
||||||
|
|
||||||
return master_key
|
return master_key
|
||||||
|
|
||||||
|
def get_session_key(self, master_key):
|
||||||
|
|
||||||
|
# Recover session key using the master key
|
||||||
|
session_key = xor_keys(master_key, bytes(self.cipher))
|
||||||
|
|
||||||
|
# Validate the recovered session key
|
||||||
|
if not check_password(session_key, self.hash):
|
||||||
|
raise InvalidKey("Invalid master key")
|
||||||
|
|
||||||
|
return session_key
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class SecretRole(models.Model):
|
class SecretRole(models.Model):
|
||||||
|
Loading…
Reference in New Issue
Block a user