Сейчас научу "плохому" — будем поднимать наше веб-приложение на телефоне с https, dns, cloudflared туннелями и прочей красотой.
Для этой цели я накидал приложение на go, которое определяет IP адрес, вычисляет город, отправляет запрос во внешний сервис и отдает страницу с данными о погоде в вашей локации. Я не стал упарываться - он просто нужен для демонстрации, исходники тут https://github.com/itcaat/what-is-the-weather-now.
Что нам нужно:
Итак, качаем UserLAnd https://play.google.com/store/apps/details?id=tech.ula. В списке операционных систем выбираем Ubuntu (Minimal → Terminal). На телефоне откроется терминал и сразу установим пароль пользователя userland. Не спрашивайте почему через sudo - просто поверьте, так надо. =)
$ sudo passwd userland
Теперь посмотрим в настройках wifi свой IP адрес и подключимся с компа по ssh (порт 2022). Ну и сразу установим пакетики.
$ ssh userland@192.168.1.75 -p2022
$ sudo apt update && sudo apt install ca-certificates nano jq unzip -y
Само приложение и его сборка у меня уже готовы. Я собираю сразу под все платформы и архитектуры и качу релиз из main бранчи. Подсмотреть как сделано можно тут https://github.com/itcaat/what-is-the-weather-now/blob/main/.github/workflows/release.yml. Но нам нужен только arm64.
Деплоить на телефон мы будем максимально просто - сделаем скрипт который будет находить последний релиз и разворачивать в userland.
Скрипт развертывания можно посмотреть тут: https://github.com/itcaat/what-is-the-weather-now/blob/main/install_and_run.sh. Там есть параметр —force, который убьет все процессы нашей прилки и заново скачает и запустит приложеньку. Также если скрипт обнаружит новый релиз, то также стопнет текущие процессы нашей прилки и раскатит новую версию. (Можно попробовать поставить github self-hosted runner и деплоить по красоте, но у меня памяти не хватило на него).
Просто кладем его в домашний каталог, chmod +x install_and_run.sh и запускаем. Он найдет последний релиз, скачает его под нашу платформу arm64 и запустит в фоне приложение. Приложение вешается на порт 8080. (см скриншот)
Дальше остается просто добавить туннель в cloudflare zerotrust. При активации вас попросит вбить карту - можно скипнуть этот шаг и сразу настроить туннель cloudflared. По сути нам надо просто выделить либо корневой домен, либо какой то поддомен. Логично что обслуживание домена у вас должно быть в cloudflare (напоминаю, что это бесплатно). (см скриншот)
Далее нам нужно выбрать нужную архитектуру и операционную систему. В нашем случае debian arm64 и запустить команду для установки cloudflared. (см скриншот)
После установки зароутим web трафик в туннель. (см скриншот)
По итогу туннель будет запущен и можно открывать наш супер сайт https://weather.devopsbrain.ru, который хостится прямо на нашем телефоне. SSL также будет из коробки. (см скриншот)
$ curl https://weather.devopsbrain.ru
<html>
<head>
<title>Weather</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Your IP: 213.196.40.61</h1>
<h2>Weather in Amsterdam </h2>
<p>Partly cloudy +9°C</p>
</body>
</html>
Бонусом можно в Rules добавить редирект с http на https в пару кликов. Ну и как вы понимаете, запустить в принципе можно все что хотите (даже с бд-шками) при достаточном количестве памяти. А на этом все - всем хорошего вечерочка.
UPD Есть ненулевая вероятность, что демонстрационный сайт выйдет в окно, так как никакого кеширования там нет и выйти за рейты используемых API очень легко. И вообще это не продакшен-реди решение ;)
UPD2: все таки добавил in memory cache - а то без него грустно
habr: https://habr.com/ru/articles/879818/
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥14👍5❤2💯1
Dive in performance tools. Часть 3️⃣ .2️⃣ [bandwhich]
Мы уже познакомились с bmon тут https://t.me/devopsbrain/123. Сегодня максимально коротко - хочу познакомить с bandwhich.
bandwhich - это консольная тулза для отображения текущего использования сети по процессам, соединениям и удалённым IP-адресам.
Киллер-фича данной тулы в том, что она показывает суммарную утилизацию по remote IP-адресам (Панель utilization by remote address вверху справа). Есть много тузов которые показывают текущее состояние в разрезе процессов или установленных соединений, протоколов и портов - bandwhich же группирует по ip адресам. Это бывает очень полезно, если вы не хотите видеть шум а картину в целом, но с группировкой по IP-адресу.
Также интересно бывает посмотреть утилизацию сети в разрезе на каждое соединение, чтобы определить потенциальный источник проблемы как в целом системы, bandwhich также позволит это сделать.
Мы уже познакомились с bmon тут https://t.me/devopsbrain/123. Сегодня максимально коротко - хочу познакомить с bandwhich.
bandwhich - это консольная тулза для отображения текущего использования сети по процессам, соединениям и удалённым IP-адресам.
Киллер-фича данной тулы в том, что она показывает суммарную утилизацию по remote IP-адресам (Панель utilization by remote address вверху справа). Есть много тузов которые показывают текущее состояние в разрезе процессов или установленных соединений, протоколов и портов - bandwhich же группирует по ip адресам. Это бывает очень полезно, если вы не хотите видеть шум а картину в целом, но с группировкой по IP-адресу.
Также интересно бывает посмотреть утилизацию сети в разрезе на каждое соединение, чтобы определить потенциальный источник проблемы как в целом системы, bandwhich также позволит это сделать.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥5👏2👍1
DevOps Brain 🧠 pinned «🗺 Карта канала 🗺 Ламповый чатик: https://t.me/+KY6hbAcgOL84OTIy Мои статьи: --- ▶️ Бесплатный сайт - закроем тему - https://t.me/devopsbrain/141 ▶️ Про магию for в prometheus - https://t.me/devopsbrain/138 ▶️ Настройка самоподписных валидных ssl-сертификатов…»
DevOps Brain 🧠
Бесконечно можно смотреть на 3 вещи: огонь, воду и симулятор kafka от softwaremill 🔗 https://softwaremill.com/kafka-visualisation. Очень классная визуализация, которая позволяет понять принципы работы и покрутить разные ручки для разных сценариев 🔥
Media is too big
VIEW IN TELEGRAM
Ладно, есть еще одна вещь на которую тоже можно вечно смотреть - симулятор rabbitmq. https://tryrabbitmq.com/
❤7🔥3
🆕 Как исправлять ошибки в Git, не оставляя улик
Кто не сталкивался с коммитами вроде "Remove debug log", "Fix" или "фикс фикса"?
Такие коммиты как грязные носки под кроватью: их не видно, пока не придёт ревьюер с пристальным взглядом или, что еще хуже, потенциальный работодатель, решивший посмотреть на ваш github.
К счастью, Git предлагает два супер-инструмента для того, чтобы история коммитов выглядела так, будто ты всегда знаешь, что делаешь: git commit --fixup и git rebase --autosquash.
⚠️ Важно! Не вздумайте применять rebase в main или
# Использование fixup и autosquash
## Что делает
Команда git commit --fixup <commit> говорит Git: *"Я накосячил, но давай сделаем вид, что этого никогда не было"*. Она автоматически помечает коммит как исправление указанного коммита, чтобы позже их можно было объединить.
## Как работает
Команда git rebase -i --autosquash делает всю грязную работу: находит fixup-коммиты и запихивает их обратно в родительский коммит, словно ничего и не происходило.
---
# Практический пример
## Шаг 1. Делаем коммиты (как обычно, неидеально)
Представьте, что вы работаете в своей фича-ветке mvp-server и коммитите две новые фичи:
## Шаг 2. Ой… нашлась ошибка в первом коммите
Оказывается, в коммите с feat: listen port 8080 была опечатка, и теперь сервер запускается не на 8080, а на 808 порту. Не беда, просто делаем fixup. Но для начала надо найти тот коммит, который будем фиксить. В нашем случае это будет dc4efa9
Git сам добавляет fixup! перед сообщением, как бы говоря: "Да-да, я понял, ты хотел исправить, но давай замнем эту тему".
Если же настроен git hook для добавления в начало сообщения ID-таска, то можно воспользоваться --no-verify , чтобы временно отключить хуки. В противном случае придется при ребейзе руками прописывать pick для fixup-коммита.
## Шаг 3. Проверяем, что нас ждёт
## Шаг 4. Применяем
Важно, что надо передать в ребейз хеш последнего коммита, который вы хотите сохранить как есть, а не первого, который вы хотите поменять. В нашем случае это будет df9f0ae , так как git будет менять как раз dc4efa9 feat: listen port 8080 .
Редактор откроет вот такую картину:
Просто сохраняем, выходим и наслаждаемся магией.
## Шаг 5. Проверяем, что история коммитов идеальна
Как будто всё было идеально с самого начала, а будущий работодатель уже шлет тебе оффер ибо таких красивых коммитов он еще в жизни не видел и не важно, что код не работает.
habr: https://habr.com/ru/articles/881614/
Кто не сталкивался с коммитами вроде "Remove debug log", "Fix" или "фикс фикса"?
Такие коммиты как грязные носки под кроватью: их не видно, пока не придёт ревьюер с пристальным взглядом или, что еще хуже, потенциальный работодатель, решивший посмотреть на ваш github.
К счастью, Git предлагает два супер-инструмента для того, чтобы история коммитов выглядела так, будто ты всегда знаешь, что делаешь: git commit --fixup и git rebase --autosquash.
⚠️ Важно! Не вздумайте применять rebase в main или
stable
-ветках, если не хотите, чтобы ваши коллеги не сделали вам больно. Эти штуки нужны для приведения feature-ветки в божеский вид перед слиянием.# Использование fixup и autosquash
## Что делает
fixup
?Команда git commit --fixup <commit> говорит Git: *"Я накосячил, но давай сделаем вид, что этого никогда не было"*. Она автоматически помечает коммит как исправление указанного коммита, чтобы позже их можно было объединить.
## Как работает
autosquash
?Команда git rebase -i --autosquash делает всю грязную работу: находит fixup-коммиты и запихивает их обратно в родительский коммит, словно ничего и не происходило.
---
# Практический пример
## Шаг 1. Делаем коммиты (как обычно, неидеально)
Представьте, что вы работаете в своей фича-ветке mvp-server и коммитите две новые фичи:
$ git add main.go
$ git commit -m "feat: listen port 8080"
[mvp-server dc4efa9] feat: listen port 8080
1 file changed, 1 insertion(+)
$ git add main.go
$ git commit -m "feat: added handlers"
[mvp-server ab604f9] feat: added handlers
1 file changed, 1 insertion(+), 1 deletion(-)
## Шаг 2. Ой… нашлась ошибка в первом коммите
Оказывается, в коммите с feat: listen port 8080 была опечатка, и теперь сервер запускается не на 8080, а на 808 порту. Не беда, просто делаем fixup. Но для начала надо найти тот коммит, который будем фиксить. В нашем случае это будет dc4efa9
$ git log --oneline
ab604f9 (HEAD -> mvp-server) feat: added handlers
dc4efa9 feat: listen port 8080
df9f0ae (main) mvp
$ git add main.go
$ git commit --fixup dc4efa9
[mvp-server 62e7318] fixup! feat: listen port 8080
Git сам добавляет fixup! перед сообщением, как бы говоря: "Да-да, я понял, ты хотел исправить, но давай замнем эту тему".
Если же настроен git hook для добавления в начало сообщения ID-таска, то можно воспользоваться --no-verify , чтобы временно отключить хуки. В противном случае придется при ребейзе руками прописывать pick для fixup-коммита.
$ git commit --no-verify --fixup <commit_hash>
## Шаг 3. Проверяем, что нас ждёт
$ git log --oneline
62e7318 (HEAD -> mvp-server) fixup! feat: listen port 8080
ab604f9 feat: added handlers
dc4efa9 feat: listen port 8080
df9f0ae (main) mvp
## Шаг 4. Применяем
rebase
и делаем вид, что всё было идеально с самого началаВажно, что надо передать в ребейз хеш последнего коммита, который вы хотите сохранить как есть, а не первого, который вы хотите поменять. В нашем случае это будет df9f0ae , так как git будет менять как раз dc4efa9 feat: listen port 8080 .
$ git rebase -i --autosquash df9f0ae
Редактор откроет вот такую картину:
pick dc4efa9 feat: listen port 8080
fixup 62e7318 fixup! feat: listen port 8080
pick ab604f9 feat: added handlers
Просто сохраняем, выходим и наслаждаемся магией.
## Шаг 5. Проверяем, что история коммитов идеальна
$ git log --oneline
a72151f (HEAD -> mvp-server) feat: added handlers
0441501 feat: listen port 8080
df9f0ae (main) mvp
Как будто всё было идеально с самого начала, а будущий работодатель уже шлет тебе оффер ибо таких красивых коммитов он еще в жизни не видел и не важно, что код не работает.
habr: https://habr.com/ru/articles/881614/
1🔥18❤1
В данном гайде мы настроим автоматический выпуск “валидных” сертификатов в локальном kubernetes кластере. В качестве примера запустим приложение grafana.
Что будем делать:
1. Развернем локально кластер локально. Установим MetalLB, cert-manager, ingress и поднимем тестовое приложение grafana.
2. Настроим нашу систему так, чтобы она доверяла выпущенным в кубе сертификатам.
3. Используем nip.io, чтобы не заморачиваться с hosts-файлом
# Поднимаем кластер
Тут совершенно нет никаких проблем, я буду использовать стандартный Docker Desktop для запуска. Ставим галочку в настройках Docker Desktop, что нам нужен куб и погнали дальше.
# MetalLB
MetalLB — это балансировщик нагрузки для Kubernetes, предназначенный для работы в средах, где нет встроенного облачного балансировщика, например, в bare-metal кластерах. Kubernetes изначально предполагает, что балансировка нагрузки будет предоставляться облачными провайдерами (AWS, GCP, Azure), но в локальных кластерах или в on-premise инфраструктуре такой возможности нет. MetalLB решает эту проблему, предоставляя LoadBalancer-сервисам реальные IP-адреса.
MetalLB поставим и сконфигурируем просто для удобства. Он выдаст сервису Ingress Load Balancer наш локальный IP-адрес.
# Для начала проверим что мы точно в нужном кластере
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop
# Устанавливаем
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/main/config/manifests/metallb-native.yaml
# Проверяем что подики поднялись
$ kubectl get pods -n metallb-system
# Найдем наш локальный ip адрес (у меня macos).
$ ifconfig | grep "inet " | grep -v 127.0.0.1
inet 192.168.1.52 netmask 0xffffff00 broadcast 192.168.1.255
Теперь сразу же настроим, чтобы выдавался только нужный нам IP адрес. Вы можете тоже самое сделать и для 127.0.0.1. Но я буду вешать на IP адрес в локальной сети, так как в дальнейшем планирую, что доступ понадобится из локальной сети. В моем случае это будет 192.168.1.52.
kubectl apply -f - <<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ingress-ip-pool
namespace: metallb-system
spec:
addresses:
- "192.168.1.52-192.168.1.52"
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: advert
namespace: metallb-system
EOF
Продолжение далее
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍2
# Сертификаты и ingress
Сначала нам надо выпустить корневой сертификат. Для этих целей будем использовать mkcert. Это утилита, которая позволяет легко создавать локальные SSL/TLS-сертификаты без необходимости подписывать их у внешнего удостоверяющего центра (CA). Основное преимущество mkcert — автоматическая генерация доверенного корневого сертификата и выпуск локальных сертификатов, которые сразу же распознаются браузерами и системами без дополнительных настроек. Процесс установки есть в https://github.com/FiloSottile/mkcert под вашу OS.
# Запустим утилиту. Это надо сделать один раз, она сгенерит CA и пропишет в нашу ОС.
$ mkcert --install
Далее установим наш cert-manager в kubernetes и добавим наш CA в кластер, чтобы мы могли выпускать сертификаты.
# Устанавливаем в namespace cert-manager
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.1/cert-manager.crds.yaml
$ helm repo add jetstack https://charts.jetstack.io --force-update
$ helm install cert-manager --namespace cert-manager --version v1.17.1 jetstack/cert-manager --create-namespace
# cert-manager сможет использовать этот CA для автоматической выдачи сертификатов
$ kubectl create secret tls mkcert-ca-key-pair --key "$(mkcert -CAROOT)"/rootCA-key.pem --cert "$(mkcert -CAROOT)"/rootCA.pem -n cert-manager
# Создаем объект ClusterIssuer в Kubernetes, который будет использовать сертификаты из секрета mkcert-ca-key-pair
$ kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: mkcert-issuer
namespace: cert-manager
spec:
ca:
secretName: mkcert-ca-key-pair
EOF
Теперь установим ingress nginx.
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update
$ helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace
# Запускаем приложение
Возникает вопрос какой же домен использовать. Мы же не ограничены только одним приложением, а хотим просто в ingress задавать нужный домен и чтобы он был доступен на локальной машине. А каждый раз при поднятии нового приложения прописывать адрес в hosts - такая себе история. Чтобы сделать красиво и без боли воспользуемся таким классным сервисом как nip.io.
nip.io — это бесплатный сервис для динамического DNS, он позволяет использовать доменные имена, привязанные к IP-адресу, без необходимости иметь собственный DNS-сервер. Сервис автоматом подставляет IP-адрес при запросе <IP-адрес>.nip.io. Например:
- 192.168.1.52.nip.io → разолвится в 192.168.1.52
- demo.203.0.113.20.nip.io → резолвится в 203.0.113.20
У нас все готово и осталось запустить grafana. Применяем подготовленные манифесты с Deployment, Service и Ingress.
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana-deployment
labels:
app: grafana
spec:
replicas: 3
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- image: grafana/grafana:11.5.1
name: grafana
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: grafana-service
labels:
app: grafana
spec:
selector:
app: grafana
ports:
- protocol: TCP
port: 3000
targetPort: 3000
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
annotations:
cert-manager.io/cluster-issuer: mkcert-issuer
spec:
ingressClassName: nginx
tls:
- hosts:
- grafana.192.168.1.52.nip.io
secretName: hello-ingress-cert
rules:
- host: grafana.192.168.1.52.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana-service
port:
number: 3000
EOF
Ну и получаем работающее приложение с валидным на локальной машине самоподписным сертификатом по адресу https://grafana.192.168.1.52.nip.io/
habr: https://habr.com/ru/articles/883428/
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥10👍5
Media is too big
VIEW IN TELEGRAM
Что-то скучный у меня сегодня вечер: жена уехала тусить с подругой, а дети сидят и играют в лего.
Штош, тогда надо сделать что-то полезное, но не скучное. Будем писать хацкерский скрипт - это ацкий комбайн из kubescape(k8s) и metasploit.
Идея очень простая: сканим кластер k8s через kubescape, сохраняем результаты в json, дергаем оттуда CVE и ищем в metasploit. По итогу получаем список эксплойтов, которые можно заюзать в metasploit.
Пользуйтесь, друзья. Все только в образовательных целях, не надо пытаться взламывать кластера работодателя, оно там уголовно-наказуемо и все такое.
https://devopsbrain.ru/posts/2025-02-16-metasploit-%D0%BAubescape/
Штош, тогда надо сделать что-то полезное, но не скучное. Будем писать хацкерский скрипт - это ацкий комбайн из kubescape(k8s) и metasploit.
Идея очень простая: сканим кластер k8s через kubescape, сохраняем результаты в json, дергаем оттуда CVE и ищем в metasploit. По итогу получаем список эксплойтов, которые можно заюзать в metasploit.
Пользуйтесь, друзья. Все только в образовательных целях, не надо пытаться взламывать кластера работодателя, оно там уголовно-наказуемо и все такое.
#!/bin/bash
DEFAULT_SCAN_NAME=$(date +"%Y-%m-%d_%H-%M-%S")
read -p "Enter a name for this scan (leave empty for default: $DEFAULT_SCAN_NAME): " SCAN_NAME
SCAN_NAME=${SCAN_NAME:-$DEFAULT_SCAN_NAME}
SCAN_DIR="scans/$SCAN_NAME"
mkdir -p "$SCAN_DIR"
echo "[+] Scan results will be stored in: $SCAN_DIR"
echo "[+] Checking for required tools..."
if ! command -v kubescape &> /dev/null; then
echo "[-] Kubescape is not installed. Please install it first."
exit 1
fi
echo "[+] Checking current Kubernetes context..."
CURRENT_CONTEXT=$(kubectl config current-context)
if [ -z "$CURRENT_CONTEXT" ]; then
echo "[-] No active Kubernetes context found. Please configure your kubeconfig."
exit 1
fi
echo "[+] You are currently using Kubernetes context: $CURRENT_CONTEXT"
read -p "Do you want to continue with this context? (y/n): " CONTINUE
if [[ "$CONTINUE" != "y" && "$CONTINUE" != "Y" ]]; then
echo "[-] Exiting script."
exit 0
fi
read -p "Enter the namespace to scan (leave empty for all namespaces): " NAMESPACE
if [[ -z "$NAMESPACE" ]]; then
NAMESPACE_FLAG="--all-namespaces"
echo "[+] Scanning all namespaces..."
else
NAMESPACE_FLAG="-n $NAMESPACE"
echo "[+] Scanning namespace: $NAMESPACE"
fi
read -p "Do you want to check Metasploit for available exploits? (y/n): " CHECK_METASPLOIT
if [[ "$CHECK_METASPLOIT" == "y" || "$CHECK_METASPLOIT" == "Y" ]]; then
SEARCH_METASPLOIT=true
# Check if Metasploit is installed
if ! command -v msfconsole &> /dev/null; then
echo "[-] Metasploit is not installed. Exploit search will be skipped."
SEARCH_METASPLOIT=false
fi
else
SEARCH_METASPLOIT=false
echo "[+] Skipping Metasploit exploit search."
fi
echo "[+] Retrieving container images..."
kubectl get pods $NAMESPACE_FLAG -o json | jq -r '.items[].spec.containers[].image' | sort -u > "$SCAN_DIR/images.txt"
if [[ ! -s "$SCAN_DIR/images.txt" ]]; then
echo "[-] No container images found in the selected namespace(s)."
exit 1
fi
echo "[+] Found $(wc -l < "$SCAN_DIR/images.txt") unique images."
echo "[+] Scanning container images with Kubescape..."
mkdir -p "$SCAN_DIR/results"
while read -r image; do
echo "[*] Scanning $image..."
safe_name=$(echo "$image" | tr '/:' '_')
kubescape scan image "$image" --format json --output "$SCAN_DIR/results/${safe_name}.json"
done < "$SCAN_DIR/images.txt"
echo "[+] Extracting CVEs from Kubescape reports..."
jq -r '.matches[].vulnerability.id' "$SCAN_DIR/results/"*.json | grep CVE > "$SCAN_DIR/cve_list.txt"
if [[ ! -s "$SCAN_DIR/cve_list.txt" ]]; then
echo "[-] No CVEs found in container images."
exit 0
fi
echo "[+] Found $(wc -l < "$SCAN_DIR/cve_list.txt") CVEs."
if [[ "$SEARCH_METASPLOIT" == true ]]; then
echo "[+] Searching for exploits in Metasploit..."
rm -f "$SCAN_DIR/metasploit_results.txt"
while read -r cve; do
echo "[*] Searching for $cve in Metasploit..."
msfconsole -q -x "search $cve; exit" | tee -a "$SCAN_DIR/metasploit_results.txt"
done < "$SCAN_DIR/cve_list.txt"
echo "[+] Search completed. Found exploits:"
grep -E 'exploit/' "$SCAN_DIR/metasploit_results.txt" || echo "[-] No exploits found for detected CVEs."
else
echo "[+] Skipping Metasploit exploit search."
fi
echo "[+] Scan completed. Results are stored in: $SCAN_DIR"
https://devopsbrain.ru/posts/2025-02-16-metasploit-%D0%BAubescape/
🔥12😁4❤2🍓2👍1👏1
Мои дети просто обожают играть в minecraft. Ну а я никогда не понимал смысла игры. Ходишь там что-то добываешь без конца и строишь, крафитишь, добываешь и так до бесконечности. Сейчас они обнаружили, что можно ставить моды. Иногда зовут меня смотреть, что у них там получается, а иногда зовут помочь с запуском модов. И тут я решил, что пора их с моими играми познакомить.
Вчера я предоложил им поиграть в Terraform. Они поискали и нашли что за игра в Steam https://store.steampowered.com/app/347790/Terraform. Но как вы понимаете играли мы в совершенно другую игру. 🧌
Результатом этого "геймплея" стал вот этот реп: https://github.com/itcaat/terraform-kubernetes-desktop-startkit. Помните, был пост про настройку локального куба и валидных ssl в нем(https://t.me/devopsbrain/135)? Так вот это почти тоже самое, но теперь все можно настроить за пару команд.
📌 Как играть в Terraform Kubernetes — Starter Kit for Docker Desktop?
1️⃣ Ставите Docker Desktop и активируйте в нем Kubernetes (или любой аналог)
2️⃣ Форкаете репу https://github.com/itcaat/terraform-kubernetes-desktop-startkit.
3️⃣ Запускаете по инструкции – и вот у вас есть локальный кластер с Ingress, Cert-Manager, MetalLB и Echo Server в качестве примера!
Цель игры в Terraform проста: накопать как можно больше модулей и собрать из них что-то прикольное.
Кстати, моим детям не понравилось играть в Terraform. Говорят, слишком мало криперов и слишком много непонятной ерунды. Ну и в чем они не правы?
Вчера я предоложил им поиграть в Terraform. Они поискали и нашли что за игра в Steam https://store.steampowered.com/app/347790/Terraform. Но как вы понимаете играли мы в совершенно другую игру. 🧌
Результатом этого "геймплея" стал вот этот реп: https://github.com/itcaat/terraform-kubernetes-desktop-startkit. Помните, был пост про настройку локального куба и валидных ssl в нем(https://t.me/devopsbrain/135)? Так вот это почти тоже самое, но теперь все можно настроить за пару команд.
📌 Как играть в Terraform Kubernetes — Starter Kit for Docker Desktop?
1️⃣ Ставите Docker Desktop и активируйте в нем Kubernetes (или любой аналог)
2️⃣ Форкаете репу https://github.com/itcaat/terraform-kubernetes-desktop-startkit.
3️⃣ Запускаете по инструкции – и вот у вас есть локальный кластер с Ingress, Cert-Manager, MetalLB и Echo Server в качестве примера!
Цель игры в Terraform проста: накопать как можно больше модулей и собрать из них что-то прикольное.
Кстати, моим детям не понравилось играть в Terraform. Говорят, слишком мало криперов и слишком много непонятной ерунды. Ну и в чем они не правы?
🔥12😁9
🆕 На что влияет evaluation_interval и for в алертах prometheus
_
Если вы используете prometheus или victoria metrics для настройки алертов, то наверняка встречали функции анализа временных рядов. Их отличительной особенностью является то, что они на вход получают временной интервал ([X]).
- increase() — считает, на сколько увеличился счётчик.
- rate() — усреднённая скорость изменения в секунду.
- delta() — разница между начальным и конечным значением.
- deriv() — скорость изменения с учётом тренда.
Разберем на примере, где хотим получить все успешные заказы в окружении production.
В данном примере increase(...) рассчитывает, насколько увеличился счётчик orders_total за последние 30 минут. Поскольку это счётчик counter (
Теперь пришло время сделать алерт. Мы хотим знать, что конверсия (количество успешных заказов в данном случае) упала и бизнесу плохо. И тут некоторые ошибочно полагают, что не могут использовать for меньше чем 30 минут. Природа ошибки в принципе понятна, чаще всего мы используем в выражении меньший интервал, а for больший. Ну к примеру, increase(...[1m]) с for: 5m. В этом случает никаких вопросов нет и все просто. Но на самом деле все гораздо интереснее.
Механизм срабатывания алерта в Prometheus зависит от параметра evaluation_interval, который определяет частоту вычислений правил. По-умолчанию он evaluation_interval: 1m . Поэтому prometheus будет вычислять по такому алгоритму:
- В T0 (
- В T+1m он снова считает increase(...[30m]), теперь за [T-29m, T+1m].
- В T+2m — за [T-28m, T+2m].
- ...
- В T+5m — за [T-25m, T+5m].
Если значение выражения остаётся выше порога на всех 5 оценках (
Предположим, что для бизнеса нормально делать по 100 заказов за 30 минут, в противном случае нам нужен алерт. Пример в данном случае выдуман из головы и в реальной жизни нам был бы интересен for: 0m. Но мы предположим, что при for: 0m у нас будут ложные срабатывания. Ну, например, во время релизов допускается, что возможны просадки. Поэтому мы заложим туда 5 минут и опишем так:
Разбор примера:
- Как мы говорили выше — функция increase(...[30m]) вычисляет изменение метрики за последние 30 минут.
- Это изменение пересчитывается каждый раз при выполнении запроса в зависимости от настройки evaluation_interval в Prometheus.
- Если условие алерта (
_
Если вы используете prometheus или victoria metrics для настройки алертов, то наверняка встречали функции анализа временных рядов. Их отличительной особенностью является то, что они на вход получают временной интервал ([X]).
- increase() — считает, на сколько увеличился счётчик.
- rate() — усреднённая скорость изменения в секунду.
- delta() — разница между начальным и конечным значением.
- deriv() — скорость изменения с учётом тренда.
Разберем на примере, где хотим получить все успешные заказы в окружении production.
increase(orders_total{environment="production", status="success"}[30m])
В данном примере increase(...) рассчитывает, насколько увеличился счётчик orders_total за последние 30 минут. Поскольку это счётчик counter (
_total
в имени как бы намекает), его значения могут только увеличиваться или сбрасываться на 0, если произошёл рестарт сервиса. Таким образом, increase(...[30m]) показывает, сколько успешных заказов (status="success"
) было обработано за последние 30 минут.Теперь пришло время сделать алерт. Мы хотим знать, что конверсия (количество успешных заказов в данном случае) упала и бизнесу плохо. И тут некоторые ошибочно полагают, что не могут использовать for меньше чем 30 минут. Природа ошибки в принципе понятна, чаще всего мы используем в выражении меньший интервал, а for больший. Ну к примеру, increase(...[1m]) с for: 5m. В этом случает никаких вопросов нет и все просто. Но на самом деле все гораздо интереснее.
Механизм срабатывания алерта в Prometheus зависит от параметра evaluation_interval, который определяет частоту вычислений правил. По-умолчанию он evaluation_interval: 1m . Поэтому prometheus будет вычислять по такому алгоритму:
- В T0 (
now
) он считает increase(...[30m]), получая данные за диапазон [T-30m, T0].- В T+1m он снова считает increase(...[30m]), теперь за [T-29m, T+1m].
- В T+2m — за [T-28m, T+2m].
- ...
- В T+5m — за [T-25m, T+5m].
Если значение выражения остаётся выше порога на всех 5 оценках (
T0
, T+1m, ..., T+5m
), то алерт срабатывает.Предположим, что для бизнеса нормально делать по 100 заказов за 30 минут, в противном случае нам нужен алерт. Пример в данном случае выдуман из головы и в реальной жизни нам был бы интересен for: 0m. Но мы предположим, что при for: 0m у нас будут ложные срабатывания. Ну, например, во время релизов допускается, что возможны просадки. Поэтому мы заложим туда 5 минут и опишем так:
- alert: NoSuccessOrders
expr: increase(orders_total{environment="production", status="success"}[30m]) < 100
for: 5m
labels:
severity: critical
annotations:
summary: "No Success Orders"
description: "Successful orders dropped below 100 in the last 30 minutes"
Разбор примера:
- Как мы говорили выше — функция increase(...[30m]) вычисляет изменение метрики за последние 30 минут.
- Это изменение пересчитывается каждый раз при выполнении запроса в зависимости от настройки evaluation_interval в Prometheus.
- Если условие алерта (
expr
) остаётся истинным в течение 5 минут подряд (на всех оценках), алерт сработает.❤5🔥5👍2
Всем привет в этом “чате”. Решил немного разбавить материал новой рубрикой: “а как оно работает на самом деле” с отсылками к теоретической части различных технологий. И сегодня мы поговорим про кольцо хеширования (Consistent Hashing) и почему оно нам интересно. Также я навайбкодил симулятор и выложил его в конце статьи.
Кольцо хеширования - это алгоритм распределения ключей между множеством узлов (например, серверов, кешей, шардов БД) таким образом, чтобы минимизировать количество перестановок при добавлении или удалении узлов. А интересен он тем, что этот принцип широко используется в системах с распределённым хранением данных, например, в DynamoDB, Cassandra, Riak, а также в Memcached.
# Основные термины
- Хеш-пространство. Все возможные значения хеша (например, от 0 до 2³²−1 при использовании 32-битного хеш-функции) образуют кольцо - замкнутое пространство.
- Хеширование узлов. Каждый узел (сервер) получает одно или несколько значений в этом пространстве - они определяются с помощью хеш-функции от имени узла (например, hash("cache1")).
- Хеширование ключей. Каждый ключ (например, ID объекта) также хешируется и отображается на кольцо.
- Поиск узла для ключа. Ищется ближайший по часовой стрелке узел на кольце - он и будет ответственным за хранение данного ключа. Если не нашлось подходящего узла “вправо” - кольцо замыкается, и мы просто берём первый по кругу. Вот такая красивая логика.
# Как рассчитывается позиция узла
При добавлении нового узла, он перехватывает часть ключей у ближайших по кольцу узлов. Остальные остаются на месте. Таким образом изменения затрагивают только часть данных, а не все. Это повышает масштабируемость системы. При удалении узла аналогично - его ключи перераспределяются между оставшимися узлами, что также затрагивает только часть данных.
## Разберем на примере
Базовая реализация расчета позиции узла в кольце будет выглядеть так:
Где:
- node_id - уникальный идентификатор узла (например, `"node-1"`).
- hash() - детерминированная хеш-функция (например, **SHA1**).
Хеш-функция преобразует node_id в число из диапазона 0 до 2³²−1, где N количество бит хеша (например, 32 или 64). Это число и определяет позицию узла на кольце.
Если добавляется "node-D" он встанет между A и B на кольце и запустится перераспределение части ключей.
Чтобы избежать неравномерного распределения, часто применяют виртуальные узлы (virtual nodes):
Каждый виртуальный узел это просто хеш от строки с суффиксом. Это приводит к тому, что один физический узел будет представлен в нескольких местах на кольце - и получит ключи с разных участков, выравнивая нагрузку. Конечно, под капотом у реальных систем все гораздо сложнее, но у нас и нет цели тут построить DynamoDB.
Поиграться с симулятором consistent hashing можно тут https://consistent-hashing.simulators.devopsbrain.ru. В симуляторе вы можете добавить/удалить узлы, увидеть, как перераспределяются ключи.
UPD: оказывается версия на мобилках работала криво - поправил.
Кольцо хеширования - это алгоритм распределения ключей между множеством узлов (например, серверов, кешей, шардов БД) таким образом, чтобы минимизировать количество перестановок при добавлении или удалении узлов. А интересен он тем, что этот принцип широко используется в системах с распределённым хранением данных, например, в DynamoDB, Cassandra, Riak, а также в Memcached.
# Основные термины
- Хеш-пространство. Все возможные значения хеша (например, от 0 до 2³²−1 при использовании 32-битного хеш-функции) образуют кольцо - замкнутое пространство.
- Хеширование узлов. Каждый узел (сервер) получает одно или несколько значений в этом пространстве - они определяются с помощью хеш-функции от имени узла (например, hash("cache1")).
- Хеширование ключей. Каждый ключ (например, ID объекта) также хешируется и отображается на кольцо.
- Поиск узла для ключа. Ищется ближайший по часовой стрелке узел на кольце - он и будет ответственным за хранение данного ключа. Если не нашлось подходящего узла “вправо” - кольцо замыкается, и мы просто берём первый по кругу. Вот такая красивая логика.
# Как рассчитывается позиция узла
При добавлении нового узла, он перехватывает часть ключей у ближайших по кольцу узлов. Остальные остаются на месте. Таким образом изменения затрагивают только часть данных, а не все. Это повышает масштабируемость системы. При удалении узла аналогично - его ключи перераспределяются между оставшимися узлами, что также затрагивает только часть данных.
## Разберем на примере
Базовая реализация расчета позиции узла в кольце будет выглядеть так:
position = hash(node_id)
Где:
- node_id - уникальный идентификатор узла (например, `"node-1"`).
- hash() - детерминированная хеш-функция (например, **SHA1**).
Хеш-функция преобразует node_id в число из диапазона 0 до 2³²−1, где N количество бит хеша (например, 32 или 64). Это число и определяет позицию узла на кольце.
# считаем позиции
hash("node-A") = 132
hash("node-B") = 278
hash("node-C") = 75
Если добавляется "node-D" он встанет между A и B на кольце и запустится перераспределение части ключей.
hash("node-D") = 200
Чтобы избежать неравномерного распределения, часто применяют виртуальные узлы (virtual nodes):
hash("node-D#1")
hash("node-D#2")
hash("node-D#3")
Каждый виртуальный узел это просто хеш от строки с суффиксом. Это приводит к тому, что один физический узел будет представлен в нескольких местах на кольце - и получит ключи с разных участков, выравнивая нагрузку. Конечно, под капотом у реальных систем все гораздо сложнее, но у нас и нет цели тут построить DynamoDB.
Поиграться с симулятором consistent hashing можно тут https://consistent-hashing.simulators.devopsbrain.ru. В симуляторе вы можете добавить/удалить узлы, увидеть, как перераспределяются ключи.
UPD: оказывается версия на мобилках работала криво - поправил.
🔥12👍1🤔1
Как же меня бесят статьи на популярных ресурсах (которые еще и набирают кучу лайков) от горе vps-хостеров в духе “Как всего за 139 рублей в месяц развернуть свой сайт-визитку на vps”. Какие нафиг 139 рублей за сайт-визитку?! Вы чего, ребятушки, совсем уже стыд потеряли?! Надо исправлять это недоразумение.
В этой статье я вам расскажу как бесплатно (ну или до тех пор пока github не прикроют) разместить и вести ваш личный сайт, блог, cv странички, личной вики. Вам даже отдельный домен не нужен (все будет “из коробки”), хотя никто не мешает и свой домен натравить на ваш сайт.
Краткий план наш будет такой: создаем специальную репку, ставим локально генератор статических сайтов и генерим странички, немного магии github actions и профит! В основе всего будет GitHub Pages - бесплатный хостинг статических сайтов, который позволяет автоматически публиковать сайт из репозитория GitHub.
Я буду поднимать персональный блог с CV. И я хочу чтобы мой сайт был доступен по красивому адресу https://itcaat.github.io. Тут надо понимать что занять вы можете адрес только с именем вашего аккаунта. У меня аккаунт на github: itcaat.
# Шаг 1. Создаем новый репозиторий c именем itcaat.github.io.
Важно чтобы он имел именно формат: ACCOUNT_NAME.github.io, чтобы хост itcaat.github.io смотрел именно на этот репозиторий. Далее выставляем в настройки репозитория->Pages->Source=Github Actions. Больше никакие настройки не трогаем. На данном этапе у нас будет просто пустой репозиторий без файлов и бранчей.
# Шаг 2. Перейдите в каталог в котором хотите создать сайт и выполните команду создания нового сайта.
# Ставим генератор статических сайтов hugo
# https://gohugo.io/installation/ - здесь можете выбрать под свою OS
brew install hugo
# Будет создан каталог itcaat.github.io и нужная структура внутри
cd ~/Documents/my
hugo new site itcaat.github.io
Давайте добавим эти файлы в созданный репозиторий и зальем их. Так нам будет проще видеть историю изменений. Заранее создадим .gitignore.
cd itcaat.github.io
cat <<EOF >.gitignore
public
EOF
git init
git add .
git commit -m "mvp"
git branch -M main
git remote add origin git@github.com:itcaat/itcaat.github.io.git
git push -u origin main
# Шаг 3. Теперь заглянем в магазин тем и выберем ту что вам подходит. Мне нравится минимализм, поэтому я остановился на https://github.com/athul/archie.
# Подключим его как сабмодуль
git submodule add https://github.com/athul/archie.git themes/archie
# Шаг 4. Почти все темы содержат пример сайта со всеми необходимыми параметрами для корректной работы темы. Давайте перенесем контент и настройки из exampleSite в корень нашего репозитория.
cp -R themes/archie/exampleSite/* ./
# Обычно в exampleSite настройки лежат в config.toml.
# Поэтому нам надо переложить их в hugo.toml чтобы генератор увидел настройки
mv ./config.toml ./hugo.toml
git add . && git commit -m "added theme athul archie" && git push
Поздравлю, мы уже можем сгенерировать сайт локально и посмотреть что у мы имеем на данный момент. Тут важно понимать что сервер поднимается просто для локального тестирования - он просто собирает все воедино из css, тем и md-файлов.
hugo server --buildDrafts
# Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
# Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
# Press Ctrl+C to stop
Открываем http://localhost:1313/ и смотрим что все корректно работает.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤🔥1
“Но тут же чужие посты и контакты!” скажете вы. Cейчас это поправим. За то что мы видим на сайте отвечают файлы внутри content и файл конфигурации hugo.toml. Я не хочу подробно тут останавливаться на hugo.toml - там все интуитивно понятно. У меня будет примерно будет так:
baseURL = "https://itcaat.github.io"
title = "ItCaat personal blog and CV"
....
[[params.social]]
name = "GitHub"
icon = "github"
url = "https://github.com/itcaat"
[[params.social]]
name = "Twitter"
icon = "twitter"
url = "https://x.com/itcaat"
....
# Шаг 5. Теперь давайте вернемся к наполнению. Тут надо понимать две простые вещи: все одержимое вашего сайта находится в content и все содержимое это обычные md-файлы из которых в дальнейшем генерируется сайт.
Вы можете отредактировать, создать и удалить текущие посты как вам нравится. Ну и отредактируйте about.md.
# Новые посты рекомендуется создавать через команду.
# По-умолчанию пост создает в draft и не будет опубликован.
# Draft версия доступна только при локальном запуске hugo.
# Когда пост будет финально готов - то просто удалите draft: true
hugo new posts/kak-kakat.md
Мы подошли к финалу - публикация нашего сайта. Давайте запустим его, проверим что нам все нравится и зальем финальные правки.
hugo server --buildDrafts
git add . && git commit -m "ready for release" && git push
# Шаг 6. Доверим всю работу по публикации github actions. Для этого просто закинем в .github/workflows/hugo.yml содержимое ниже и commit push. Данный файл сделает всю грязную работу и опубликует наш сайт.
# .github/workflows/hugo.yml
name: Deploy Hugo site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
# Default to bash
defaults:
run:
shell: bash
jobs:
# Build job
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.145.0
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install Dart Sass
run: sudo snap install dart-sass
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: Build with Hugo
env:
HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
HUGO_ENVIRONMENT: production
run: |
hugo \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Заливаем правки по github actions и дожидаемся публикации нашего сайта.
git add . && git commit -m "github actions" && git push
Поздравляю, у вас бесплатный сайт/блог/wiki/cv доступный по адресу https://itcaat.github.io. Для тех кому лень разбираться в деталях и вы хотите такой же сайт в таком же исполнении - просто форкайте репу https://github.com/itcaat/itcaat.github.io
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍18🔥7❤1
✨️️️️️️️ Иллюзия приватности: как мы доверились ИИ без оглядки
Кажется, ещё вчера искусственный интеллект был чем-то из фильмов и фантазий. А сегодня - он везде: в чатах, в рабочих инструментах, в личных помощниках. Мы удивительно легко впустили его в свою жизнь - с интересом, с восхищением, с доверием.
Мы отправляем в ИИ-сервисы документы, пароли, переписки, исходный код. Мы делимся внутренними обсуждениями, стратегиями, личными вопросами. Как только видим громкую новость о появлении очередной программы или сервиса который должен упростить нам жизнь - бежим его ставить и без оглядки даем доступы до всего что новоустановленный тул может дотянуться.
Мы ведём себя так, будто это безопасное пространство. Будто есть некий невидимый контракт: "Ты такой классный помошник, я тебе доверяю".
Только проблема в том, что контракта нет. И гарантий тоже нет. Мы не читаем политику конфиденциальности. Не задумываемся, где хранятся эти данные, кто их видит, кто их анализирует. Мы верим в иллюзию приватности - просто потому, что интерфейс красивый, а ответ кажется умным.
Но ИИ не магия. И под капотом там инфраструктура и люди, которые ее обслуживают. А инфраструктура ломается. Сливается. Продаётся. Взламывается.
И здесь компании оказываются зажатыми в тиски: отказаться от использования инструментов ИИ невозможно - тебя просто выкинут с рынка конкуренты, которые запустили процессы интеграции с ИИ и стали эффективно их использовать. С другой стороны активное использование подразумевает передачу чувствительной информации в лапы ИИ. К тому же, компания не может запретить сотрудникам использовать инструменты ИИ, которые ему приглянусь и которые он считает очень удобными.
Что можно и нужно сделать компаниям прямо сейчас?
1. Определить политики использования ИИ. Чётко зафиксировать, какие данные можно и нельзя передавать в ИИ-инструменты, особенно внешние.
2. Обучать сотрудников. Рассказывать не только о возможностях ИИ, но и о рисках. Показывать реальные кейсы утечек.
3. Использовать self-hosted и on-prem решения. Там, где это возможно - разворачивать модели локально, контролируя окружение.
4. Анализировать политику конфиденциальности используемых сервисов. Проверять, передаются ли данные третьим сторонам, используются ли они для обучения моделей.
5. Инвентаризировать, какие ИИ-сервисы уже используются в компании. "Теневой ИИ" - это как теневой IT: опасен, если не знаете, где он уже работает.
ИИ даёт мощные возможности. Но без здравого смысла и защиты данных - это всего лишь ещё один путь к новой форме утечки.
Кажется, ещё вчера искусственный интеллект был чем-то из фильмов и фантазий. А сегодня - он везде: в чатах, в рабочих инструментах, в личных помощниках. Мы удивительно легко впустили его в свою жизнь - с интересом, с восхищением, с доверием.
Мы отправляем в ИИ-сервисы документы, пароли, переписки, исходный код. Мы делимся внутренними обсуждениями, стратегиями, личными вопросами. Как только видим громкую новость о появлении очередной программы или сервиса который должен упростить нам жизнь - бежим его ставить и без оглядки даем доступы до всего что новоустановленный тул может дотянуться.
Мы ведём себя так, будто это безопасное пространство. Будто есть некий невидимый контракт: "Ты такой классный помошник, я тебе доверяю".
Только проблема в том, что контракта нет. И гарантий тоже нет. Мы не читаем политику конфиденциальности. Не задумываемся, где хранятся эти данные, кто их видит, кто их анализирует. Мы верим в иллюзию приватности - просто потому, что интерфейс красивый, а ответ кажется умным.
Но ИИ не магия. И под капотом там инфраструктура и люди, которые ее обслуживают. А инфраструктура ломается. Сливается. Продаётся. Взламывается.
И здесь компании оказываются зажатыми в тиски: отказаться от использования инструментов ИИ невозможно - тебя просто выкинут с рынка конкуренты, которые запустили процессы интеграции с ИИ и стали эффективно их использовать. С другой стороны активное использование подразумевает передачу чувствительной информации в лапы ИИ. К тому же, компания не может запретить сотрудникам использовать инструменты ИИ, которые ему приглянусь и которые он считает очень удобными.
Безопасники: Василий, мы обнаружили утечку данных и следы ведут к вам!
Василий: Но я просто промтил…
Безопасники: А, ну тогда все в порядке, извините за беспокойство.
Что можно и нужно сделать компаниям прямо сейчас?
1. Определить политики использования ИИ. Чётко зафиксировать, какие данные можно и нельзя передавать в ИИ-инструменты, особенно внешние.
2. Обучать сотрудников. Рассказывать не только о возможностях ИИ, но и о рисках. Показывать реальные кейсы утечек.
3. Использовать self-hosted и on-prem решения. Там, где это возможно - разворачивать модели локально, контролируя окружение.
4. Анализировать политику конфиденциальности используемых сервисов. Проверять, передаются ли данные третьим сторонам, используются ли они для обучения моделей.
5. Инвентаризировать, какие ИИ-сервисы уже используются в компании. "Теневой ИИ" - это как теневой IT: опасен, если не знаете, где он уже работает.
ИИ даёт мощные возможности. Но без здравого смысла и защиты данных - это всего лишь ещё один путь к новой форме утечки.
🔥12👍2👏2
Котлеги, привет. Сегодня без длинных постов - но я не могу не рассказать про https://github.com/ripienaar/free-for-dev.
Это просто клад - тысячи бесплатных сервисов и инструментов для ойтишников: хостинги, CI/CD, мониторинг, базы данных и многое другое. И самое главное что не триалы, а реально бесплатные тарифы (с ограничениями, но без внезапных счетов).
Если вы запускаете pet-проект, MVP или просто хотите сэкономить на инфраструктуре - must-have в закладках.
P.S. Если вы уже что-то используете оттуда - напишите, что зашло. 🤘
Это просто клад - тысячи бесплатных сервисов и инструментов для ойтишников: хостинги, CI/CD, мониторинг, базы данных и многое другое. И самое главное что не триалы, а реально бесплатные тарифы (с ограничениями, но без внезапных счетов).
Если вы запускаете pet-проект, MVP или просто хотите сэкономить на инфраструктуре - must-have в закладках.
P.S. Если вы уже что-то используете оттуда - напишите, что зашло. 🤘
GitHub
GitHub - ripienaar/free-for-dev: A list of SaaS, PaaS and IaaS offerings that have free tiers of interest to devops and infradev
A list of SaaS, PaaS and IaaS offerings that have free tiers of interest to devops and infradev - ripienaar/free-for-dev
👍8👀7❤3🔥1