Esempio n. 1
0
 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)
Esempio n. 2
0
    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)
Esempio n. 7
0
    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