Павел Селиванов, архитектор решений Southbridge и преподаватель Слёрма, выступил с докладом на DevOpsConf 2019. Этот доклад — часть одной из тем углубленного курса по Kubernetes «Слёрм Мега».


Слёрм Базовый: введение в Kubernetes проходит в Москве 18-20 ноября.
Слёрм Мега: заглядываем под капот Kubernetes — Москва, 22-24 ноября.
Слёрм Онлайн: оба курса по Kubernetes доступен всегда.



Под катом — расшифровка доклада.


Доброго дня, коллеги и им сочувствующие. Сегодня я буду рассказывать про безопасность.


Я вижу, что в зале сегодня много безопасников. Я заранее перед вами извиняюсь, если термины из мира безопасности я буду использовать не совсем так, как у вас принято.


Так получилось, что где-то полгода назад мне в руки попал один публичный кластер Kubernetes. Публичный — означает, что там есть n-ное количество namespaces, в этих неймспейсах есть users, изолированные в своём неймспейсе. Все эти юзеры принадлежат разным компаниям. Ну, и предполагалось, что этот кластер нужно использовать как CDN. То есть вам дают кластер, дают туда пользователя, вы туда приходите в свой namespace, деплоите свои фронты.


Моей предыдущей компании попытались такую услугу продать. И меня попросили потыкать кластер на предмет — подходит или не подходит такое решение.


Пришёл я в этот кластер. Мне дали ограниченные права, ограниченный namespace. Там ребята понимали, что такое безопасность. Они читали, что такое Role-based access control (RBAC) у Кубернетеса — и они его закрутили так, что я не мог запускать поды отдельно от деплойментов. Не помню задачу, которую я пытался решить, запуская под без деплоймента, но мне очень хотелось запустить просто под. Я решил на удачу посмотреть, какие права у меня в кластере есть, что я могу, что не могу, что они там понакрутили. Заодно расскажу, что у них в RBAC настроено неправильно.


Так получилось, что через две минуты я получил админа к их кластеру, посмотрел во все соседние namespaces, увидел там запущенные продакшн фронты компаний, которые уже купили услугу и задеплоились. Я еле остановил себя, чтобы не прийти к кому-нибудь во фронт и на главную страницу не поместить какое-нибудь матерное слово.


Я расскажу на примерах, как я это сделал и как от этого надо защищаться.


Но для начала представлюсь. Меня зовут Павел Селиванов. Я архитектор компании Southbridge. Я разбираюсь в Kubernetes, DevOps и всяких модных штуках. Мы с инженерами Southbridge всё это строим, а я консультирую.


Помимо основной деятельности мы ещё недавно запустили проекты, которые называются Слёрмы. Мы наше умение работать с Kubernetes пытаемся немного привнести в массы, научить других людей тоже работать с К8s.


О чём я буду сегодня рассказывать. Тема доклада очевидна — про безопасность кластера Kubernetes. Но сразу хочу сказать, что эта тема очень большая — и потому я сразу хочу оговорить, о чём я точно рассказывать не буду. Я не буду рассказывать про заезженные термины, которые в интернете уже сто раз перемусолены. Всякие RBAC и сертификаты.


Я буду рассказывать о том, что у меня и у моих коллег болит от безопасности в кластере Kubernetes. Мы эти проблемы видим и у провайдеров, которые предоставляют кластера Kubernetes, и у клиентов, которые к нам приходят. И даже у клиентов, которые приходят к нам от других консалтинговых админских компаний. То есть масштаб трагедии очень большой на самом деле.


Буквально три пункта, о которых я сегодня расскажу:


  1. Права пользователеи? vs права pod’ов. Права пользователей и права подов — это не одно и то же.
  2. Сбор информации о кластере. Покажу, что из кластера можно собирать всю информацию, которая понадобится, не имея особых прав в этом кластере.
  3. DoS-атака на кластер. Если мы не сможем собирать информацию, мы сможем кластер положить в любом случае. Я расскажу про DoS-атаки на управляющие элементы кластера.

Ещё одна общая вещь, о которой я упомяну — на чём я всё это тестировал, на чём я точно могу сказать, что всё это работает.


За основу мы берём установку кластера Kubernetes с помощью Kubespray. Если кто-то не знает, это фактически набор ролей для Ansible. Мы в работе его постоянно используем. Хорош тем, что можно накатить куда угодно — и на железки можно накатить, и куда-нибудь в облако. Один способ установки подходит в принципе для всего.


В этом кластере у меня будет Kubernetes v1.14.5. Весь кластер Куба, который мы будем рассматривать, поделен на неймспейсы, каждый неймспейс принадлежит отдельной команде, в каждый неймспейс есть доступ у членов этой команды. В разные неймспейсы они ходить не могут, только в свой. Но есть некая админская учётка, у которой есть права на весь кластер.



Я обещал, что первое у нас будет — получение админских прав на кластер. Нам нужен специально подготовленный pod, который будет ломать кластер Kubernetes. Всё, что нам нужно сделать, это применить его в кластер Кубернетес.


kubectl apply -f pod.yaml

Этот pod у нас приедет на один из мастеров кластера Kubernetes. И кластер нам после этого радостно вернёт файлик, который называется admin.conf. В Кубе в этом файле хранятся все сертификаты админа, а заодно настроен API кластера. Вот так просто можно получить админский доступ, думаю, к 98% кластеров Kubernetes.


Повторюсь, этот pod сделал один разработчик в вашем кластере, у которого есть доступ деплоить свои предложения в один маленький namespace, он весь зажат RBAC. Прав у него никаких не было. Но тем не менее сертификат вернулся.


А теперь о специально подготовленном поде. Запускаем на любом образе. Для примера возьмём debian:jessie.


У нас есть такая штука:


tolerations:
-   effect: NoSchedule 
    operator: Exists 
nodeSelector: 
    node-role.kubernetes.io/master: "" 

Что такое toleration? Мастера в кластере Кубернетеса обычно помечены штукой, которая называется taint («зараза» по-английски). И суть этой «заразы» — она говорит, что на мастеровые ноды нельзя назначать поды. Но никто не мешает в любом поде указать, что он толерантен к «заразе». Секция Toleration как раз и говорит, что если на какой-то ноде стоит NoSchedule, то наш под к такой заразе толерантен — и никаких проблем.


Дальше, мы говорим, что наш под не просто толерантен, но и хочет специально попадать на мастера. Потому что на мастерах находится самое вкусное, что нам нужно — все сертификаты. Поэтому мы говорим nodeSelector — и у нас есть стандартный лейбл на мастерах, который позволяет выбрать из всех нод кластера именно те ноды, которые являются мастерами.


Вот с такими двумя секциями под точно приедет на мастер. И ему разрешат там жить.


Но просто приехать на мастер нам недостаточно. Это нам ничего не даст. Поэтому далее у нас есть такие две вещи:


hostNetwork: true 
hostPID: true 

Мы указываем, что наш под, который мы запускаем, будет жить в неймспейсе ядра, в network неймспейсе и в PID неймспейсе. Как только под запустится на мастере, он сможет видеть все настоящие, живые интерфейсы этой ноды, прослушивать весь трафик и видеть PID всех процессов.


Далее дело за малым. Берете etcd и читаете, что хотите.


Самое интересное — эта возможность Kubernetes, которая там по умолчанию присутствует.


volumeMounts:
- mountPath: /host 
  name: host 
volumes:
- hostPath: 
    path: / 
    type: Directory 
  name: host 

И суть её в том, что мы можем в поде, который мы запускаем, даже без прав на этот кластер, сказать, что мы хотим создать volume типа hostPath. Значит взять путь с хоста, на которым мы запустимся — и взять его как volume. И дальше его обзываем name: host. Весь этот hostPath мы монтируем внутрь пода. В данном примере в директорию /host.


Ещё раз повторюсь. Мы сказали поду приезжать на мастер, получать туда hostNetwork и hostPID — и весь root мастера замонтировать внутрь этого пода.


Вы понимаете, что в дебиане у нас запущен bash, и этот bash у нас работает под рутом. То есть мы только что получили рута на мастер, при этом не обладая какими-то правами в кластере Kubernetes.


Дальше вся задача — зайти в под в директорию /host /etc/kubernetes/pki, если не ошибаюсь, забрать там все мастеровые сертификаты кластера и, соответственно, стать админом кластера.


Если так посмотреть, это одни из самых опасных прав в подах — несмотря на то, какие права есть у пользователя:


Если у меня есть права запустить под в каком-то неймспейсе кластера, то у этого пода эти права есть по умолчанию. Я могу запускать привилегированные поды, а это вообще все права, практически рут на ноду.


Моё любимое — Root user. А у Кубернетеса есть такая опция Run As Non-Root. Это такая типа защита от хакера. Знаете, что такое «молдавский вирус»? Если вы вдруг хакер и пришли в мой кластер Кубернетес, то мы, бедные администраторы, просим: «Укажите, пожалуйста, в своих подах, которыми вы будете хакать мой кластер, run as non-root. А то так получится, что вы запустите процесс в своём поде под рутом, и вам очень просто будет меня хакнуть. Защититесь, пожалуйста, от себя сами».


Host path volume — на мой взгляд, самый быстрый способ получить желаемый результат от кластера Кубернетеса.


Но что со всем этим делать?


Мысли, которая должны приходить любому нормальному администратору, который сталкивается с Кубернетесом: «Ага, я же говорил, Кубернетес не работает. В нём дырки. И весь Куб фигня». На самом деле, есть такая штука, как документация, а если туда посмотреть, то там есть раздел Pod Security Policy.


Это такой yaml-объект — мы его можем создавать в кластере Кубернетес — который контролирует аспекты безопасности именно в описании подов. То есть фактически он контролирует те права на использование всяких hostNetwork, hostPID, определённых типов volume, которые есть в подах при запуске. С помощью Pod Security Policy всё это можно описать.


Самое интересное в Pod Security Policy, что в кластере Кубернетеса у всех установщиков PSP не просто никак не описаны, они просто по умолчанию выключены. Pod Security Policy включается с помощью admission plugin.


Окей, в кластер задеплоим Pod Security Policy, скажем, что у нас есть служебные некие поды в неймспейсе, к которому имеют доступ только админы. Скажем, во всех остальных поды имеют ограниченные права. Потому что скорее всего разработчикам не нужно запускать в вашем кластере привилегированные поды.


И у нас вроде всё хорошо. И наш кластер Кубернетес нельзя взломать за две минуты.


Есть проблема. Скорее всего, если у вас есть кластер Кубернетес, то в вашем кластере установлен мониторинг. Я даже берусь предсказать, что если в вашем кластере есть мониторинг, то он называется Prometheus.


То, что я сейчас расскажу, будет валидно и для Prometheus-оператора, и для Prometheus, поставленного в чистом виде. Вопрос в том, что если я в кластер не могу так быстро админа получить, то это означает, что мне нужно больше искать. А искать я могу с помощью вашего мониторинга.


Вероятно, все читали одни и те же статьи на Хабре, и мониторинг находится в неймспейсе monitoring. Helm chart у всех называется примерно одинаково. Я предполагаю, что если вы сделаете helm install stable/prometheus, то у вас получаться примерно одинаковые названия. И даже скорее всего DNS-имя в вашем кластере мне угадывать не придётся. Потому что оно стандартное.



Дальше у нас есть некий dev ns, в нём можно запустить некий под. И дальше из этого пода очень легко сделать вот так:


$ curl http://prometheus-kube-state-metrics.monitoring 

prometheus-kube-state-metrics — это один из экспортеров прометеуса, который собирает метрики из API самого Kubernetes. Там очень много данных, что запущено у вас в кластере, какое оно, какие у вас с ним есть проблемы.


Как простой пример:


kube_pod_container_info{namespace=«kube-system",pod="kube-apiserver-k8s- 1",container="kube-apiserver",image=


"gcr.io/google-containers/kube-apiserver:v1.14.5"


,image_id="docker-pullable://gcr.io/google-containers/kube- apiserver@sha256:e29561119a52adad9edc72bfe0e7fcab308501313b09bf99df4a96 38ee634989",container_id="docker://7cbe7b1fea33f811fdd8f7e0e079191110268f2 853397d7daf08e72c22d3cf8b"} 1


Сделав простой запрос curl из непривилегированного пода, можно получить такую вот информацию. Если вы не знаете, в какой версии Кубернетес вы запущены, то он легко вам расскажет.


А самое интересное, что кроме того, что вы обращаетесь к kube-state-metrics, вы можете с тем же успехом обратиться и в сам Prometheus напрямую. Вы можете собрать оттуда метрики. Вы даже можете построить оттуда метрики. Даже теоретически вы можете построить такой запрос из кластера в Prometheus, который его просто выключит. И у вас мониторинг вообще перестанет от кластера работать.


И тут уже возникает вопрос, мониторит ли какой-нибудь внешний мониторинг ваш мониторинг. Только что я получил возможность действовать в кластере Кубернетес вообще без последствий для себя. Вы даже не узнаете, что я там действую, так как мониторинга уже нет.


Точно так же, как с PSP, возникает ощущение, будто бы проблема в том, что все эти модные технологии — Kubernetes, Prometheus — они просто не работают и полны дырок. На самом деле нет.


Есть такая штука — Network Policy.


Если вы нормальный админ, то скорее всего про Network Policy вы знаете, что это очередной yaml, которых в кластере и так дофига. И Network Policies какие-то точно не нужны. А если даже вы и прочитали, что такое Network Policy, что это yaml-файервол Кубернетеса, он позволяет ограничивать права доступа между неймспейсами, между подами, то вы уж точно решили, что файервол в формате yaml в Кубернетесе на очередных абстракциях… Не-не. Это точно не нужно.


Даже если у вас специалистам по безопасности не рассказали, что с помощью вашего Кубернетеса можно строить очень легко и просто файервол, причём очень гранулированный. Если они у вас ещё этого не знают и вас не дёргают: «Ну дайте, дайте…» То в любом случае Network Policy вам нужно, чтобы закрывать доступ к некоторым служебным местам, которые можно из вашего кластера подёргать, не имея никакой авторизации.


Как в примере, который я приводил, можно подёргать kube state metrics из любого неймспейса в кластере Кубернетес, не имея на это никаких прав. Network policies закрыли доступ из всех остальных неймспейсов в неймспейс мониторинга и как бы всё: нет доступа, нет проблем. Во всех чартах, которые есть, и стандартного прометеуса, и того прометеуса, который в операторе, там просто в values хелма есть опция просто включить network policies для них. Нужно просто включить, и они будут работать.


Есть тут правда одна проблема. Будучи нормальным бородатым админом, вы скорее всего решили, что network policies не нужны. И почитав всякие статьи на ресурсах типа Хабра, вы решили, что flannel особенно с режимом host-gateway — это самое лучшее, что вы можете выбрать.


Что делать?


Вы можете попробовать передеплоить сетевое решение, которое стоит у вас в кластере Кубернетес, попробовать заменить на что-то более функциональное. На то же самое Calico, например. Но сразу же хочу сказать, задача поменять сетевое решение в рабочем кластере Кубернетес — довольно нетривиальная. Я её два раза решал (оба раза, правда, теоретически), но мы даже на Слёрмах показывали, как это сделать. Для наших обучаемых мы показывали, как поменять сетевое решение в кластере Кубернетес. В принципе можете попробовать сделать так, чтобы на продакшн-кластере даунтайма не было. Но вероятно у вас ничего не получится.


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


Когда будете новый кластер поднимать, заодно Calico вставьте вместо flannel.


Что делать если у вас сертификаты выписаны на сто лет и кластер вы передеплоивать не собираетесь? Есть такая штука Kube-RBAC-Proxy. Это очень классная разработка, она позволяет встроить себя, как sidecar container к любому поду в кластере Кубернетес. И она фактически добавляет к этому поду авторизацию через RBAC самого Kubernetes.


Одна проблема есть. Раньше в прометеус оператора это решение Kube-RBAC-Proxy было встроено. Но его потом не стало. Сейчас современные версии опираются на то, что у вас есть network policу и закрываете с помощью них. И поэтому придётся немного переписать чартом. На самом деле если вы зайдёте в этот репозиторий, там есть примеры, как это использовать как sidecars, и чарты придётся переписать минимально.


Есть ещё одна небольшая проблема. Не только Prometheus отдаёт свои метрики кому ни попадя. У нас все компоненты кластер Кубернетес тоже свои метрики умеют отдавать.


Но как я уже говорил, если не можешь получить доступ к кластеру и собрать информацию, то можно хотя бы навредить.


Так что я быстренько покажу два способа, как можно кластеру Kubernetes испортить здоровье.


Вы будете смеяться, когда я это расскажу, это два случая из реальной жизни.


Способ первый. Исчерпание ресурсов.


Запускаем ещё один специальный под. У него будет вот такая секция.


resources: 
    requests: 
        cpu: 4 
        memory: 4Gi 

Как вы знаете, requests — это то количество ЦПУ и памяти, которое на хосте резервируется для конкретных подов с реквестами. Если у нас есть четырёхядерный хост в кластере Кубернетес, и туда приезжает под с реквестами четыре по ЦПУ, то значит ни одного больше пода с реквестами на этот хост приехать не сможет.


Если я запущу такой под, потом сделаю команду:


$ kubectl scale special-pod --replicas=...

То больше никто в кластер Кубернетес деплоиться не сможет. Потому что во всех нодах закончатся реквесты. И таким образом я ваш кластер Kubernetes остановлю. Если я вечерком такое сделаю, то деплои могу остановить довольно надолго.


Если мы посмотрим в очередной раз в документацию Kubernetes, то мы увидим такую штуку, которая называется Limit Range. Он устанавливает ресурсы для объектов кластера. Вы можете написать в yaml объект Limit Range, применить его в определённые неймспейсы — и дальше в этом неймспейсе вы можете сказать, что у вас есть ресурсы для подов дефолтные, максимальные и минимальные.


С помощью такой штуки мы можем ограничить пользователей в конкретных продуктовых неймспейсах команд в возможностях указывать на своих подах всякую гадость. Но к сожалению, даже если вы скажете пользователю, что нельзя запускать поды с реквестами больше одного ЦПУ, есть такая замечательная команда scale, ну или через dashboard они могут делать scale.


И отсюда проистекает способ номер два. Запускаем 11 111 111 111 111 подов. Это одиннадцать миллиардов. Это не потому, что я придумал такое число, а потому что я сам это видел.


Реальная история. Поздним вечером я уже собирался уходить из офиса. Смотрю, в уголке сидит группка разработчиков и что-то судорожно с ноутбуками делает. Я подхожу к ребятам и спрашиваю: «Что у вас случилось?»


Чуть пораньше, часов в девять вечера один из разработчиков собирался домой. И решил: «Я сейчас своё приложению заскейлю до единички». Нажал единичку, а интернет немножко затупил. Он ещё раз нажал на единичку, он надавил на единичку, клацнул по Enter. Потыкал на всё, что мог. Тут интернет ожил — и всё начало скейлиться до этого числа.


Правда, эта история происходила не на Kubernetes, на тот момент это был Nomad. Закончилось это тем, что через час наших попыток остановить Nomad от упорных попыток скейлиться, Nomad ответил, что скейлиться не перестанет и ничем другим заниматься не будет. «Я устал, я ухожу». И свернулся.


Я естественно попробовал сделать то же самое на Kubernetes. Одиннадцать миллиардов подов Кубернетес не обрадовали, он сказал: «Не могу. Превышает внутренние капы». А вот 1 000 000 000 подов смог.


В ответ на один миллиард Куб в себя не ушёл. Он действительно начал скейлить. Чем дальше процесс заходил, тем больше времени у него уходило на создание новых подов. Но всё равно процесс шёл. Единственная проблема в том, что если я могу в своём неймспейсе неограниченно запускать поды, то даже без реквестов и лимитов я могу позапускать с какими-то задачами такое количество подов, что с помощью этих задач ноды начнут складываться по памяти, по ЦПУ. Когда я запускаю столько подов, информация из них должна попасть в хранилище, то бишь etcd. А когда туда поступает слишком много информации, хранилище начинает слишком медленно отдавать — и у Кубернетеса начинаются затупы.


А ещё одна проблема… Как знаете, управляющие элементы Кубернетес — это не одна какая-то центральная штуковина, а несколько компонентов. Там в частности есть контроллер менеджер, scheduler и так далее. Все эти ребята начнут выполнять одновременно ненужную бестолковую работу, которая со временем начнёт занимать всё больше и больше времени. Контроллер менеджер будет новые поды создавать. Scheduler будет пытаться найти им новую ноду. Новые ноды у вас в кластере, скорее всего, скоро закончатся. Кластер Кубернетес начнёт работать всё медленнее и медленнее.


Но я решил пойти ещё дальше. Как вы знаете, в Кубернетес есть такая штука, которая называется сервис. Ну, и по умолчанию в ваших кластерах, скорее всего, сервис работает с помощью IP tables.


Если запустить один миллиардов подов, к примеру, а потом с помощью скриптика заставить Кубернетис создавать новые сервисы:


for i in {1..1111111}; do
    kubectl expose deployment test --port 80 \ 
        --overrides="{\"apiVersion\": \"v1\", 
           \"metadata\": {\"name\": \"nginx$i\"}}"; 
done 

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


Я это всё дело проверял на несколько тысячах, до десятка. И проблема в том, что уже на этом пороге ssh на ноду сделать довольно проблематично. Потому что пакеты, проходя такое количество цепочек, начинают не очень хорошо себя чувствовать.


И это тоже всё решается с помощью Кубернетеса. Есть такой объект Resource quota. Устанавливает количество доступных ресурсов и объектов для неи?мспеи?са в кластере. Мы можем создать yaml объект в каждом неймспейсе кластера Кубернетес. С помощью этого объекта мы можем сказать, что у нас для этого неймспейса выделено определённое количество реквестов, лимитов, и дальше мы можем сказать, что в этом нейспейсе возможно создать 10 сервисов и 10 подов. И разработчик единичкой может хоть обдавиться по вечерам. Кубернетес ему скажет: «Нельзя заскейлить ваши поды до такого количества, потому что превышает ресурс квоту». Всё, проблема решена. Документация тут.


Один проблемный момент в связи с этим возникает. Вы чувствуете, как сложно становится создать в Кубернетесе неймспейс. Чтобы его создать, нам необходимо кучу всего учесть.


Resource quota + Limit Range + RBAC
• Создаем namespace
• Создаем внутри limitrange
• Создаем внутри resourcequota
• Создаем serviceaccount для CI
• Создаем rolebinding для CI и пользователеи?
• Опционально запускаем нужные служебные поды


Поэтому пользуясь случаем, я хотел бы поделиться своими разработками. Есть такая штука, называется оператор SDK. Это способ в кластере Кубернетес писать для него операторы. Вы можете писать операторы с помощью Ansible.


Сначала у нас было написано на Ansible, а потом я посмотрел, что есть оператор SDK и переписал Ansible-роль в оператор. Этот оператор позволяет создать в кластере Кубернетес объект, который называется команда. Внутри команды он позволяет описывать в yaml окружение для этой команды. И внутри окружения команды он позволяет описывать, что мы выделяем столько-то ресурсов.


Маленькая облегчалка всего этого сложного процесса.


И в заключении. Что со всем этим делать?
Первое. Pod Security Policy — это хорошо. И не смотря на то, что ни один из установщиков Кубернетес по сей день их не использует, всё-таки в ваших кластерах их использовать нужно.


Network Policy — это не какая-то еще одна ненужная фича. Это то, что в кластере реально нужно.


LimitRange/ResourceQuota — пора бы использовать. Мы давно начали этим пользоваться, и я долго был уверен, что все поголовно это применяют. Оказалось, что это редкость.


Помимо того, что я упоминал в ходе доклада, есть незадокументированные фичи, которые позволяют атаковать кластер. Вышел недавно большой анализ уязвимостей Кубернетес.


Некоторые вещи настолько печальные и обидные. Как например, при некоторых условиях кублеты в кластере Кубернетес могут отдавать содержимое warlocks директории, причём неавторизованному пользователю.


Тут лежат инструкции, как воспроизвести всё, что я рассказывал. Там лежат файлики с продакшн примерами, как ResourceQuota, Pod Security Policy выглядят. И всё это можно потрогать.


Всем спасибо.

Комментарии (14)


  1. vrutkovs
    22.10.2019 12:39

    Одна проблема есть. Раньше в прометеус оператора это решение Kube-RBAC-Proxy было встроено. Но его потом не стало. Сейчас современные версии опираются на то, что у вас есть network policу и закрываете с помощью них

    Да нет, вот же он — https://github.com/coreos/kube-prometheus/blob/master/jsonnet/kube-prometheus/kube-state-metrics/kube-state-metrics.libsonnet#L18


    1. pauljamm
      22.10.2019 13:02

      Да, ты прав. Действительно в jsonnetе сохранился.
      Мы пользуемся helm чартом, я только туда заглянул и не нашел.
      Ну тогда все еще проще, можно прям из jsonnet портировать в helm.


  1. gecube
    22.10.2019 13:00
    +1

    Отличный обзор из категории "вредные советы". Точнее — как делать не надо и как себя обезопасить. К сожалению, я подозреваю, что это только верхушка айсберга. И наверняка там под капотом еще куча более хитрых способов положить кластер. Какое может быть решение? Ну, или контроль. Или может быть просто из кластера не делать коммуналку? Каждому проекту по своему кластеру? Это не снимает вопросы ИБ, но по крайне мере снижает влияние пользователей-проектов друг на друга.
    Еще очень интересно Ваше отношение к опеншифту. Поясню. Дело в том, что, насколько мне известно, опеншифту форсит правильные стратегии вроде "не используйте рута в контейнерах", маппит польщователей докера в рандомные на хосте, форсит psp и сетевую изоляцию… И пр. А раз так, то нужно сразу учиться с этис жить. Это больно. Никто не спорит. Зато потом за продакшен можно не беспокоиться. Потому что если заходить с другого конца — вообще ванильный кластер без ничего, то вроде быстро вкатываешься, но потом уже довел продукт до состояния препрод, а оказывается, что там еще очень много работы по поведению его к состоянию, в котором его можно выпускать в дикий мир (именно по соображениям иб и пр.)


    1. gecube
      22.10.2019 13:12

      Добавлю, что при работе с кубернетесом потихоньку выкристаллизовываются какие-то лучшие практики работы с ним. Например, очень круто заводить все внешние ресурсы, которые необходимы как Service внутрь неймспейса. Более того — это практически сама оф. рекомендация от гуголь. Зачем так делать? А чтобы получить наблюдаемость. Сразу видишь от каких внешних по отношению к кластеру сущностей зависит твой сервис. А в случае необходимости — ее (внешнюю сущность) можно будет затащить в кластер без каких-либо проблем.


      Касательно уязвимостей — кластер, который апихой куда-либо смотрит — легко может эффективно использовать как ssh jump host внутрь корп. сети или DMZ…


    1. pauljamm
      22.10.2019 13:23
      +1

      По поводу обезопашивания кластера, я бы выделил н пунктов:
      1. Аутентификация компонентов кластера между собой по сертификатам.
      2. Наличие понятных механизмов ротации этих самых сертификатов и никаких сертификатов на 100 лет.
      3. Включенные аудит логи, настроенный их парсинг и алерты по полученным данным.
      4. Наличие понятного и рабочего механизма обновления кластера и его компонентов с возможностью производить это так часто как требуется.
      5. Настроенный файрвол для служебных портов кластера.
      6. Включенные и настроенные сетевые политики.
      7. Авторизация по RBAC, с пониманием и контролем прав в RBAC ролях.
      8. Авторизация внешних пользователей в кластер через центральное юзерохранилище компании (аля LDAP) с ролями и тд + какой нибудь OAuth (аля Dex).
      8. Включенные и настроенные PSP.
      9. Включенные и настроенные LimitRange и ResourceQuota для всех нэймспэйсов.
      10. Отдельные кластера для Dev/Stage и Prod.
      11. Доступ на запуск новых абстракций только у CI, причем с четким контролем конкретных прав и нэймспэйсов для каждого проекта CI.

      Это то что быстро в голову пришло. По идее этого должно хватить, чтобы ваша ИБ перестала прям уж сильно хвататься за голову. Но это все сильно прибавит работы Админам/Devops/SRE командам. Тут работает именно та диаграмма о которой я в докладе в начале говорил. Чем выше безопасность, тем ниже удобство.

      А по поводу OpenShift полностью согласен. Как всегда «в опеншифт это их коробки».
      Действительно там проведена огромная работа, и Кубернетис под копотом настроен по дефолту у них очень хорошо. Эти ребята читали документацию и занют о встроенных фичах Куба.

      Дальше обычно следует вопрос – а почему вы не используете Опеншифт?
      – Потому что я тоже читал документацию к Кубернетису и могу собрать под каждую задачу именно тот кластер, который мне нужен, а не тот который за меня преднастроил вендор, впилив сверху еще кучу своих костылей.


      1. gecube
        22.10.2019 13:40

        Дальше обычно следует вопрос – а почему вы не используете Опеншифт?
        – Потому что я тоже читал документацию к Кубернетису и могу собрать под каждую задачу именно тот кластер, который мне нужен, а не тот который за меня преднастроил вендор, впилив сверху еще кучу своих костылей.

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


        1. pauljamm
          22.10.2019 14:05
          +6

          Именно так.
          Кубернетис в компании это скорее всего отдельно выделенный инженер, а то и не один.
          Это постоянная досборка/пересборка конструктора. Это огромная инфраструктура, которая должна сопутствовать кластеру.
          Для небольшой компании, особенно исповедующей noops подходы это может стать непосильной задачей. Поэтому люди и выбирают всякие managed решения или Rancher и иже с ним (правда в последствии отгребая какие нибудь неожиданности от этих решений, которые потом не в состоянии никак починить, так как экспертизы то как не было так и нет, развернулось то все одной кнопкой).

          Плюсов конечно у Куба много, но это большая сложная система. И что бы там ни писали в англоязычных блогах, как это все просто и как стартапы из двух девелоперов строят кластера на 5000 машин с rps под миллион, это все неправда. И нужно отдавать себе отчет при внедрении таких продуктов как Кубернетис. Что ты хочешь от него получить и чем придется взамен пожертвовать (например большим куском бюджета на ЗП специалисту).

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


          1. rzerda
            22.10.2019 16:00
            +2

            Больше всего меня в этой истории радует то, что лет пять назад ровно такие же тексты писали про OpenStack. Только теперь Go вместо Python, контейнеры вместо ВМ. И даже портянки iptables правил и департаменты мостов и тоннелей по сути те же, чтобы обеспечивать это всё сетевой связностью.


            1. gecube
              22.10.2019 17:19

              Глядишь, еще лет через пять — будут так же говорить про noops, lambda, serverless


            1. Win32Sector
              23.10.2019 09:36

              А с OpenStack сейчас все еще хуже и специалистов все меньше, а существующие все дороже.


              1. gecube
                23.10.2019 10:43

                Эм… И это плохо? Специалистам, наверное, хорошо — не иссякнет пул заказов и работ для них )


  1. SONANT
    22.10.2019 18:42
    -1

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


    1. pauljamm
      22.10.2019 19:06
      +4

      Повышение привилегий или получение информации, которой ты не должен был по идее обладать осуществляется не всегда со злыми намерениями (хотя и часто как раз с ними, и изнутри это происходит чаще чем хотелось бы).
      Например в моей практике случались моменты, когда коллеги пользовались дырками во внутренних инфраструктурах для того чтобы эффективней выполнять свою работу. Зачем писать задачу админам, если ты получил себе доступ куда не нужно было и теперь можешь по-тихому сам выполнять нужные действия.
      Правда велика вероятность, что при этом такой сотрудник совершит рано или поздно какую нибудь ошибку (все таки при нормальном стечении обстоятельств изначальные ограничения были не просто так придуманы), которая в итоге может привести к очень плачевным последствиям. Хотя первоначальные цели этого «взлома» были как бы благими.
      И обычно тут начинается выяснение кто и куда влез, зачем он так действовал, разборки, выговоры и увольнения. А виновата как бы система, которая предоставляла доступ куда не нужно, кому не следует, а не сотрудник.

      А еще см. пример с 11 миллиардами контейнеров из доклада. Там вообще никакого умысла что то взламывать или портить не было. Систему сломал буквально несчастный случай.


      1. SONANT
        23.10.2019 10:43

        Согласен. Про доступ тут тоже двойная проблема, это еще и орг. момент. А так в статье действительно хорошие напоминалочки о защите от выстрела себе в ногу. Для себя оставил заметки на полях.