Пример #1
0
    def is_logged_in(self, body: Dict[str, any],
                     access_token: Union[str]) -> Response:
        """
        Checks whether user is logged in or not.

        Args:
            body:
            access_token:

        Returns:

        """

        _, key, iv = api.decrypt_request_data(body=body)

        session = Sessions()

        data = {
            "Success": True,
            "is_logged_in": session.is_active(self.username)
        }
        return api.response_data(data=data,
                                 message="",
                                 status_code=200,
                                 key=key,
                                 iv=iv)
Пример #2
0
    def __call__(self, environ, start_response):
        request = Request(environ)
        request_endpoint = request.split(-1)
        if request_endpoint in ["register", "login", "get_rsa_key"]:
            return self.app(environ, start_response)

        access_token: str = request.headers.get("access_token")
        content_length = int(environ.get("CONTENT_LENGTH"))
        request_body = environ["wsgi.input"].read(content_length).decode()
        request_body: Dict[str, any] = json.loads(json.loads(request_body))

        request_data, key, iv = api_controller.decrypt_request_data(body=request_body)

        if access_token is None:
            data = {"success": False}
            response = api_controller.response_data(
                data=data, message="Unauthorized", status_code=401, key=key, iv=iv
            )
            return response(environ, start_response)

        access_token: str = base64.decodebytes(
            bytes(access_token, encoding="utf-8")
        ).decode()
        username: str = access_token.split("+")[-1]
        user: User = Users().get_user(username=username)

        if user is None:
            data = {"success": False}
            response = api_controller.response_data(
                data=data, message="Unauthorized", status_code=401, key=key, iv=iv
            )
            return response(environ, start_response)

        if request_endpoint in ["grant_access", "revoke_access"]:
            if not user.admin:
                data = {"success": False}
                response = api_controller.response_data(
                    data=data, message="Unauthorized", status_code=401, key=key, iv=iv
                )
                return response(environ, start_response)

            user_password: str = request_data["password"]
            password_hash: bytes = utils.hash_data(
                data=user_password, salt=user.salt_for_password
            )

            if password_hash != user.password:
                data = {"success": False}
                response = api_controller.response_data(
                    data=data,
                    message="Authorization Failed",
                    status_code=401,
                    key=key,
                    iv=iv,
                )
                return response(environ, start_response)

        return self.app(environ, start_response)
Пример #3
0
    def revoke_all(body: Dict[str, any], access_token: str) -> Response:
        """
        Revokes all access of the specified user.

        :param body:
        :param access_token:
        :return:
        """

        data, key, iv = api.decrypt_request_data(body=body)
        grantee_username: str = data["username"]
        admin_password: str = data["password"]
        ssh_key: bytes = get_ssh_key(password=admin_password)

        if admin_ssh_key == b"":
            data = {"success": False}
            return api.response_data(
                data=data,
                message="You haven't generated your key pair",
                status_code=409,
                key=key,
                iv=iv,
            )

        grantee_user: User = UserModel().get_user(username=grantee_username)

        if grantee_user is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="The user you are trying to revoke access from does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        current_ips = AccessControlModel().get_all_ips(username=username)
        if current_ips is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="Username does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        for ip_address in current_ips:
            tasks.revoke_access.delay(username, ssh_key, ip_address)

        data = {"success": True}
        return api.response_data(
            data=data, message="Access will be revoked", status_code=200, key=key, iv=iv
        )
Пример #4
0
    def register(self, body: Dict[str, any]) -> Response:
        """
        Generates the secrets of the user based on the password. Hashes the password using SAH256 and stores the
        generated information in DynamoDB.

        :param body:
        :return: True/False for success/failure
        """

        data, key, iv = api.decrypt_request_data(body=body)
        self.set_attributes(username=data["username"],
                            password=data["password"],
                            name=data["name"])

        if self.user.exists(username=self.username):
            data = {"success": False}
            return api.response_data(data=data,
                                     message="Username is taken",
                                     status_code=409,
                                     key=key,
                                     iv=iv)

        self.secrets.generate_secrets(password=str(self.__password))
        self.__password = utils.hash_data(self.__password,
                                          self.secrets.salt_for_password)
        user_is_admin = True

        if self.user.admin_exists():
            user_is_admin = False

        user_created = self.user.create(
            name=self.name,
            username=self.username,
            password=self.__password,
            admin=user_is_admin,
            encrypted_dek=self.secrets.dek,
            iv_for_dek=self.secrets.iv_for_dek,
            salt_for_dek=self.secrets.salt_for_dek,
            iv_for_kek=self.secrets.iv_for_kek,
            salt_for_kek=self.secrets.salt_for_kek,
            salt_for_password=self.secrets.salt_for_password,
        )

        data = {"success": user_created}
        return api.response_data(data=data,
                                 message="User created",
                                 status_code=200,
                                 key=key,
                                 iv=iv)
Пример #5
0
    def logout(self, body: Dict[str, any]):
        """
        Handles user logout.

        Args:
            body:
            access_token:

        Returns:

        """

        _, key, iv = api.decrypt_request_data(body=body)

        if self.user.exists(username=self.username):
            session = Sessions()

            if not session.exists(username=self.username):
                data = {"success": False}
                return api.response_data(
                    data=data,
                    message="User not logged in",
                    status_code=400,
                    key=key,
                    iv=iv,
                )
            else:
                if session.deactivate_session(username=self.username):
                    data = {"success": True}
                    return api.response_data(
                        data=data,
                        message="Log out successful",
                        status_code=200,
                        key=key,
                        iv=iv,
                    )

        data = {"success": False}
        return api.response_data(
            data=data,
            message="User not found",
            status_code=404,
            key=key,
            iv=iv,
        )
    def get_private_key(self, body: Dict[str, any]) -> Response:
        """
        Gets the encrypted SSH key and decrypts it.

        :param body:
        :return:
        """

        request_data, key, iv = api.decrypt_request_data(body=body)

        user = Users().get_user(username=self.username)
        if user is None:
            data = {
                "success": False,
            }
            return api.response_data(
                data=data, message="Unauthorized", status_code=401, key=key, iv=iv
            )

        user_key: PrivateKey = user.private_key
        if user_key is None:
            data = {"success": False}

            return api.response_data(
                data=data,
                message="User's key does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        self.password = request_data["password"]
        self.set_user_secrets()
        self.ssh_encrypted_key = user_key.encrypted_private_key
        self.ssh_key = self.decrypt(ciphertext=self.ssh_encrypted_key)

        data = {"success": False, "ssh_key": self.ssh_key}

        return api.response_data(data=data, message="", status_code=200, key=key, iv=iv)
Пример #7
0
    def is_admin(self, body: Dict[str, any]) -> Response:
        """
        Checks whether user is admin or not.

        Args:
            body:
            access_token:

        Returns:

        """

        data, key, iv = api.decrypt_request_data(body=body)

        user = self.user.get_user(username=self.username)

        data = {"success": True, "is_admin": user is not None and user.admin}
        return api.response_data(data=data,
                                 message="",
                                 status_code=200,
                                 key=key,
                                 iv=iv)
Пример #8
0
    def login(self, body: Dict[str, any]) -> Response:
        """
        Handles user login.

        :param body:
        :return: access token upon successful login
        """

        data, key, iv = api.decrypt_request_data(body=body)
        self.set_attributes(username=data["username"],
                            password=data["password"],
                            name="")

        user: User = self.user.get_user(self.username)

        if user is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="User does not exists",
                status_code=401,
                key=key,
                iv=iv,
            )

        user_data = user
        self.set_attributes(username=self.username,
                            password=self.__password,
                            name=user_data.name)
        secrets = {
            "encryptedDek": user_data.encrypted_dek,
            "ivForDek": user_data.iv_for_dek,
            "saltForDek": user_data.salt_for_dek,
            "ivForKek": user_data.iv_for_kek,
            "saltForKek": user_data.salt_for_kek,
            "saltForPassword": user_data.salt_for_password,
        }
        self.secrets.set_secrets(secrets=secrets)

        if user_data.password == utils.hash_data(
                data=self.__password, salt=self.secrets.salt_for_password):
            access_token: str = uuid.uuid4().hex + "+" + self.username
            access_token = (base64.encodebytes(
                bytes(access_token, encoding="utf-8")).decode().strip())
            session = Sessions()

            res = True
            if not session.exists(username=self.username):
                res = session.create(username=self.username,
                                     access_token=access_token)
            else:
                res = session.activate_session(username=self.username)

            if res:
                data = {"success": True, "access_token": access_token}
                return api.response_data(
                    data=data,
                    message="Login successful",
                    status_code=200,
                    key=key,
                    iv=iv,
                )
        else:
            data = {
                "success": False,
            }
            return api.response_data(
                data=data,
                message="Password does not match",
                status_code=401,
                key=key,
                iv=iv,
            )
Пример #9
0
    def revoke_access(body: Dict[str, any]) -> Response:
        """
        Revokes access to the list of IP addresses to the specifies username,

        :param body:
        :param access_token:
        :return:
        """

        data, key, iv = api.decrypt_request_data(body=body)
        grantee_username: str = data["username"]
        admin_password: str = data["password"]
        connection_strings: List[str] = data["connection_strings"]
        ip_addresses: List[str] = [
            connection_string.split("@")[1] for connection_string in connection_strings
        ]
        admin_ssh_key: bytes = get_ssh_key(password=admin_password)

        if admin_ssh_key == b"":
            data = {"success": False}
            return api.response_data(
                data=data,
                message="You haven't generated your key pair",
                status_code=409,
                key=key,
                iv=iv,
            )

        grantee_user: User = UserModel().get_user(username=grantee_username)

        if grantee_user is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="The user you are trying to revoke access from does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        current_ips: List[str] = grantee_user.access_control.ip_addresses
        if ip_addresses not in current_ips:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="The user already does not has access.",
                status_code=409,
                key=key,
                iv=iv,
            )

        if current_ips is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="Username does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        for connection_string in connection_strings:
            ip_address = connection_string.split("@")[1]
            remote_username = connection_string.split("@")[0]
            if ip_address in current_ips:
                tasks.revoke_access.delay(
                    grantee_username, admin_ssh_key, ip_address, remote_username
                )

        data = {"success": True}
        return api.response_data(
            data=data, message="Access will be revoked", status_code=200, key=key, iv=iv
        )
Пример #10
0
    def grant_access(self, body: Dict[str, any]) -> Response:
        """
        Grants access to the given ip addresses.

        Args:
            body (Dict[str, any]):
        """

        data, key, iv = api.decrypt_request_data(body=body)
        grantee_username: str = data["username"]
        admin_password: str = data["password"]
        connection_strings: List[str] = data["connection_strings"]
        ip_addresses: List[str] = [
            connection_string.split("@")[1] for connection_string in connection_strings
        ]
        admin_ssh_key: bytes = self.get_ssh_key(password=admin_password)

        if admin_ssh_key == b"":
            data = {"success": False}
            return api.response_data(
                data=data,
                message="You haven't generated your key pair",
                status_code=409,
                key=key,
                iv=iv,
            )

        grantee_user: User = UserModel().get_user(username=grantee_username)

        if grantee_user is None:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="The user you are trying to give access does not exist",
                status_code=404,
                key=key,
                iv=iv,
            )

        current_ips: List[str] = grantee_user.access_control.ip_addresses
        if ip_addresses in current_ips:
            data = {"success": False}
            return api.response_data(
                data=data,
                message="The user already has access.",
                status_code=409,
                key=key,
                iv=iv,
            )

        for connection_string in connection_strings:
            ip_address = connection_string.split("@")[1]
            remote_username = connection_string.split("@")[0]
            if ip_address not in current_ips:
                tasks.grant_access.delay(
                    grantee_username, admin_ssh_key, ip_address, remote_username
                )

        return api.response_data(
            data=data, message="Access will be granted", status_code=200, key=key, iv=iv
        )