mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -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
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseBadRequest
|
||||
|
||||
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.viewsets import ModelViewSet, ViewSet
|
||||
|
||||
from secrets.exceptions import InvalidSessionKey
|
||||
from secrets.exceptions import InvalidKey
|
||||
from secrets.filters import SecretFilter
|
||||
from secrets.models import Secret, SecretRole, SessionKey, UserKey
|
||||
from utilities.api import WritableSerializerMixin
|
||||
@ -84,7 +83,7 @@ class SecretViewSet(WritableSerializerMixin, ModelViewSet):
|
||||
try:
|
||||
sk = SessionKey.objects.get(userkey__user=request.user)
|
||||
self.master_key = sk.get_master_key(session_key)
|
||||
except (SessionKey.DoesNotExist, InvalidSessionKey):
|
||||
except (SessionKey.DoesNotExist, InvalidKey):
|
||||
raise ValidationError("Invalid session key.")
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
@ -140,6 +139,9 @@ class GetSessionKeyViewSet(ViewSet):
|
||||
{
|
||||
"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]
|
||||
|
||||
@ -163,14 +165,26 @@ class GetSessionKeyViewSet(ViewSet):
|
||||
if master_key is None:
|
||||
return HttpResponseBadRequest(ERR_PRIVKEY_INVALID)
|
||||
|
||||
# Delete the existing SessionKey for this user if one exists
|
||||
SessionKey.objects.filter(userkey__user=request.user).delete()
|
||||
try:
|
||||
current_session_key = SessionKey.objects.get(userkey__user_id=request.user.pk)
|
||||
except SessionKey.DoesNotExist:
|
||||
current_session_key = None
|
||||
|
||||
# Create a new SessionKey
|
||||
sk = SessionKey(userkey=user_key)
|
||||
sk.save(master_key=master_key)
|
||||
encoded_key = base64.b64encode(sk.key)
|
||||
# b64decode() returns a bytestring under Python 3
|
||||
if current_session_key and request.GET.get('preserve_key', False):
|
||||
|
||||
# Retrieve the existing session key
|
||||
key = current_session_key.get_session_key(master_key)
|
||||
|
||||
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):
|
||||
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
|
||||
|
@ -13,7 +13,7 @@ from django.utils.encoding import force_bytes, python_2_unicode_compatible
|
||||
from dcim.models import Device
|
||||
from utilities.models import CreatedUpdatedModel
|
||||
|
||||
from .exceptions import InvalidSessionKey
|
||||
from .exceptions import InvalidKey
|
||||
from .hashers import SecretValidationHasher
|
||||
|
||||
|
||||
@ -221,13 +221,24 @@ class SessionKey(models.Model):
|
||||
|
||||
# Validate the provided session key
|
||||
if not check_password(session_key, self.hash):
|
||||
raise InvalidSessionKey()
|
||||
raise InvalidKey("Invalid session key")
|
||||
|
||||
# Decrypt master key using provided session key
|
||||
master_key = xor_keys(session_key, bytes(self.cipher))
|
||||
|
||||
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
|
||||
class SecretRole(models.Model):
|
||||
|
Loading…
Reference in New Issue
Block a user