def create_from_plaintext(cls: Type[T], plaintext_passphrase: str) -> T: """Return a Secret created based on the supplied plaintext passphrase""" if not isinstance(plaintext_passphrase, str): raise NozomiError('Passphrases must be strings', 400) salt = Salt.create() hashed_passphrase = cls._compute_hash(plaintext_passphrase, salt) return cls(salt, hashed_passphrase)
def __init__(self, headers: Headers, request_body: bytes, max_content_length: int = 10000) -> None: length = headers.value_for('content-length') if length is None: raise BadRequest('No content-length header found in your request.') try: content_length = int(length) except ValueError: raise BadRequest('Invalid content-length header value') if content_length > max_content_length: raise NozomiError( 'Content too large, max: {s}'.format( s=str(max_content_length)), HTTPStatusCode.PAYLOAD_TOO_LARGE.value) try: string_data = request_body.decode('utf-8') except Exception: raise BadRequest('Unable to decode the body of your request with t\ he UTF-8 character set. UTF-8 required.') content_type = headers.value_for('content-type') if content_type is None: raise BadRequest('Could not find a content-type header in your req\ uest.') try: content_type_value = content_type.lower().split(';')[0] except Exception: raise BadRequest('Unable to parse your request\'s content-type hea\ der.') if content_type_value == 'application/json': try: json_data = json.loads(string_data) except Exception: raise BadRequest('Unable to parse your request body as json. P\ lease check the syntax of your request body.') return super().__init__(raw=json_data) if content_type_value == 'application/xml': try: xml_data = XML.xmlstring_to_data(string_data) except Exception: raise BadRequest('Unable to parse your request body as xml. Pl\ ease check the syntax of your request body.') return super().__init__(raw=xml_data) raise BadRequest('Invalid content type. Valid content types are applic\ ation/json and application/xml only.')
def require_from_headers(cls: Type[T], headers: Optional[Headers], datastore: Datastore, configuration: Configuration, request_may_change_state: bool = True) -> T: session = cls.from_headers(headers=headers, datastore=datastore, configuration=configuration, request_may_change_state=True) if session is None: raise NozomiError('Not authenticated', 401) return session
def from_headers(cls: Type[T], headers: Headers, boundary_ip_header: str, debug: bool = False, debug_address: Optional[str] = None) -> T: if debug is True: assert isinstance(debug_address, str) return cls(debug_address) addresses = headers.getlist(boundary_ip_header) # We presume that headers are being set by HAProxy. If these checks # fail, HAProxy is not configured properly. if len(addresses) != 1: raise NozomiError('Internal error', HTTPStatusCode.INTERNAL_ERROR) if len(addresses[0].split(',')) != 1: raise NozomiError('Internal error', HTTPStatusCode.INTERNAL_ERROR) return cls(addresses[0])
def create(cls: Type[T], provided_email: str, provided_plaintext_secret: str, ip_address: IpAddress, datastore: Datastore, perspective: Perspective, configuration: Configuration) -> T: """Return a newly minted Session""" secret = Secret.retrieve_for_email(provided_email, datastore) if secret is None: raise NozomiError('Invalid credentials', 401) secret_check = secret.matches(provided_plaintext_secret) if secret_check is False: raise NozomiError('Invalid credentials', 401) assert secret_check is True # Redundant sanity check assert secret.agent_id is not None input_data = { 'session_id': RandomNumber(128).urlsafe_base64.replace('=', ''), 'session_key': RandomNumber(192).urlsafe_base64.replace('=', ''), 'api_key': RandomNumber(192).urlsafe_base64.replace('=', ''), 'email_address': provided_email, 'ip_address': ip_address, 'agent_id': secret.agent_id, 'seconds_to_live': configuration.session_seconds_to_live, 'perspective': perspective.perspective_id } query = cls._load_query(cls._Q_CREATE) try: result = query.execute(datastore, input_data) except Exception: datastore.rollback() raise datastore.commit() return cls.decode(result)
def create_with_request_data(cls: Type[T], data: Any, ip_address: IpAddress, datastore: Datastore, perspective: Perspective) -> T: """Return a newly minted Session""" assert isinstance(ip_address, IpAddress) assert isinstance(perspective, Perspective) if not isinstance(data, dict): raise BadRequest('Expected a key/value object (dict)') try: provided_plaintext_secret = data['secret'] provided_email = data['email'] except KeyError as error: raise BadRequest('Missing key ') raise NozomiError('Missing key ' + str(error.args[0]), 400) return cls.create(provided_email=provided_email, provided_plaintext_secret=provided_plaintext_secret, ip_address=ip_address, datastore=datastore, perspective=perspective)
def value_for(self, key: str) -> Optional[str]: """ Return the value of a supplied header key, or None if no value exists for that key. """ value = self._raw.get(key) if value is None: for item in self._raw: if isinstance(item, tuple) and len(item) > 1: if isinstance(item[0], str): if item[0].lower() == key.lower(): return item[1] if isinstance(item, str) and item.lower() == key.lower(): return self._raw[key.lower()] return None if not isinstance(value, str): raise NozomiError( self._TYPE_ERROR.format(k=key, t=str(type(value))), HTTPStatusCode.BAD_REQUEST) return value