Русский
Русский
English
Статистика
Реклама

Pod

Разбор понятий trivial type, standard layout, POD

14.12.2020 16:17:31 | Автор: admin

Автор: Виталий Бутурлин

Содержание:

Trivial class

Тривиальные классы(trivial class) - это классы или структуры, в которых специальные функции-члены предоставляются компилятором (явно отсутствует реализация) либо явно заданы как default. В таком классенет управляющего кода, так как специальные функции-члены обьявлены (явно или неявно) тривиальными по умолчанию.

Кроме того есть дополнительные требования, тривиальный класс не должен иметь:

  • виртуальных функций

  • нетривиальных базовых классов

  • нетривиальных типов данных

Под словом "тривиальный" понимается наличие:

  • тривиальных специальных функций-членов (msdn)

  • POD членов(см. ниже)

Тривиальные классы могут быть безопасно скопированы функциями типа memcpy в полной точности.

Тривиальность функций членов (отсутсвие управляющего кода) подразумевает:

  • выделение памяти под обьект без инициализации

  • побайтовое копирование обьекта

  • освобождение памяти без очистки

Standard layout

Стандартная структура(standard layout) - это структура (struct), которая не содержит специальных возможностей C++:

  • виртуальные функции и виртуальные базовые классы

  • несколько уровней доступа (private, protected)

  • нестатические члены ссылочного типа

Стандартная структура:

  • не имеет члены являющиеся нестандартной структурой

  • не имеет базовые классы не являющиеся нестандартной структурой

  • не имеет более одного базового класса с нестатическими членами данных

  • не имеет двух мест обьявления нестатических членов (например в базовом классе и у себя)

  • не имеет более двух базовых (или косвенно) классов

Стандартная структура имеетпредсказуемое устройство памяти, так как не содержит данных, которые компилятор мог бы структурировать по своему усмотрению (например в случае наличия public/private/protected) -как написано так и храниться в памяти.

Автор: Виталий Бутурлин

Источник: https://byurrer.ru/konspektyi/razbor-ponyatij-trivial-standard-layout-pod.html

Подробнее..
Категории: Javascript , Java , Pod , Fermarunet

Перевод Как получить доступ к ресурсам Kubernetes Pod

11.09.2020 18:10:30 | Автор: admin
The Reward by Tohad

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

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

Команда Kubernetes aaS от Mail.ru перевела статью о ресурсах контейнеров (CPU & MEM), запросах и ограничениях ресурсов. Вы узнаете, какие преимущества дают эти настройки и что произойдет, если их не установить.

Вычислительные ресурсы


У нас есть два типа ресурсов со следующими единицами:

  • Центральный процессор (CPU) ядра;
  • Память (MEM) байты.

Ресурсы указывают для каждого контейнера. В следующем YAML-файле Pod вы увидите раздел ресурсов, который содержит запрошенные и предельные ресурсы:

  • Запрошенные ресурсы Pod = сумма запрошенных ресурсов всех контейнеров;
  • Предельные ресурсы Pod = сумма предельных ресурсов всех контейнеров.

apiVersion: v1kind: Podmetadata:  name: backend-pod-name  labels:    application: backendspec:  containers:     name: main-container      image: my-backend      tag: v1      ports:       containerPort: 8080      resources:        requests:          cpu: 0.2 # REQUESTED CPU: 200m cores          memory: "1Gi" # REQUESTED MEM: 1Gi        limits:          cpu: 1 # MAX CPU USAGE: 1 core          memory: "1Gi" # MAX MEM USAGE:  1Gi     name: other-container      image: other-app      tag: v1      ports:       containerPort: 8000      resources:        requests:          cpu: "200m" # REQUESTED CPU: 200m cores          memory: "0.5Gi" # REQUESTED MEM: 0.5Gi        limits:          cpu: 1 # MAX CPU USAGE: 1 core          memory: "1Gi" # MAX MEM USAGE:  1Gi
Пример запрошенных и предельных ресурсов

Поле resources.requested из спецификации Pod один из элементов, который используют для поиска нужной ноды. Уже на нее можно запланировать развертывание Pod. Как же ищут подходящую ноду?

Kubernetes состоит из нескольких компонентов, в том числе содержит главный узел или мастер-ноду (Kubernetes Control Plane). В мастере-ноде несколько процессов: kube-apiserver, kube-controller-manager и kube-scheduler.

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

Куда будет помещен фиолетовый Pod?

На картинке видно, что kube-scheduler должен запланировать новый фиолетовый Pod. Кластер Kubernetes содержит два узла: A и B. Как можно заметить, kube-scheduler не может запланировать Pod на узел A доступные (незапрошенные) ресурсы не соответствуют запросам фиолетового Pod. Так, запрошенный фиолетовым Pod 1 Гб памяти не уместится на узле А, поскольку доступный объем памяти 0,5 Гб. Но у узла В достаточно ресурсов. В итоге kube-scheduler решает, что место назначения фиолетового Pod узел B.

Теперь мы знаем, как запрошенные ресурсы влияют на выбор ноды для запуска Pod. Но как влияют предельные ресурсы?

Предельные ресурсы граница, которую CPU/MEM не может пересекать. Тем не менее ресурс CPU гибкий, поэтому контейнеры, достигшие предельных значений по CPU, не приведут к завершению работы Pod. Вместо этого запустится троттлинг по CPU. Если же будет достигнут предел по использованию MEM, то контейнер будет остановлен по причине OOM-Killer и перезапущен, если это разрешено настройкой RestartPolicy.

Запрашиваемые и предельные ресурсы в деталях


Связь ресурсов между Docker и Kubernetes

Лучший способ объяснить, как работают запрашиваемые и предельные ресурсы представить связь между Kubernetes и Docker. На рисунке выше вы можете посмотреть, как связаны поля Kubernetes и флаги запуска Docker.

Память: запрос и ограничение


containers:... resources:   requests:     memory: "0.5Gi"   limits:     memory: "1Gi"

Как упоминалось выше, память измеряется в байтах. Основываясь на документации Kubernetes, мы можем указать память в виде числа. Обычно оно целое, например 2678 то есть 2678 байт. Можно также использовать суффиксы G и Gi, главное помнить, что они не равнозначны. Первый десятичный, а второй двоичный. Как пример, упомянутый в документации k8s: 128974848, 129e6, 129M, 123Mi они практически эквивалентны.

Параметр Kubernetes limits.memory соответствует флагу --memory из Docker. В случае с request.memory стрелка для Docker отсутствует, поскольку Docker не использует это поле. Вы можете спросить, нужно ли это вообще? Да, нужно. Как я уже говорил, поле имеет значение для Kubernetes. На основе информации из него kube-scheduler решает, на какой узел запланировать Pod.

Что будет, если установить для запроса недостаточно памяти?

Если контейнер достиг границ запрошенной памяти, то Pod помещается в группу Pod, которые останавливаются при нехватке памяти в ноде.

Что произойдет, если установить слишком маленькое предельное значение памяти?

Если контейнер превышает предельное значение памяти, он будет завершен по причине OOM-Killed. И будет перезапущен, если это возможно на основании RestartPolicy, где значение по умолчанию Always.

Что будет, если не указать запрашиваемую память?

Kubernetes возьмет предельное значение и установит его как значение по умолчанию.

Что может произойти, если не указать предельную память?

У контейнера нет ограничений, он может использовать столько памяти, сколько захочет. Если же он начнет использовать всю доступную память ноды, то его убьет OOM. Затем контейнер будет перезапущен, если это возможно на основе RestartPolicy.

Что будет, если не указать лимитов памяти?

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

Если запрашиваемая память больше, чем может предложить нода Pod не будет запланирован. Важно помнить, что Requests.memory не минимальное значение. Это описание объема памяти, достаточного для постоянной работы контейнера.

Обычно рекомендуют устанавливать одно и то же значение для request.memory и limit.memory. Благодаря этому Kubernetes не запланирует Pod на узле, у которого достаточно памяти для запуска Pod, но недостаточно для работы. Имейте в виду: при планировании Pod Kubernetes учитывает только requests.memory, а limits.memory не учитывает.

CPU: запрос и ограничение


containers:... resources:   requests:     cpu: 1   limits:     cpu: "1200m"

C CPU все немного сложнее. Возвращаясь к картинке со взаимосвязью между Kubernetes и Docker, можно заметить, что request.cpu соответствует --cpu-shares, тогда как limit.cpu соответствует флагу cpus в Docker.

CPU, который запрашивает Kubernetes, умножается на 1024 пропорцию циклов CPU. Если вы хотите запросить 1 полное ядро, то должны добавить cpu: 1, как показано выше.

Запрос полного ядра (пропорция = 1024) не означает, что ваш контейнер его получит. Если у вашего хост-компьютера только одно ядро, и вы используете более одного контейнера, то все контейнеры должны совместно использовать доступный CPU между собой. Как это происходит? Давайте посмотрим на картинку.


Запрос CPU система с одним ядром

Давайте представим, что у вас есть хост-система с одним ядром, на которой запущены контейнеры. Мама (Kubernetes) испекла пирог (CPU) и хочет разделить его между детьми (контейнерами). Трое детей хотят по целому пирогу (пропорция = 1024), еще один ребенок хочет половину пирога (512). Мама хочет быть справедливой и проводит несложный расчет.

# Сколько пирогов хотят дети?# 3 ребенка хотят по целому пирогу и еще один хочет половину пирогаcakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5# Выражение получается так:3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)# Сколько пирогов испечено?availableCakesNumber = 1# Сколько пирога (максимально) дети реально могут получить?newMaxRequest = 1 / 3.5 =~ 28%

Исходя из расчета, трое детей получат по 28% ядра, а не по целому ядру. Четвертому ребенку достанется 14% от полного ядра, а не половина. Но все будет по-другому, если у вас мультиядерная система.


Запрос CPU мультиядерная (4) система

На изображении выше видно, что трое детей хотят по целому пирогу, а один половину. Поскольку мама испекла четыре пирога, каждый из ее детей получит столько, сколько захочет. В многоядерной системе процессорные ресурсы распределены по всем доступным ядрам процессора. Если контейнер ограничен менее, чем одним полным ядром CPU, то все равно может использовать его на 100%.

Приведенные выше расчеты упрощены для понимания того, как CPU распределяется между контейнерами. Конечно, помимо самих контейнеров, есть и другие процессы, которые также используют ресурсы CPU. Когда процессы в одном контейнере простаивают, другие могут использовать его ресурс. CPU: "200m" соответствует CPU: 0,2, что означает примерно 20% одного ядра.

Теперь давайте поговорим о limit.cpu. CPU, который ограничивает Kubernetes, умножается на 100. Результат количество времени, которое контейнер может использовать каждые 100 мкс (cpu-period).

limit.cpu соответствует флагу Docker --cpus. Это новая комбинация старых --cpu-period и --cpu-quota. Устанавливая его, мы указываем, сколько доступных ресурсов CPU контейнер может максимально использовать до тех пор, пока не начнется троттлинг:

  • cpus комбинация cpu-period и cpu-quota. cpus = 1.5 эквивалентно установке cpu-period = 100000 и cpu-quota = 150000;
  • cpu-period период планировщика CPU CFS, по умолчанию 100 микросекунд;
  • cpu-quota количество микросекунд внутри cpu-period, которым ограничен контейнер.

Что будет, если установить недостаточно запрошенного CPU?

Если контейнеру нужно больше, чем установлено, то он украдет CPU у других процессов.

Что произойдет, если установить недостаточный лимит CPU?

Поскольку ресурс CPU регулируемый, то включится троттлинг.

Что случится, если не указать запрос CPU?

Как и в случае с памятью, значение запроса равно лимиту.

Что будет, если не указать лимит CPU?

Контейнер будет использовать столько CPU, сколько ему необходимо. Если в пространстве имен определена политика CPU по умолчанию (LimitRange), то этот лимит используют и для контейнера.

Что произойдет, если не указать ни запрос, ни лимит CPU?

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

Помните: если вы запросите больше CPU, чем могут предоставить ноды, то Pod не будет запланирован. Requests.cpu не минимальное значение, а значение, достаточное для запуска Pod и работы без сбоев. Если приложение не выполняет сложных вычислений, лучший вариант установить request.cpu <= 1 и запустить столько реплик, сколько необходимо.

Идеальное количество запрошенных ресурсов или лимита ресурсов


Мы узнали об ограничении вычислительных ресурсов. Теперь пришло время ответить на вопрос: Сколько ресурсов требуется моему Pod для работы приложения без проблем? Какое количество идеальное?.

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

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

В качестве примера посмотрите этот дашборд Grafana. Он отображает разницу между запрошенными ресурсами или лимитом ресурсов и текущим использованием ресурсов.

Заключение


Запрос и ограничение ресурсов помогают поддерживать работоспособность кластера Kubernetes. Правильная конфигурация лимитов сводит к минимуму затраты и постоянно поддерживает приложения в рабочем состоянии.

Если вкратце, то нужно помнить о нескольких моментах:

  1. Запрашиваемые ресурсы конфигурация, которая учитывается во время запуска (когда Kubernetes планирует размещение приложения). Напротив, ограничение ресурсов важно во время работы когда приложение уже запущено на узле.
  2. По сравнению с памятью, CPU регулируемый ресурс. В случае нехватки CPU ваш Pod не завершит работу, включится механизм троттлинга.
  3. Запрашиваемые ресурсы и лимит ресурсов это не минимальные и максимальные значения! Определяя запрашиваемые ресурсы, вы гарантируете, что приложение будет работать без проблем.
  4. Хорошая практика устанавливать запрос памяти, равный лимиту памяти.
  5. Хорошо устанавливать запрошенный CPU <=1, если приложение не выполняет сложных вычислений.
  6. Если вы запросите больше ресурсов, чем есть на ноде, то Pod никогда не будет запланирован на эту ноду.
  7. Чтобы определить правильное количество запрошенных ресурсов/лимитов ресурсов, используйте нагрузочное тестирование и мониторинг.

Надеюсь, эта статья поможет вам понять основную концепцию ограничения ресурсов. И вы сможете применить эти знания в своей работе.

Успехов!

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

  1. Наблюдаемость SRE: пространства имен и структура метрик.
  2. 90+ полезных инструментов для Kubernetes: развертывание, управление, мониторинг, безопасность и не только.
  3. Наш канал Вокруг Kubernetes в Телеграме.
Подробнее..

Перевод Проблемные поды эскалация привилегий подов в Kubernetes

01.02.2021 12:14:39 | Автор: admin


Что будет, если разрешить лишнее при создании подов в Kubernetes? Зависит от того, какие неймспейсы хоста и контексты безопасности разрешены. Здесь мы поговорим о восьми небезопасных конфигурациях подов и методах эскалации привилегий. Эта статья и созданный для нее репозиторий помогут пентестерам и администраторам разобраться в распространенных ошибках конфигурации.


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


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


Краткий обзор


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


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


Защита подов: что может натворить один атрибут?


Любой эксперт по безопасности Kubernetes скажет, что при подготовке подов нужно использовать принцип наименьших привилегий. Но как выполнить детальную настройку и оценить риск каждого атрибута?


Администратор Kubernetes может реализовать принцип наименьших привилегий с помощью контроллеров допуска. Это может быть, допустим, встроенный контроллер PodSecurityPolicy или популярный сторонний контроллер OPA Gatekeeper. Контроллеры допуска запрещают поду доступ в кластер, если у него больше разрешений, чем предписано политикой.


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


Пентестеры часто получают доступ к созданию подов на кластере, где не действует никакая политика. Это я называю легким уровнем сложности. Используем этот манифест от Рори МакКьюна (Rory McCune) (@raesene), эту команду от Даффи Кули (Duffie Cooley) (@mauilion) или плагин node-shell krew и вот уже можно интерактивно выполнять код в привилегированном режиме на хосте. Проще уже не придумаешь.


А что если создавать поды можно только с hostNetwork, hostPID, hostIPC, hostPath или privileged? Что будет в каждом случае? Сейчас узнаем.



Проблемные поды: атрибуты и их худшие последствия


Я расположил проблемные поды по мере убывания рисков. Атаки, которым подвержены любые поды Kubernetes (например, проверка доступа пода к сервису метаданных облачного провайдера или поиск неправильно настроенного Kubernetes RBAC) описаны в разделе Проблемный под 8: все запрещено.


Проблемные поды:


Поды


Проблемный под 1: все разрешено


Проблемный под 2: Privileged и hostPid


Проблемный под 3: только Privileged


Проблемный под 4: только hostPath


Проблемный под 5: только hostPid


Проблемный под 6: только hostNetwork


Проблемный под 7: только hostIPC


Проблемный под 8: все запрещено.


Проблемный под 1: все разрешено



Что произойдет в худшем случае?


Много всего.


Как?


Созданный под монтирует файловую систему хоста к поду. Проще всего будет создать под в ноде control-plane с помощью селектора nodeName в манифесте. Потом можно выполнить в поде exec и сделать chroot для каталога, где примонтирована файловая система хоста. Теперь у нас есть права root в ноде, где запущен наш под.


  • Читаем секреты из etcd. Если мы запускаем под на ноде control-plane с помощью селектора nodeName в спецификации пода, мы легко получаем доступ к базе данных etcd, где хранится вся конфигурация кластера, включая секреты.
  • Ищем токены привилегированных учеток сервисов. Даже если удалось запустить под только на рабочей ноде, мы все равно можем получить доступ к секретам всех подов на этой ноде. В продакшен-кластере даже на рабочей ноде всегда есть хотя бы один под с токеном, который привязан к учетке сервиса, связанной с clusterrolebinding, так что мы можем, например, создавать поды или просматривать секреты во всех неймспейсах.

Больше схем эскалации привилегий см. в файле README (ниже) и в разделе Проблемный под 4: hostPath.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/everything-allowed


Дополнительные материалы



Проблемный под 2: privileged и hostpid



Что произойдет в худшем случае?


Много всего.


Как?


Единственное отличие от предыдущего варианта способ получения root-доступа к хосту. Там мы делали chroot для файловой системы хоста, а здесь используем nsenter, чтобы получить права root для ноды, где запущен наш под.


Почему это работает?


  • Privileged. Контекст безопасности privileged: true на уровне контейнера ломает почти любые преграды, которые по идее должен давать контейнер для защиты от атак. Остается разве что неймспейс PID. Без hostPID nsenter сможет входить только в неймспейсы процесса, который запущен в контейнере. Больше примеров действий, которые можно совершить с privileged: true, см. в следующем разделе Проблемный под 3: только Privileged.


  • Privileged + hostPID. Если одновременно задать hostPID: true и privileged: true, поду будут доступны все процессы на хосте, и мы сможем войти в систему init (PID 1) на хосте. А там уже можно запустить shell на ноде.



С root-доступом на хосте у нас есть те же пути эскалации привилегий, о которых мы говорили в разделе Проблемный под 1: все разрешено.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv-and-hostpid


Дополнительные материалы



Проблемный под 3: только privileged



Что произойдет в худшем случае?


Много всего.


Как?


С privileged: true у нас два пути:


  • Примонтировать файловую систему хоста. В привилегированном режиме /dev на хосте будет доступен нашему поду. Мы можем примонтировать к нашему поду диск с файловой системой хоста командой mount. По моему опыту, полной свободы действий нам это не даст. Некоторые файлы и пути эскалации привилегий недоступны из привилегированного пода, если только мы не эскалируем его до полноценной shell. Зато можно легко примонтировать диск и посмотреть, что мы там увидим.
  • Использовать уязвимость cgroup в user mode с помощью специальных программ. Лучше всего получить интерактивный root-доступ к ноде, но тут придется повозиться. Можем использовать прототип эксплойта Феликса Уилхелма (Felix Wilhelm) undock.sh, чтобы выполнять по команде за раз, или вариант, который Брэндон Эдвадрс (Brandon Edwards) и Ник Фриман (Nick Freeman) предложили в своем выступлении Краткое руководство по выходу из контейнера. В этом варианте мы заставляем хост подключиться к listener на поде для эскалации до интерактивного root-доступа на хосте. Еще один вариант взять модуль Metasploit Docker Privileged Container Escape, где используется тот же эксплойт для апгрейда shell на контейнере до shell на хосте.

При любом варианте пути эскалации привилегий в Kubernetes во многом похожи на те, которые мы описали для проблемного пода 1, где все разрешено.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv


Дополнительные материалы



Проблемный под 4: только hostpath



Что произойдет в худшем случае?


Много всего.


Как?


Допустим, у нас нет доступа к хостовым process- и network- неймспейсам, но администраторы не ограничили возможности монтирования. Тогда можно примонтировать всю файловую систему хоста к поду и получить к ней доступ на чтение и запись. Теперь можем использовать те же пути эскалации привилегий, что и раньше. Этих путей столько, что Иен Колдуотер (Ian Coldwater) и Даффи Кули (Duffie Cooley) посвятили им целое выступление на Black Hat 2019: Неизведанный путь: атака на Kubernetes с параметрами по умолчанию.


Вот несколько путей эскалации привилегий, которые можно использовать, когда у нас есть доступ к файловой системе ноды Kubernetes:


  • Ищем файлы kubeconfig в файловой системе хоста. Если повезет, можно даже найти конфигурацию cluster-admin с полным доступом вообще ко всему.
  • Ищем токены во всех подах на ноде. Возьмем что-то типа kubectl auth can-i --list или access-matrix и посмотрим, есть ли в подах токены, которые дадут нам больше разрешений. Ищем токены, с которыми можно получать секреты или создавать поды, деплойменты и т. д. в kube-system или создавать clusterrolebinding.
  • Добавляем свой SSH-ключ. Если у нас есть сетевой доступ к SSH-соединению с нодой, добавим к ноде свой публичный ключ и подключимся к ней по SSH, чтобы получить полный интерактивный доступ.
  • Ломаем хэшированные пароли. Взламываем хэши в /etc/shadow и пытаемся использовать их для доступа к другим нодам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpath


Дополнительные материалы



Проблемный под 5: только hostpid



Что произойдет в худшем случае?


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


Как?


С одним только hostPID не так просто получить root-доступ к ноде, но кое-что натворить можно.


  • Смотрим процессы на хосте. Если запустим ps в поде с hostPID: true, увидим все процессы на хосте, включая процессы на каждом поде.
  • Ищем пароли, токены, ключи и тому подобное.Если повезет, найдем что-нибудь для эскалации привилегий и доберемся до кластера, до сервисов, поддерживаемых кластером, или до сервисов, которые общаются с приложениями на кластере. Придется повозиться, но можно найти токен для учетки сервиса в Kubernetes или что-то подобное, чтобы раздобыть доступ к другим пространствам имен и в итоге получить привилегии cluster-admin.
  • Завершаем процессы. Можно завершить на ноде любой процесс, чтобы вызвать отказ в обслуживании (не советую пентестерам экспериментировать с этим пунктом).

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpid


Проблемный под 6: только hostnetwork



Что произойдет в худшем случае?


Риск компрометации кластера.


Как?


Если у нас есть только hostNetwork: true, напрямую выполнить код в привилегированном режиме на хосте мы не можем, но если сильно повезет, шанс добраться до cluster-admin все же есть. Путей эскалации может быть три:


  • Прослушиваем трафик. С tcpdump можно прослушивать незашифрованный трафик на любом интерфейсе хоста. Если звезды сложатся, нам попадутся токены учетки сервиса или другая конфиденциальная информация, которая передается по незашифрованным каналам.
  • Получаем доступ к сервисам, связанным с localhost. Мы можем получить доступ к сервисам, которые принимают трафик только через loopback интерфейс хоста или как-то еще ограничены сетевыми политиками. Оттуда можно найти какие-нибудь интересные пути эскалации привилегий.
  • Обходим сетевую политику. Если пространство имен ограничено сетевой политикой, можно задеплоить под с атрибутом hostNetwork: true, чтобы обойти эти ограничения. Суть в том, что мы привязываемся к сетевым интерфейсам хоста, а не подам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostnetwork


Проблемный под 7: только hostipc



Что произойдет в худшем случае?


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


Как?


Если какой-то процесс на хосте или процессы в поде используют механизмы межпроцессного взаимодействия (IPC) хоста (общая память, массивы семафоров, очереди сообщений и т. д.), можно использовать эти механизмы для чтения/записи. Сначала ищем /dev/shm, общий для всех подов с атрибутом hostIPC: true и хоста. Можно проверить и другие механизмы IPC с помощью ipcs.


  • Проверяем /dev/shm. Ищем файлы в общей памяти.
  • Проверяем существующие объекты IPC. С помощью /usr/bin/ipcs можно узнать, используются ли какие-нибудь объекты IPC.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostipc


Проблемный под 8: все запрещено



Что произойдет в худшем случае?


Много всего.


Как?


Даже если все атрибуты запрещены, мы все равно можем найти множество путей атак, если можно создать под или хотя бы получить к нему доступ. Имея доступ к поду Kubernetes, обращаем внимание на следующее:


  • Доступные облачные метаданные. Если под размещен в облаке, пытаемся получить доступ к облачному сервису метаданных. Там можно найти учетные данные IAM, связанные с нодой, или хотя бы облачные учетные данные IAM, созданные специально для этого пода. В обоих случаях можно добраться до кластера, до облачной среды или и туда, и туда.
  • Учетки сервисов с лишними разрешениями. Если учетка сервиса по умолчанию в пространстве имен примонтирована к /var/run/secrets/kubernetes.io/serviceaccount/token в поде и позволяет слишком многое, с этим токеном можно эскалировать привилегии в кластере.
  • Компоненты Kubernetes с неправильной конфигурацией. Если у apiserver или kubelet'ов для anonymous-auth задано true и никакие сетевые политики нам не мешают, можно взаимодействовать с ними напрямую без аутентификации.
  • Эксплойты в ядре, движке контейнера или Kubernetes. Эксплойт в этих компонентах можно использовать для выхода из контейнера или доступа к кластеру Kubernetes без дополнительных разрешений.
  • Уязвимые сервисы. Если смотреть на сетевые сервисы кластера через под, скорее всего, мы увидим больше, чем с машины, где создали этот под. Можем поискать уязвимые сервисы и приложения, направляя трафик через под.

Примеры использования
https://github.com/BishopFox/badPods/tree/main/manifests/nothing-allowed


Дополнительные материалы


Защита Kubernetes KubeCon NA 2019 CTF
Kubernetes Goat
Атака на Kubernetes через Kubelet
Подробный обзор угроз для Kubernetes в реальном мире
Краткое руководство по выходу из контейнера
CVE-2020-8558 POC


Заключение


Если не считать проблемный под номер 8, где все и так запрещено, все пути эскалации привилегий в этом посте (и репозитории к нему) можно перекрыть политиками безопасности.


Администраторы Kubernetes могут использовать и другие методы глубокой защиты, чтобы снизить или полностью устранить риски некоторых путей атак, даже если у злоумышленника есть доступ к некоторым или ко всем неймспейсам и возможностям на хосте (отключить автоматическое монтирование токенов учеток сервисов или запретить подам запуск с правами root, указав MustRunAsNonRoot=trueи allowPrivilegeEscalation=false). Как это обычно и бывает с пентестами, для взлома может потребоваться больше или меньше усилий.


Админам часто приходится применять методы защиты без примеров последствий, к которым может привести та или иная рискованная конфигурация. Надеюсь, примеры в этом посте и манифестах в репозитории Bad Pods помогут вам применять принцип наименьших привилегий при создании подов Kubernetes в вашей компании.


От редакции: подробнее о безопасности в K8s можно узнать на интенсиве Kubernetes Мега. Интенсив пройдет в онлайн-формате с 17 по 19 мая 2021.
Подробнее..

14 лучших практик разработки приложений на OpenShift

18.02.2021 14:23:54 | Автор: admin

Много работая с командами разработки, только что перешедшими на OpenShift, мы стремимся дать им рекомендации и лучшие практики для успешного создания и внедрения приложений на этой платформе. По итогам этой работы мы отобрали 14 ключевых, на наш взгляд, практик, которые можно разбить на две категории: надежность приложений и безопасность приложений. Эти категории пересекаются, поскольку чем выше надежность, тем лучше безопасность, и наоборот, а сам список лучших практик выглядит следующим образом.

Надежность приложений

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

1. Не храните конфигурацию приложения внутри контейнера

Если контейнерный образ содержит конфигурацию для какой-то конкретной среды (Dev, QA, Prod), его не получится без изменений переносить между средами. Это плохо с точки зрения надежности процесса выпуска версий, поскольку в продакшн пойдет уже не тот образ, который тестировался на предыдущих этапах. Поэтому не держите внутри контейнера конфигурацию приложения для конкретной среды, а храните ее отдельно, например, с помощью ConfigMaps и Secrets.

2. Задавайте ресурсные требования и лимиты в определениях podа

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

3. Прописывайте зонды активности (liveness) и готовности (readiness) в определениях podа

С помощью этих зондов кластер может обеспечивать базовую устойчивость: перезапускать приложение, если не проходит liveness, или больше не маршрутизировать на него трафик, когда не отвечает readiness. Подробнее см. раздел Мониторинг работоспособности приложений в документации OpenShift Platform.

4. Используйте PodDisruptionBudget для защиты приложений

Иногда podы приходится убирать с узла кластера, например, при обслуживании хоста, или когда autoscaler даунсайзит кластер, отключая лишние узлы. Чтобы приложение при этом оставалось доступным, надо настроить объекты PodDistruptionBudget.

5. Правильное завершение работы podов

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

6. Один контейнер один процесс

Старайтесь, чтобы каждый процесс работал в своем собственном контейнере. Это повышает изоляцию процессов и предотвращает проблемы с маршрутизацией сигналов и появление зомби-процессов, которые иначе придется периодически вычищать. Подробнее см. разделИзбегайте нескольких процессовв документации OpenShift Platform.

7. Используйте системы мониторинга приложений и оповещения

Мониторинг приложений средствами Prometheus и Grafana помогает поддерживать нормальную работу приложений в продакшн-режиме согласно требованиям бизнеса.

8. Пусть приложения пишут свои логи в stdout/stderr

Тогда OpenShift сможет собирать и пересылать их в централизованную систему обработки (ELK, Splunk). Логи это бесценный ресурс при анализе работы приложения в продакшн-режиме. Кроме того, оповещения, генерируемые на базе содержимого логов, помогают проконтролировать, что приложение работает как задумано.

9. Изучите целесообразность применения Circuit breakers, Timeouts, Retries, Rate Limiting

Эти механизмы повышают устойчивость приложения к отказам, защищая от перегрузок (Rate Limiting, Circuit Breakers) и помогая справляться с сетевыми проблемами (Timeouts, Retries). Рассмотрите возможность применения решения OpenShift Service Mesh, которое позволяет реализовать эти функции, не трогая код приложений.

Безопасность приложений

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

10. Используйте только доверенные контейнерные образы

Применяйте вендор-образы везде, где это возможно, поскольку они гарантировано тестируются, дорабатываются на безопасность и обеспечиваются поддержкой. Что касается community-образов, используйте наработки только тех сообществ, которым доверяете. И помните, что в публичных реестрах, вроде Docker Hub, имеются образы неизвестного происхождения не используйте их ни в коем случае!

11. Используйте последние версии базовых контейнерных образов

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

12. build-образы отдельно, runtime-образы отдельно

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

13. Restricted security context constraint (SCC) везде, где только возможно

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

14. TLS для защиты коммуникаций между компонентами приложения

Компоненты приложения могут пересылать друг другу конфиденциальные данные. Если сеть, в которой работает OpenShift, не может считаться безопасной, то трафик между компонентами приложения можно защитить с помощью TLS-шифрования, а уже упомянутый OpenShift Service Mesh позволяет сделать это, не трогая код приложений.

Заключение

Итак, теперь у вас есть список из 14 лучших практик для построения более надежных и безопасных приложений OpenShift. Это хорошее начало для выработки собственного кодекса разработки для членов вашей команды. Дополнительные сведения и рекомендации можно найти в разделе Создание образов документации OpenShift.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru