Коробка с питоном
530 subscribers
49 photos
128 links
Заметки от Python-разработчика: сниппеты, обзоры пакетов, новости и другая полезная информация.
Download Telegram
💡 asyncssh - асинхронный ssh клиент и не только

👀 Если вы будете искать асинхронную альтернативу paramiko (это реализация SSHv2 на чистом питоне), то скорее всего наткнетесь на asyncssh - paramiko из под коробки не умеет в асинк.

Вообще, зачем он нужен, тем более для python? А давайте посмотрим, какие примеры есть у asyncssh:

➡️ Обычный клиент, который заходит на сервер и отправляет туда команду. Полезно, когда хочется сделать какой-то инструмент автоматизации, который заходит на кучу серверов и что-то на них выполняет (давайте представим что Ansible не существует, ладно?).
Еще у меня встречался кейс, когда есть какая-то штука, которая ставится на сервер, у которой нет API но есть CLI-утилита. Вот такие библиотеки здорово выручают.
➡️ Порт-форвардинг. Например, когда я писал диплом, у меня был скрипт который форвардил нужные для меня сервисы (ума не хватало впн поднять, да) на выданном мне хосте.
➡️ SFTP-клиент. Даже готовый класс есть, бери и накидывай поверх него какой-то гуй.
В последний раз, кстати, я такую штуку использовал для того, чтобы выкачивать бекапы. Был только доступен SFTP, поэтому мы выживали как могли...
➡️ А можно еще свой ssh сервер бахнуть. Например чтобы сделать простой honeypot для ботов, посмотреть что они будут делать на серваке.
➡️ Ну и закончу, пожалуй, sftp сервером. Можно написать небольшой сервер, c кастомной логикой.
Однажды я участвовал в одной CTF, в одной из тасок надо было за 5 команд получить доступ к флагу.
Количество попыток было ограничено. Угадаете, на чем было реализовано?

✏️ В общем, asyncssh это не просто "асинхроннй ssh-клиент, ну там чтобы командики отправить". Тут столько возможностей и идей для использования - бери и пили!

Документация | Github | PyPi
#библиотека
Please open Telegram to view this post
VIEW IN TELEGRAM
👏6🔥3🤔31
🔩 Если вам понадобится в рантайме поменить тип принимаемого объекта в роуте FastAPI, вот вам небольшой рецепт.

😆 Для одного проекта я решил сделать плагин-систему, которая автоматически регистрирует python-файлы и добавляет эндпоинты в API написанном на FastAPI. Так как я использую OpenAPI, очень хочется, чтобы принимаемые и возвращаемые типы отображались в нём корректно.

➡️Допустим, есть у меня вот такой код, создающий эндпоинты в зависимости от переданного Action:
class Action[ReqT, RespT](Protocol):
name: str
request_schema: Type[ReqT] # тип который мы будем принимать
response_schema: Type[RespT] # тип который мы будем возвращать
interact: Callable[[ReqT], Coroutine[Any, Any, RespT]]

def create_action_handler(action: Action):
# какой-то код
async def action_endpoint(entity_id: int, data: dict[str, Any]) -> Any:
# какой-то код
return await action.interact(server, data)
return action_endpoint


➡️ А вот так я добавляю нашу ручку в роутер:
def add_action_route(router: APIRouter, action: Action):
handler = create_action_handler(action)
router.post(
f"/plugins/{action.name}",
response_model=action.response_schema, # установим схему для ответа
)(handler)


Схему для ответа я установил при регистрации нашего эндпоинта в response_model. А что делать с data, тип которого должен быть не dict[str, Any] а action.request_schema

ℹ️ Для начала, я подумал, что раз FastAPI строит доку из аннотаций, наверное я смогу поменять аннотации и на этом дело сделано:
handler = create_action_handler(action)
handler.__annotations__["data"] = action.request_schema

Но это не помогло - аннотации поменялись, а вот схема - нет 🍺 !

😱 Оказывается, FastAPI не использует аннотации, а использует запеченные Signature, которые собираются из Dependency. При чем, в понимании FastAPI, dependency не только источник каких-то функций, а еще и наших схем. А дальше он из них и строит OpenAPI.

Зная это нам остается только одно - изменить signature перед регистрацией роута 😱:

sig = inspect.signature(handler) # достаем сигнатуру
new = []
for p in sig.parameters.values():
if p.name == "data": # находим нашу data
p = p.replace(annotation=action.request_schema) # меняем
new.append(p)
handler.__signature__ = sig.replace(parameters=new) # записываем новую сигнатуру


Вуаля! Теперь в OpenAPI будет указанная в action.request_schema схема 👏

#fastapi #рецепт
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯4🔥3