TGViewer
Channel Public Channel
Артем Лещев | ИТ

Артем Лещев | ИТ

@asleshchev

Авторский ИТ-блог на разные темы. Тут много чего.

@artem_leshchev — аффтор, ведущий системный аналитик на проекте банка ВТБ.
Subscribers
71
Photos
19
Videos
1
Links
65
Recent Posts 20 shown
Post #145 45
🛡 XSS-атака и аспекты безопасного API.

Когда я 3-4 года назад работал менеджером ИТ-проектов в веб-студии, то разработал корпоративный шаблон ТЗ. Эх, ностальгия... Среди требований ИБ я прописал, что не допускается проведение различных инъекций:
SQL (в канале было опубликовано 2 поста), JS и т.д.
Разберем JS-инъекцию на примере XSS-атаки.

🔪 XSS (Cross-Site Scripting, ЭксЭсЭс, Межсайтовый скриптинг). Уязвимость в веб-приложениях, которая позволяет внедрять и исполнять произвольный скрипт (обычно JS).

Часто проверяют есть ли уязвимость вызывая функцию alert. alert выводит на экран модальное окно с сообщением. Если функция вызовется, значит уязвимость есть.

Есть 3 основных разновидности XSS:

🔴 Reflected (Отраженная).

Вредоносный скрипт «отражается» от веб-приложения, т.е. сервер возвращает (отражает) этот код обратно в ответе. Например, в сообщении об ошибке, результатах поиска или статусе).

В самом простом задании на Portswigger на эту уязвимость нужно вставить в строку поиска:
<script>alert(1)</script>

🔴 Stored (хранимая).

Более опасный вариант. Вредоносный скрипт «сохраняется» на сервере или в БД. Часто используется там, где человек вводит информацию, и она видна многим: личка и беседы, комменты, отзывы...

В самом простом задании на Portswigger на эту уязвимость нужно опубликовать <script>alert(1)</script> в поле ввода текста комментария.

🔴 DOM-based (на основе DOM-дерева).

Угроза возникает, когда на клиенте JS обрабатывает данные из ненадежного источника небезопасным способом, обычно записывая данные обратно в DOM. То есть значения вставляются "как есть" в код страницы. Значит можно сформировать URL, где параметры будут содержать не обычные значения, а вредоносный скрипт. Он вставится в форму и выполнится.

В самом простом задании на Portswigger предлагается:

1. Написать что-то в строку поиска, например, rocknroll. Отправится GET-запрос с передачей квери-параметра /?search=rocknroll.
2. Открываем инспектором сформированное DOM-дерево. В поиске по дереву ищет rocknroll.
Видим:

<script>
function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
trackSearch(query);
}
</script>
<img src="/resources/images/tracker.gif?searchTerms=rocknroll">


3. Ага. Произошла подстановка в <img src="">.
А что если мы закроем этот тэг, и после него вызовем что-то иное?
4. Передаем в строку поиска (можно сразу в адресную строку браузера):
"><svg onload=alert(1)>

Получится:
<img src="/resources/images/tracker.gif?searchTerms="><svg onload=alert(1)>

что закроет тэг <img> и вызовет функцию alert.

А есть еще XSS-варианты?

В замечательной статье на SecurityLab описаны разные виды атак и даны рекомендации по защите.

Еще есть: Blind, Mutated, Polyglot, Contextual.

🤡 И даже Self-XSS, когда мошенник убеждает пользователя выполнить в консоле скрипт, который накрутит ему кучу денег/токенов/еще чего-то.

Хорошая статья на Хабре.

Как защититься?

На английском языке подробно написано здесь.
В основном это:
1. Валидировать и экранировать данные ввода/вывода.
2. Настроить сервер таким образом, чтобы в ответах он отправлял HTTP-заголовок Content-Security-Policy. Он задает белый список источников для загрузки скриптов, стилей и прочих ресурсов.

⚡️ Ограничит источники контента только исходным сервером (без поддоменов):

Content-Security-Policy: default-src 'self'

⚡️ Разрешает получение контента с доверенного домена и всех его поддоменов:

Content-Security-Policy: default-src 'self'*.trusted.com

Больше примеров в доках mdm.

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
Post #144 55
Есть у меня пара знакомых программистов, которые работают с железом. На мой вопрос — кто и как вам пишет тз? — они грустно отвечали, что никто и никак 🫠. "Разбирайся сам, надо чтобы эта хрень заработала".

В голове сложился паттерн, что системные аналитики отсутствуют на низкоуровневых проектах. Железячники и некоторые системщики работают без постановок от аналитиков. Но иногда исключения есть. Давайте посмотрим, какие требования к системным аналитикам предъявляются в компании YADRO.
YADRO — российская технологическая компания, созданная в 2014 году и объединяющая направления разработки и производства вычислительных платформ, систем обработки и хранения данных, телекоммуникационного и сетевого оборудования, персональных и «умных» устройств, микропроцессорных ядер и fabless-разработку микропроцессоров.
Сразу оговорюсь, что YADRO нанимают и software-аналитиков тоже.
Но в данном посте посмотрим требования к тем, кто занимается hardware или около.

✔️ Возьмем вакансию на системного аналитика, закрытую полгода назад, 20 января 2026. Посмотрите, какая жемчужина среди типовых задач затесалась:
— Разработка спецификации требований для составных частей multi-RAT базовой станции, а также сервисов, необходимых для запуска, обновления и обмена сообщениями других SW компонентов базовой станции;

❓ А что по общим требованиям?
Что мы ожидаем от будущего члена команды:

— Уверенное понимание технологий и архитектуры программных продуктов;
— Знания сетевых протоколов, включая IP, DNS, DHCP, VRRP
— Знания/опыта работы с решениями в области синхронизации, PTP, Glonass, GPS, SyncE, NTP
— Опыта работы с различными сборками Linux (Debian, Red Hat, ...)
— Знания процесса загрузки Linux, PXE, BIOS/UEFI, systemd
— Знания процессоров семейства Intel/AMD, x86, ARM
— Знания в области схемотехники
— Знания физических интерфейсов (PCIe, Ethernet, I2C,...)
— Знания протоколов/интерфейсов, в том числе для взаимодействия с BMC (ipmi, Redfish, ...)
— Опыт написания технической документации.
— Владение английским языком на уровне чтения и написания технической документации.

Дополнительно приветствуем:

— Знание технологий контейнеризации и оркестрирования
— Опыт администрирования, в т.ч. инсталляция, конфигурирование и обслуживание
— Работа с драйверами, оптимизация производительности
— Проектирования компьютеров/систем на базе x86, ARM, RISC
— Практический опыт схемотехнического проектирования
— Опыт программирования на Go (Golang), bash, Python и/или C/C++;
— Опыт программирования/отладки микроконтроллеров, плис
— Опыт работы, знания мобильных телекоммуникационных систем GSM/LTE/5G или знания/опыт работы в смежных областях (Tetra,...)
❓ Какими знаниями из перечисленного может обладать обычный СА?

Ну... IP, DNS, DHCP.

Ну сеньоры шарят за оптимизацию производительности. Но не драйверов.

Ну инсталляция и конфигурирование некоторого ПО.

Ну код на Python почитать.

Но все остальное тянет на редкую квалификацию.

✔️ А вот требования по текущей вакансии на СА:
— Обеспечение экспертной декомпозиции требований для BIOS / BMC / Firmware команды разработки, включая формирование и обновление технических требований к продукту, декомпозируя требования от владельца продукта и/или системного архитектора, L3 поддержки, с учётом имеющегося и запланированного функционала, для нескольких параллельных потоков.

Мы ожидаем от будущего члена команды:
— Знание hw архитектуры и общих принципов создания серверов в железе.
— Базовые знания основ Linux.
— Базовые знания сетевых технологий (LAN, SAN-сети, ICMP/ SNMP / IPMI / Redfish).
— Навыки анализа и сбора сложных бизнес-требований и требований к оборудованию.
— Опыт создания детальных технических заданий в области инфраструктуры.
— Умение ясно доносить сложную техническую информацию

Приветствуется:
— Базовое понимание архитектуры BIOS/UEFI и BMC.


Стоит ли вникать в эти вещи software-аналитикам? Зависит от задачи.
❌ Если перекладывать json, то нет. Хватит сетей и протоколов прикладного уровня.
✔️ Если задача архитектурная и требуется вникнуть в инфраструктуру, то да.
➕ В общем же случае: чем больше знаешь, тем больше аналитик.
  • 🔥 1
Post #143 58
🛡 CSRF-атака и аспекты безопасного API.

CSRF произносится как sea-surf.
C
ross-Site Request Forgery.
Межсайтовая подделка запроса.

В чем суть кейса?

🔴 Злоумышленник делает лжесайт, например:
bank-darit-million-rublei.ru

внутри которого будут скрытые HTML-формы. JS-скрипт будет с этих форм отправлять запросы на настоящий сайт банка. Злоумышленник рассчитывает, что пользователь прямо сейчас на нем авторизован.

🔴 По-скольку пользователь авторизован, то у него есть активная сессия и куки. JS-скрипт выполняется. В банке, в личном кабинете человека, отправляется запрос, например, на перевод денег со счета клиента.

🔴 Злоумышленник улетает на Кипр, человек остается с опытом. ИТ-отдел получает ремня.

Вредоносная CSRF-форма не крадет ваши данные, например, логин и пароль!

Она заставляет ваш браузер отправить запрос на другой сайт без вашего ведома.

Для кражи данных потребуется связка CSRF + XSS (Кросс-сайтовый скриптинг).


Как защититься?

Есть разные способы. Основной — это использовать CSRF-токен.

Сервер генерирует уникальное непредсказуемое значение и отдает его на клиент. Сохраняется в cookie, оттуда встраивается в формы. Когда поступает запрос на изменение данных (POST / PUT / PATCH / DELETE, а также поломанный GET, у которого убрана идемпотентность), сервер сверяет токен который выдал с пришедшим в запросе.
Если совпал — сервер выполняет действие (переводит деньги, меняет логин-пароль и т.д.).

Мошенник же отправляет HTTP-запрос с собственной HTML-формы, не имеющей CSRF-токена. Поэтому такой запрос не будет обработан. В этом и заключается защита.

Почему вредоносный сайт не может узнать CSRF-токена?

Чужой токен нельзя узнать со стороннего домена. В браузерах по-умолчанию реализована Same-Origin Policy (SOP, политика одного источника). CSRF-токен параметром формы передается. Чтобы он туда попал, нужно прочитать чужие cookie, и этого браузер не даст сделать. Если бы давал, то мошенник использовал бы ваши cookie аутентификации чтобы залогиниться в ваш аккаунт в соцсети и т.д.

Как выглядит HTML-форма?

Пример формы на изменение email:

<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>


Как CSRF-атака становится возможной?

Должны быть выполнены все 3 условия:

🔴 Сервис предоставляет целевое действие.
Тут все очевидно: приложение или сайт должны уметь делать то, что хочет мошенник. Изменить пароль или сделать денежный перевод...
🔴 Сессии обрабатываются только на основе cookie.
Сайт или приложение идентифицируют пользователя только на основе cookie сессии, и никак больше.
🔴 Нет неизвестных параметров.
Мошенник хочет сменить вам пароль. Форма на сайте просит ввести текущий пароль. Откуда его знать мошеннику?

Какими "слоями" еще защититься?
Проверять на сервере заголовки Origin и Referer, для подтверждения того, что запрос пришел с настоящего сайта.
Origin, это комбинация протокол + домен + порт, и он отправляется браузером, его значения нельзя подставить самому. Он сообщает серверу, с какого ресурса пришёл запрос.
Referer содержит URL страницы, с которой вы попали на текущую.

Настроить свойство SameSite=Strict в cookie. Так браузер не будет отправлять cookie при межсайтовом запросе.

Где попрактиковаться?

Пощупать атаку можно на PortSwigger. Там есть видео с решениями задач + текстовое описание решения (Solution). Из минусов - изучение платформы займет некоторое время. Стоит скачать прогу Burp Suit (можно бесплатную community-версию).

Что еще почитать?

Про CSRF написано очень много. Вот замечательные технические статьи, которые позволяют лучше понять суть:

⚡️ Описание на PortSwigger
⚡️ CSRF атака: механика эксплуатации, обход защит и построение PoC
⚡️ Межсайтовая подделка запроса (CSRF): Находим и обезвреживаем. Гайд для начинающих

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
  • 🔥 1
Post #141 94
На работе была проблема: сессия быстро протухала в Text-To-Speech-сервисе. Частые залогины меня бесили и я написал js-скрипт для выполнения из консоли браузера. Сейчас нарушается принцип DRY: у меня дважды прописан процесс создания аудиофайла, но... пока так.
Порефакторю потом.

✔️ HTTP-запросы отправляются методом fetch(). Он всегда работает асинхронно, поэтому взял синтаксис async/await. И хотя запросы не блокируются во время ожидания ответа от сервера, процесс все равно синхронен.

✔️ Аудиофайл создается так:

1️⃣ Fetch всегда отдает данные как promise. Приводим промис к json и забираем base64-строку.

Ukfj/9//0P...

2️⃣ Функцией atob() декодируем её в бинарную строку. В ней каждый символ будет представлять байт бинарных данных.

Кракозябры. Не сойдется кодировка, но это не важно.

3️⃣ Мы все ещё работаем со строкой. Для создания аудиофайла нужны байты. Приведём строку к структуре массива байтов Uint8Array. Наша цель получить кол-во элементов в массиве равное длине бинарной строки.

Много нулей:
0, 0, 0...
Нам важно только чтобы кол-во элементов массива равнялось их кол-ву в бинарной строке!

Тип данных уже не string, а object!

4️⃣ Проходим циклом по массиву байтов, меняя каждый 0 на char-код каждого символа строки.

Нули заменены на char-коды символов: 82, 73, 70, 70...

5️⃣ Создаем объект Blob, представляющий сырые бинарные данные (коллекция байтов). На вход подаётся созданный ранее массив. Со строками он не умеет работать, отсюда и вся махинация.

6️⃣ Создаем url нашего файла, а затем и сам аудиофайл через объект new Audio(url);

7️⃣ Запускаем озвучку в браузере методом .play().

✔️ Бинго! Надо озвучить другой текст? Подставляем его в тело запроса и жмем Enter.

const getAudio = async() => {
try {
sessionIdFromLs = localStorage.getItem("session_id");
const response1 = await fetch("ЗАПРОС НА TTS-СИНТЕЗ", {
"headers": {
"X-Session-ID": `${sessionIdFromLs}`,
"Content-Type": "application/json"
},\
"body": "{ТЕКСТ ДЛЯ ОЗВУЧКИ}",
"method": "POST"
});
if (response1.ok) {
const data_blob = await response1.json();
const blob_value = data_blob.data;
const binary = atob(blob_value);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i <binary.length; i++) bytes[i] = binary.charCodeAt(i);
const blob = new Blob([bytes], {type: 'audio/wav'});
const url = URL.createObjectURL(blob);
const audio = new Audio(url);
audio.play()
} else {
const response2 = await fetch("ЗАПРОС СОЗДАНИЯ СЕССИИ", {
"headers": {
"content-type": "application/json"
},
"body": "{ЛОГИН И ПАРОЛЬ}",
"method": "POST"
});
const data = await response2.json();
sessionIdFromLs = data.session_id;
localStorage.setItem("session_id", sessionIdFromLs);
const response3 = await fetch("ЗАПРОС НА TTS-СИНТЕЗ", {
"headers": {
"X-Session-ID": `${sessionIdFromLs}`,
"Content-Type": "application/json"
},
"body": "{ТЕКСТ ДЛЯ ОЗВУЧКИ}",
"method": "POST"
});
const data_blob = await response3.json();
const blob_value = data_blob.data;
const binary = atob(blob_value);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i <binary.length; i++) bytes[i] = binary.charCodeAt(i);
const blob = new Blob([bytes], {type: 'audio/wav'});
const url = URL.createObjectURL(blob);
const audio = new Audio(url);
audio.play()
};
} catch(error) {
console.error('Ошибка: ', error);
};
};

getAudio()
MDN Web Docs Введение в асинхронный JavaScript - Изучение веб-разработки | MDN В этой статье мы кратко остановимся на проблемах, связанных с синхронным Javascript, а также ознакомимся с несколькими асинхронными методами, демонстрирующими как они могут помочь нам подобные проблемы решить.
  • 🔥 1
Post #139 106
🏖️ Однажды я обращался на горячую линию к одному тур-оператору. Меня встретил голосовой помощник, который ходил уточнять информацию и возвращался с... удивительно точным ответом, идеально мне подходящим. Натурально, мне даже оператор не понадобился! Позже я узнал в чем был секрет.

Это был RAG с использованием векторного поиска. О них сегодня пост.

RAG (Retrieval Augmented Generation, генерация с дополненной выборкой) — подход когда LLM дает ответ не только своими внутренними знаниями, а еще использует внешнюю корпоративную информацию. Например, корпоративную бизнес-википедию, базу знаний...

1️⃣Дается большой набор документации, которая делится на куски-чанки.
2️⃣ На выходе получаются вектора, они же эмбеддинги — из себя представляют массив с большим набором чисел [0.1, 0.003 ...]. Все они заносятся в векторную БД.
3️⃣ Когда пользователь делает запрос, то движок тоже преобразовывает его в вектор, а затем по специальным алгоритмам ищет в БД ближайший вектор.

Происходит семантический поиск — по смыслу запроса, а не по ключевым словам. Никаких LIKE(), как в SQL.

4️⃣ Наиболее релевантные фрагменты среди миллионов документов добавляются к исходному запросу, обогащая его контекст.
5️⃣ И в конце, LLM генерирует ответ, отталкиваясь от исходного запроса пользователя и найденного в документах контекста. Так, векторая БД повышает точность ответа и снижает галлюцинации LLM.

Таким образом: векторная БД в RAG нужна для быстрого поиска знаний. LLM нужна для генерации понятного ответа.

Математическое представление смысла того или иного объекта: текст, картинка, аудио, документа. Поиск идет по смыслу, а не по ключевым словам.


🤩 Кошка спит на кресле
[0.10, -0.09, 0,56, -0.11, 0.89, ...]

Каждое число — координата в многомерном пространстве признаков, сформированном ML-моделью.

Близкие по смыслу вектора:

✔️ домашняя кошка
[0.11, -0.05, 0.50, -0.15, 0.84, ...] — все числа расположены рядом с теми, которые получились у "Кошка, спит на кресле"!
❌ самолет Boeing
[0.95, 0.67, -0.33, 0.82, 0,02, ...] — все числа слишком далеко от тех, которые указаны в "Кошка спит на кресле". Смысл уже другой.

Это пример для демонстрации сути вектора. В реальном мире семантические связы намного обширнее. Например, кресла тоже в самолете есть, как и люди путешествующие с животными. Поэтому в реальности используются большие, длинные числа. Векторная БД/движок производит ближайший поиск к точке в многомерном пространстве. Обычная база хранит данные, а векторная — смысл данных.

Многие СУБД имеют векторные движки. Но векторная СУБД кардинально отличается. Там нет SQL-запросов и нет поиска key-value. Векторный поиск — это поиск по смыслу, поиск сходства (Similarity Search), поиск ближайшего соседа (Nearest Neighbor Search).

🔤 Почему обычные СУБД хуже?
На небольших векторах это хорошее решение. Но если у нас десятки и сотни миллионов векторов, это медленный перебор записей, большие задержки, слабая масштабируемость, отсутствие специализированных индексов. В то время как в векторных БД есть ANN-индексы (Approximate Nearest Neighbors, приблизительный поиск ближайших соседей), позволяющие производить поиск за миллисекунды среди миллионов векторов.

🔤 Какие базы данных использовать?
Из специализированных векторных СУБД: Qdrant, Milvus. Касательно движков, есть pgvector (PostgreSQL) и OpenSearch (форк Elasticsearch). Yandex DB тоже обладает крепкими характеристиками для осуществления векторного поиска.

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
  • 🔥 3
Post #138 124
🎮 В мое поле зрения попали 2 браузерные игры по кибербезопасности 🛡

1. Dwell time https://sucky-charm.itch.io/dwell-time

На английском языке. Создана совсем недавно Тимуром Смирновым, ML-инженером из Positive Technologies. Тимур был одним из спикеров на митапе PT, который я посетил в ноябре 2025 в СПб.

Вы — SOC-аналитик 1-й линии, работающий в ночные смены.

Security Operations Center — центр мониторинга информационной безопасности. Аналитики SOC круглосуточно мониторят ИТ-инфраструктуру. Отслеживают подозрительную активность, анализируют и реагируют на инциденты.


В начале игры будет обучение, а затем начнутся три ночные смены. Вам поступит 30 алертов с различными ИБ-кейсами. Ваша задача, как аналитика, разобраться в сути алерта и принять решение что с ним делать:

✔️ отметить как безвредный (ALLOW);
❌ заблокировать как вредоносный (BLOCK);
📈 эскалировать на 2-ю линию (ESCALATE).
❓ Также можно нажать на кнопку INVESTIGATE и поизучать информацию об алерте, для того чтобы определиться с решением.

У игры 3 концовки в зависимости от того, как хорошо вы разобрались с алертами. А поможет вам, джуну, с этим справиться ваш коллега-сеньор Маркус.

❄️ Первый раз я играл ночью (настоящая ночная смена вышла!) и меня даже холодок пробрал по спине в самом конце.

Каждый алерт — реальная атака, описанная в матрице MITRE ATT&CK https://attack.mitre.org/

Adversarial Tactics, Techniques, and Common Knowledge / Техники, тактики и общее знание атак — общедоступная база знаний о методах киберпреступников. Разработана некоммерческой организацией MITRE Corporation в 2013 году.


Рекомендую!

2. Похожая игра, но с LLM.
Попробуйте не разрешить агенту лишнего😄
https://llmgame.scalex.dev/

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
itch.io Dwell Time by sucky_charm A SOC night-shift sim that accidentally teaches you SOC. Play in your browser
  • ❤ 3
  • 🤗 1
Post #137 106
😏Развернем Кафку.

1. Для упрощения будем работать через Docker.
2. Создаем папку. В моем случае это D:\Kafka
3. Создаем в ней файл docker-compose.yml
4. Записываем конфигурацию:

services:
zookeeper:
image: confluentinc/cp-zookeeper:7.3.2
hostname: zookeeper
container_name: zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_SERVER_ID: 1
ZOOKEEPER_SERVERS: zookeeper:2888:3888

kafka:
image: confluentinc/cp-kafka:7.3.2
hostname: kafka
container_name: kafka
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://127.0.0.1:9092
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
KAFKA_BROKER_ID: 1
KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
depends_on:
- zookeeper


5. Открываем папку в командной строке и выполняем команду поднятия контейнеров:
docker-compose up -d
Флаг -d означает, что запуск будет в фоновом режиме (терминал останется свободным).
Контейнеры поднялись!

6. Создадим топик:
docker exec -it kafka kafka-topics --create --topic topic1 --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1

7. Помимо командной строки, для Кафки есть отдельный gui. Установим с официального сайта:
Offset Explorer a.k.a. Kafka Tool.

Cluster — Пишите имя вашего кластера
Bootstrap servers — 127.0.0.1:9092
Галочку Zookeeper ставим.
Host 127.0.0.1
Port — 2181

8. Жмем Connect и изучаем интерфейс.

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
  • ❤ 1
Post #136 113
Посмотрел любопытное публичное собеседование по System Design, организованное Витой Малютиной. Бэкендер Невзоров Владимир собеседует системного аналитика Эмиля.

Составил следующее саммари видео:

🔴 Начинать дизайн системы надо с уточнения клиентских путей: что вообще должен делать новый проект/сервис, какую пользу он несет пользователям? И уже он бизнес-требований отталкиваться в технической реализации.

🔴 Определяем каналы взаимодействия.
🔴 Нужно мобильное приложение (iOS, Android, кроссплатформенное) или веб? Если и то, и другое, то их функционал должен быть полностью идентичен? Подумать в сторону возможности продолжать оформлять заказ с веба, если он частично создан в МП, и наоборот.
🔴 Предусмотреть ключ идемпотентности, чтобы заказ дважды не отправился в ресторан в случае сбоев сети.

🔴 Подумать какие API будут использоваться. В видео упоминается:
🔴 API для пользователей приложения, где будут: список ресторонов, товары, возможность создать заказ.
🔴 API для ресторанов. Ресторан формируют каталог и ассортимент цен + передает время и часы работы заведения.

🔴 Углубляясь в бэкенд, думаем о валидации.
🔴 Мобильное приложение не знает про серверные компоненты, имеет только прикрученный API.
🔴 Между мобильным приложением и сервером есть gateway-слой который проверяет запросы с фронтенда на валидность значений, во избежание подмен. Эти данные на определенном шлюзе проверяются и невалидные значения отбрасываются, не доходя до сервера.

🔴 Масштабируем систему:
🔴 Применяем балансировщик нагрузки, который отправляет заказ на определенный экземпляр приложения. Есть разные принципы определения, когда стоит перенаправлять: территориальный принцип, по идентификтору пользователя, по количеству заказов (если в одной очереди много заказов, то отправляем в другую).
🔴 Использем оркестратор микросервисов Kubernetes / OpenShift. Если кол-во запросов резко возросло, то можно создать доп. компоненты. Если нагрузка резко пойдет на спад, то поду кубера можно удалить.

🔴 Горизонтальное масштабирование базы.
🔴 Увеличиваем кол-во серверов. В видео прозвучало также увеличение оперативки - но это вертикальное масштабирование.
🔴 Настроить в базе репликацию master-slave, на случай, если с основной базой что-то случилось, то можно переключать трафик. Прямая и обратная репликация: из master в slave, и обратно.
🔴 Применить шардирование - разделить данные по разным экземплярам базы на разных серверах. В логике балансировщика реализуем логику распределение пользователей по их IP-адресам, и дальше складывать в подходящую базу: "Европа", "Азия" и т.д.

🔴 Из того, что не было освещено (согласно интервьюеру):
архитектура платежей, доставки, аутентификация, мониторинг.

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
VK Видео Открытое мок-собеседование по System Design. Сервис заказа еды Организатор мероприятия - Малютина Виталия, системный аналитик, VK, автор tg канала @vitazaebymba Интервьюер - Невзоров Владимир, старший бэкенд-разработчик HighLoad систем, специалист кибербезопасности, автор tg канала @system_design_world Собеседуемый…
  • 🔥 2
Post #134 117
🏖 Ушел в отпуск. Вернусь во второй половине мая. А чтобы этот пост был познавательным: вчера появилась лютая годнота:

🔴 Вчера на Хабре вышла статья:
https://habr.com/ru/articles/1030356/ 

Читать всем, кто интересуется клиент-серверным взаимодействием, пентестом и аутентификацией.

Узнаете как мошенники реализовали фишинг под дыру в API самого безопасного в мире мессенджера! Даже двухфакторка не спасает!
Как указал автор статьи - такая лазейка уже давно прикрыта в Telegram, WhatsApp, Signal.

Фишинговый burner-домен (временный для краткосрочных целей):
https://open-file.shop 
на момент написания поста до сих пор работает! Можете поизучать веб-морду через DevTools и повторить те действия, которые делал автор статьи :)

🔴 Вы слышали про FFmpeg? Про эту программу я впервые узнал из одного ответа на Хабр Q&A, когда искал возможность скачивать blob-видео.

Вчера некоторые каналы стали форсить видео:
https://www.youtube.com/watch?v=Ww8MzcBJUd4 
где автор рассказывает историю FFmpeg — бесплатной программы, позволяющей работать с видеороликами разных форматов.

В видео вас ждут: патентовые войны; гики, писавшие крутые программы на C и Assembler на некоммерческой основе; истории успехов и провалов. В общем, все то, за что мы любим историю ИТ.

В конце автор даст мастер-класс по работе с FFmpeg. А тем, кому интересно программирование: на 39:14 автор показывает свой код на Python, для автоматизации пережимания видео в FFmpeg. Можно поставить скорость поменьше, и посмотреть код.

Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
Post #133 93
Секционирование таблиц / Table Partitioning (на примере PostgreSQL).

Что это?
Это один из аспектов архитектуры высоконагруженных систем (или претендующих). Это разбиение данных, логически являющихся одной большой таблицей, на более мелкие физические части (секции).
Для приложения ситуация не меняется — таблица как была, так и останется. Но у DBA появится инструментарий для её гибкого сопровождения.

Когда следует применять?
Чтобы однозначно ответить на вопрос когда применять секционирование, нужны нагрузочные тесты. Они позволят посмотреть: действительно ли вы не теряете в производительности на этапе построения планов запроса. Или для части запросов, которые охватывают данные нескольких секций. Может, наоборот, случиться деградация производительности!

Некоторые критерии, когда секционирование может быть полезно:

(1) У вас большие таблицы. Например, размер которых превышает объем ОЗУ сервера, который используется под СУБД.

(2) У вас высокая скорость загрузки данных. Здесь можно заранее предусмотреть необходимость секционирования.

(3) У вас уже снижается производительность выполнения запросов. Например, замедляется вставка записей в системную TOAST-таблицу (в неё автоматически попадают большие значения, >2 килобайт) так как записи в ней приближаются к нескольким млрд. Этот пункт очень актуален, если охватывается малая часть данных, но скорость снижается из-за того, что приходится просматривать полностью все индексы.

(4) У вас данные временных рядов. Секционирование по дате может помочь быстро извлечь записи за определенный период времени, не сканируя всю таблицу.

(5) У вас высокие расходы на обслуживание таблиц.
Команда VACUUM (очистка диска от записей), к нему ANALYZE (параметр для сбора статистики по таблицам), создание индексов становятся длительными операциями.

(6) У вас применяются политики хранения данных, например, часть данных таблиц разрешается выносить в архив или вообще удалять. Удаление старой секции происходит быстрее и менее ресурсоемко, чем удаление записей.

(7) Вам необходимо снизить потребление памяти. Индексы и фрагменты данных меньшего размера лучше размещаются в памяти и повышают частоту попаданий в кэш.

Какие есть виды секционирования?
(1) По диапазонам не пересеющимся друг с другом, определённым по ключевому полю или набору полей.
Как выглядит код секционирования, на примере компании, торгующей мороженым, можно посмотреть в документации PostgreSQL.

(2) По списку. В нем явно указывается какие значения ключа должны относиться к каждой секции.

CREATE TABLE customers (id INTEGER, status TEXT, arr NUMERIC) PARTITION BY LIST(status);
---Создание секции:
CREATE TABLE cust_active PARTITION OF customers FOR VALUES IN ('ACTIVE');

(3) По хэшу. Таблица секционируется по определенным модулям и остаткам, которые указываются для каждой секции. Цель - равномерное распределение данных по разным секциям.

CREATE TABLE customers (id INTEGER, status TEXT, arr NUMERIC) PARTITION BY HASH(id);
---Создание секции:
CREATE TABLE cust_part1 PARTITION OF customers FOR VALUES WITH (modulus 3, remainder 0);

🔪 Отсечение
Секционирование тесно связано с механизмом отсечения секций (pruning), позволяющим оптимизировать SQL-запросы. На этапе выполнения плана построения запроса, оптимизатор бд понимает что в часть секций в принципе заглядывать не нужно. И это экономит время выполнения. Отсечение может происходить не только на этапе построения плана, но и в процессе выполнения запроса, т.к. некоторые значения могут появляться в процессе (например, значения из подзапросов).

📈 Проанализировать эффективность отсечения можно так:

(1) Используем команду EXPLAIN / EXPLAIN ANALYZE и смотрим план без отсечения секций.
(2) Включаем команду SET enable_partition_pruning = on; и снова выполянем EXPLAIN, и смотрим новый план с отсеченными секциями (их кол-во прописано в свойстве Subplans Removed).
Post #132 88
Как ИИ будет помогать разным профессиям?

Не так давно, Андрей Карпаты выложил инфографику
https://karpathy.ai/jobs/
где показал на какие профессии ИИ окажет наибольшее влияние (кликните таб Digital AI Exposure).
Также доступно здесь:
https://mariodian.github.io/jobs/site/index.html.
Минимальному уровню присвоена цифра 0 (не окажет влиния), а максимальному — 10 (полностью изменит).

0 — ни у одной профессии.
10 — у медицинских транскрипторов (переводят голос в текст). Могу точно сказать, что сам иногда юзаю ИИ для перевода голоса в текст и доволен результатом. 5 лет назад мне доводилось работать с англоязычной медицинской терминологии: создавать в эксельке на английском языке краткие саммари документов на мед. тематику. Страшная была рутина. ИИ мог бы взять это на себя. Кажется, Карпаты здесь попал прямо в тютельку.

Наименьшие показатели (1-2) у профессий физического труда. Уборщики, строители-отделочники-монтажники, столяры, металлурги, массажисты, парикмахеры, пекари, мясники, няни-сиделки, ассистенты ветеринаров и т.д.

Как именно будет помогать? Через небольшие административные задачи: заказ материалов и планирование работ. В общем, то, что не составляюет "ядро" профессии, а находится на периферии. У массажистов это... маркетинг. Разведка крыш дронами для... кровельщиков (да, roofers, это не руферы😀). Прогноз продаж и отслеживание инветаря для... мясников 😅.

Моя профессия, на которую учился в универе — историк — получила 7 баллов. ИИ будет помогать анализировать/синтезировать информацию, набрасывать драфты статей, работать с историческими датасетами.

Системные аналитики:

➡️ Computer systems analysts 8 баллов. ИИ будет писать ТЗ, строить диаграммы, проводить анализ выгод и затрат,  а также помогать программировать и дебажить. Ссылка на профессию в Бюро статистики труда США.

Осталось только понять: к какому году все это будет достигнуто?
Post #130 92

Forwarded from Positive Technologies

Что это был за 😄😄😄 и как он стал рекламой онлайн-казино

В пятницу тысячи (не преувеличиваем) каналов поделились сообщением, которое начиналось с красной надписи черновик: — а точнее, с трех эмодзи, которые ее и составляли. После нее каналы, в том числе крупных и известных брендов, соревновались в юморе: кто интереснее подаст свой черновик. Мы — в том числе.

На первый взгляд — безобидный флешмоб. На деле — тысячи каналов бесплатно прорекламировали онлайн-казино, сами того не подозревая. Рассказываем, как это получилось.

1️⃣ Когда вы создаете пак эмодзи в Telegram, его можно назвать как угодно. Предположим, «Котики». Вы добавляете туда прикольные картинки с котятами, делитесь с друзьями, потом это подхватывают каналы — и вот ваши котики везде.

Но у владельца эмодзи-пака есть возможность переименовать его в любой момент. То есть, например, когда он уже установлен у тысяч пользователей и им продолжают делиться, название может внезапно измениться на «Котики — не очень, песики — огонь». При этом короткое имя (ссылка на добавление пака) остается тем же.

2️⃣ В пятницу так и произошло. Пак из трех эмодзи изначально назывался просто «ЧЕРНОВИК», его начали активно распространять по каналам — копировать и вставлять, не подозревая о планируемом скаме.

Спустя время он был переименован в «ЧЕРНОВИК [упоминание канала] (ПОДПИШИСЬ)». Упоминаемый канал принадлежит некому «социальному казино» (как они сами себя называют), которое якобы бесплатно раздает деньги, но на самом деле через различные шаги уводит на платформу стандартного онлайн-казино. За несколько дней этот канал собрал несколько тысяч подписчиков. Всего за счет трех эмодзи.

3️⃣ Некоторые каналы (и мы, спасибо читателям) обратили на это внимание и заменили паки на собственные. Наш мы так и назвали — «безопасный» (кстати, его установили себе около 20 пользователей, а сколько установили оригинальный — загадка). Другие каналы, узнав об этом, удалили публикации или эмодзи в них.

4️⃣ Чего не произошло, а могло бы. Помимо того, что у паков можно обновлять названия — в них можно менять и сами эмодзи, а также добавлять новые. На примере котиков из начала объяснения — заменить их всех на песиков 🐈 —> 🐕 (сильно не переживайте, в уже размещенных эмодзи котики останутся, изменения будут только в новых публикациях). А дальше у кого на что хватит фантазии — вплоть до размещения фишингового QR-кода, состоящего из эмодзи.

💡 Такие механики — наглядный пример того, как даже без взлома можно использовать доверие аудитории в своих целях. Поэтому перед публикацией любого хайпового контента стоит оценивать риски, даже если на первый взгляд все выглядит безобидно (для себя тоже выводы сделали).

@Positive_Technologies
  • 🔥 2
Post #129 99
😄😄😄 Все-таки решил поучаствовать в модном тренде черновика. Ибо в пятницу 10 апреля все были оригинальные... А я обычный 🤷‍♂️

Поучительный пример, что не надо следовать дешёвому хайпу непонятного происхождения. PT рассказали в чем была суть красного "черновика".

Проверил, реально в разных каналах есть эмодзипак CHernovik784. Ссылка на скам-канал с добавлением (подпишись) отобразится если скопировать ссылку на эмодзипак и отправить себе в Избранное. В пятницу, согласно PT, несколько тысяч человек подписались на онлайн-казино. Потенциально, "пользовательский путь" мог вести на фишинговый QR-код.

✔️ Ну а в этом посте стоит эмодзипак от PT. Назовём его "безопасный".
Post #127 109
🔪 SQL-инъекции. Часть 2. Как защититься от инъекций?

В прошлом техническом посте мы:
➡️ посмотрели какие бывают инъекции
➡️ попробовали сами их по-эксплуатировать.

Возникает закономерный вопрос: и как же от них защититься?

Бремя ответственности лежит на разработчике. Но! ИМХО, это тот самый случай, когда и аналитик может заглянуть в код и оценить уровень бардака в нем. Потому что отличить нормальный запрос в базу от уязвимого, не так уж и сложно.

✔️ Самое главное правило: использовать подготовленные выражения (prepared statements) в базе данных или параметризированные запросы (parameterized queries) в коде бэкенда.

Эти термины часто употребляют как взаимозаменяемые. Это не совсем верно, но смысл у них один и тот же. В обоих случаях пользовательский ввод обрабатывается как данные (т.е. параметры), а не как часть исполняемого кода.

Пример ХОРОШЕЙ практики: в этом коде параметры представлены знаками вопроса:

cur.execute('INSERT INTO users(id, name, surname) VALUES(?, ?, ?)', (id, name, surname))

cur.execute('SELECT * FROM users WHERE login = ? AND password = ?', (login, password))


В общем случае, всегда помним:
❌ не склеиваем строки конкатенацией (+ в Python, Java или || в SQL);
❌ не подставляем в SQL-запрос имена таблиц и полей, либо сами значения с помощью интерполяции/f-строками.

Пример ПЛОХОЙ практики:

cur.execute(f'INSERT INTO cars(car_id, model) VALUES({car_id}, {model})')


✔️ Использовать библиотеки объектно-реляционного маппинга (ORM). Они позволяют взаимодействовать с БД через объекты и классы языка программирования, а не через SQL. ORM уже имеют встроенные механизмы параметризации.
Для Python это, например, SQLAlchemy.
Для Java, например, Hibernate.

✔️ Предусмотрите валидацию данных. Системный аналитик может предоставить данные для валидации пользовательского ввода.
Самые простые вещи, это, например, вводимый возраст:
>= 18 and <=120

✔️ Соблюдайте принцип наименьших привилегий.
Почти каждая система имеет ролевую модель. Учётки должны иметь права только на те таблицы, которые реально нужны для выполнения бизнес-операций, а не на всю базу целиком.

🐧 Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
Post #125 117
News. Закрывается школа для системных аналитиков Systems.Education.

Летом они проводили конкурс "Продолжи мысль", в котором я участвовал с постом про хэширование паролей. Обучение в школе я никогда не покупал, но просматривал бесплатные вебинары и читал статьи из их базы знаний (сайт обещали не удалять). Да и просто читал комментарии основателей школы Дениса Бескова и Алины Богачевой на разных ресурсах, чатах и т.д. Особенно мне нравится позиция Дениса относительно того, что системному аналитику все-таки стоит познакомиться с языками программирования, кто бы там что ни говорил.

Спасибо Денису и Алине за их вклад в развитие отрасли.
Telegram Systems.Education: Системный Анализ и Проектирование информационных систем: архитектура, интеграции, базы данных Школа Systems Education закрывается Спасибо, что были с нами: приходили на обучение, оставляли отзывы, читали наш канал и статьи на сайте, смотрели вебинары и участвовали в конференциях. Вместе с вами мы развивали индустрию и повышали уровень проектирования…
  • ❤ 2
Post #124 118
🔪 SQL-инъекции.

Помню, как-то начальник запостил инфу в чат аналитиков, что на проде нашли инъекцию. Предложил на тестовом стенде пощупать уязвимость. Через несколько месяцев запостил еще раз. Детали я уже подзабыл, но сути это не меняет: разработчики иной раз забивают на DevSecOps. Аналитиков же могут заставить подключиться к разбору продовых инцидентов. Ha-ha, classic 🚬.

В чем суть SQL-инъекции? В незащищённые формы ввода, URL-параметры или поля поиска прописывается частичка SQL-кода. Она передается на сервак и встраивается в основной SQL-код, меняя его логику. Мошенник получает возможность взаимодействовать с базой данных.

Классический пример. Допустим, в админке отрабатывает запрос к базе:


SELECT * FROM users WHERE login = '{логин_пользователя}' AND password = '{пароль}';


Пройдоха передает в логин что-то вроде:

' OR 1=1; --


В пароль можно вообще ничего не передавать, т.к. он закомментируется. Или передать что-то номинальное. Давайте, передадим qwerty. На серваке отработает запрос:

SELECT * FROM users WHERE login = '' OR 1=1; -- AND password = 'qwerty';


Смысл в том, что условие 1=1 является истиной, а дальнейший код закомментирован, а значит взломщику нет нужды вводить правильные credentials.

О трюке с закрытием кавычки и передаче истинного условия
OR TRUE; --
можно прочитать, например, в документации Python:

# Never do this -- insecure!
symbol = input()

# ' OR TRUE; --

sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol
print(sql)

# SELECT * FROM stocks WHERE symbol = '' OR TRUE; --'

cur.execute(sql)


На практике же, взломщику неизвестно каким образом формируется запрос и какими данными он оперирует. Поэтому SQL-инъекции превращаются в искусство, требующее набивки руки и насмотренности. Для оптимизации трудозатрат существуют сканеры. Самая известная, это SQLMap. Пока сам еще не юзал.

Инъекцией можно вытворять самую разнообразную логику. Например:

'; DROP TABLE users; --


И получим:

SELECT * FROM users WHERE login= ''; DROP TABLE users; --' AND password = '';


То есть: пытаемся отгрузить данные пользователя, а потом дропаем таблицу.

Есть, как минимум, 2 способа попытаться определить кол-во полей в таблице:

' order by 10 --
' group by 10 --


Есть слепые инъекции / blind injections направленные на получение косвенных сведений. Классический пример, это задержка производительности, показывающая что бэкенд, как минимум, уязвим:

' OR IF(1=1, SLEEP(5), 0) --


А по этой ссылке описаны атаки с регулярными выражениями. И так далее, и так далее...

✔️Потренироваться в инъекциях можно на сайте:
https://www.alexbers.com/sql/1.php
✔️ Эти же задания скопированы на ХакерДом, с приятным глазу интерфейсом:
https://sql.training.hackerdom.ru/
✔️Почитать как решать задачи можно в статье:
https://habr.com/ru/articles/253885/

Я сумел самостоятельно решить только первые 5 из 10 задач. Дальше подсматривал. На 6-й задаче я все же сумел сам догадаться, что если кавычки запрещены, то надо использовать другой формат слова god. А вот каким образом - не допер. Надо было вызвать функцию CHAR() передав в нее ASCII-коды букв слова god:

login = CHAR(103, 111, 100)


Либо перевести god в кодировку HEX. Получится 676F64. Только не забывайте подставлять префикс 0x, чтобы не скормить базе просто буквоцифры:

login = 0x676F64


А вы сталкивались с SQL-инъекциями? Сколько задач на сайте смогли сами решить? 😉

🐧 Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
  • ❤ 1
Post #123 104
🎥 В прошлую пятницу мне попалась новость, что кибербез-компания Positive Technologies сняла научно-популярный фильм "Как получить доступ ко всему: реверс-инжиниринг".

Вы когда-нибудь слышали о том, чтобы ИТ-компании снимали фильмы? Похоже, что это первый случай!

Доступен на:
📽️ Rutube
📽️ PREMIER
📽️ Ivi

Мне очень понравилось. Решил зафиксировать основные смыслы, которые он несет. Написал на выходных об этом статью на Хабр:

https://habr.com/ru/articles/1005122

Статью построил на цитатах приглашенных экспертов. Самые крутые спецы отрасли!

🐧 Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
Post #121 149
😁 Linux внутри Windows? Установил WSL!

W
indows Subsystem for Linux позволяет вам работать в пингвине не покидая винду.

Я решил поставить подсистему когда захотел развернуть проект Вовы Бурмистрова OneClickMonitoring.
🐧 Он собрал в одну репу 6 сервисов: Kibana, Grafana, ElasticSearch, Prometheus, Node Exporter, Logstash.

Если не установлен git, то выкачиваем файлы проекта и размещаем где-нибудь "не-в-Загрузках".

Дока по установке WSL:
https://learn.microsoft.com/ru-ru/windows/wsl/install

По-умолчанию команда:

wsl --install

установит Ubuntu, но если нужно что-то другое, скажем Debian, или вообще Kali, то:

wsl --list --online

выведет перечень дистрибутивов. Выбираем нужный и подставляем в команду:

wsl --install -d <DistroName>

Когда я в первый раз установил, то не сразу разобрался как с WSL работать. Начал ковыряться, чего-то там снёс. Удалил.

Когда пытался переустановить, то процесс установки Linux завис на 0.0% 🫠. Помогла команда:

wsl --install --web-download

Её я нашел здесь:
https://github.com/microsoft/WSL/issues/9390
Впрочем, про эту команду написано и в инструкции, которую я выше прикрепил 😄. Поэтому читайте внимательно документацию.

Как зайти в WSL?

(1) В поисковой строке Пуска, ищем WSL. Находим пингвина и радуемся.
(2) Либо зайти через интерфейс командной строки или PowerShell. Просто открываете терминал и пишите wsl. Далее, пишите все остальные Linux-команды, какие надо.

Внутри WSL ваши диски существуют в папке mnt.

Соответственно, выполняем команду вида:

cd /mnt/<буква_диска>/<Путь_к_файлам>

У меня проект был размещен в папке на диске D, соответственно, я написал:

cd /mnt/d/OneClickMonitoring-main

И тут я перешел к установке проекта.
🚫 И словил ошибку запуска Docker.
Долго тупил в ошибку, помог Deepseek. Алгоритм такой:

(1) запускаем Docker Desktop;
(2) заходим в шестеренку Settings;
(3) проваливаем в Resourses;
(4) жмем на таб WSL Integration;
(5) ставим крыжик на:
Enable integration with my default WSL distro;

(6) в Enable integration with additional distros:
включаем тумблер Ubuntu;
(7) не забываем нажать на Apply.

Уж не помню, делал ли я перезагрузку компа или нет? В общем, лучше сделайте.

Удостоверившись, что Docker работает, можем устанавливать проект. Для этого:

(1) выполняем команду изменения режима (change mode) с предоставление прав выполнять основной скрипт установки:
chmod +x setup-monitoring.sh
(2) запускаем скрипт
./setup-monitoring.sh

Фух, очень доволен постом! Когда снова нужно будет установить WSL, то буду пользоваться этой инструкцией, чтобы повторно не тупить. Любопытная технология, уверен, пригодится 😕

🐧 Понравился пост? Подписывайся, чтобы не пропустить следующий.

Артем Лещев
Older posts →

About this channel

How can I read @asleshchev without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Артем Лещев | ИТ: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Артем Лещев | ИТ have?
Артем Лещев | ИТ (@asleshchev) has 71 subscribers on Telegram, refreshed roughly every 30 minutes.
Does Артем Лещев | ИТ know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →