SDK встановлює користувача за допомогою UID, оскільки це вимагається Kubernetes для застосування властивості runAsNonRoot.
Ми можемо зазирнути трохи глибше, щоб побачити, звідки береться значення 1654.
Ми визначаємо користувача з ім'ям app і даємо йому UID > 1000, щоб уникнути зарезервованих діапазонів. 1654 - це 1000 + ASCII-значення кожного з символів у dotnet. Ми також встановлюємо змінну оточення - APP_UID - з таким самим значенням. Це дозволяє уникнути необхідності запам'ятовувати або використовувати це значення (без змінної оточення) для звичайних сценаріїв.
У попередньому дописі я включив набір цікавих демонстраційних прикладів для користувачів, які не мають права root. Ви можете переглянути цю статтю, щоб дізнатися більше.
Non-root Dockerfiles
Модель з Dockerfiles схожа, але вимагає одного додаткового кроку - встановлення інструкції USER .
Я покажу вам, як це виглядає, використовуючи цей приклад Dockerfile.
Цей Dockerfile використовує змінну оточення, яку ми щойно розглянули, для визначення користувача. Це шаблон, який ми хочемо, щоб усі використовували для переходу до користувача без прав суперкористувача за допомогою Dockerfiles. Знову ж таки, цей шаблон дозволяє уникнути повсюдного використання магічних чисел і найкраще працює у Kubernetes.
Примітка: Багато розробників вже створили власного користувача. Продовження роботи з власним користувачем або перемикання на вбудованого - обидва варіанти є чудовими.
Після цього ми можемо створити і запустити образ.
Як бачите, програма працює від імені користувача app.
Перемикач для увімкнення non-root хостингу (у Dockerfiles) - це лише зміна одного рядка.
Ubuntu Chiseled образи
Образи Ubuntu Chiseled схожі на пристрої, що надають заблокований досвід роботи за замовчуванням. Вони сумісні зі звичайною Ubuntu, проте мають гострі краї, де вирізані цілі розділи операційної системи. Примітно, що вони налаштовані як non-root. Це означає, що вам навіть не потрібно налаштовувати користувача, оскільки він вже налаштований.
Ви можете оглянути вирізане зображення, щоб переконатися, що користувач налаштований.
У нас є інший приклад Dockerfile, який покладається на користувача, встановленого в цих зображеннях.
Як ви можете бачити, у цьому Dockerfile не задано USER. Давайте зберемо і запустимо його.
Знову ж таки, додаток запускається від імені користувача app. Якщо ви використовуєте чисельні зображення, ви отримуєте кращі результати і менше роботи у вашому Dockerfile.
Ви можете так само легко використовувати Chiseled images за допомогою SDK publish.
Ця команда створить non-root образ, оскільки наші Chiseled images налаштовані як non-root , а dotnet publish створює non-root образи за замовчуванням.
Kubernetes
Kubernetes має механізм runAsNonRoot, який є частиною стандартів безпеки. Якщо цей параметр встановлено у true, Kubernetes не зможе завантажити маніфест пакунків, якщо образ контейнера має права root.
Я вважаю runAsNonRoot функцією типу «ролі та обов'язки». Роль образу контейнера визначає користувач. Відповідальність оркестратора полягає у перевірці того, що користувач встановлений як очікується, як non-root.
Згадайте погляд на метадані контейнера «як це робиться у Kubernetes», який ми розглядали раніше.
Kubernetes не використовує docker inspect, але ідея та сама. Він дивиться на те саме значення User, визначає, чи є це значення UID, і якщо так, то перевіряє value > 0. Якщо цей вираз дорівнює true, то проходить перевірка runAsNonRoot. У контексті root має UID 0, тому ця перевірка є аналогом user != root.
Давайте швидко розглянемо, як працює non-root у Kubernetes. Якщо ви хочете дізнатися більше, читайте статтю Запуск non-root .NET контейнерів у Kubernetes.
Ось приклад того, як задати runAsNonRoot у маніфесті Pod
У цьому прикладі кожен перелічений контейнер (навіть якщо у прикладі лише один) має бути non-root. securityContext також може бути задано для контейнера. Ви можете переглянути ці налаштування у ширшому контексті у файлі non-root.yaml.
Насправді цікаво подивитися, що станеться, якщо runAsNonRoot буде встановлено у true і ми спробуємо завантажити образ, який використовує користувачів root.
На момент написання статті образ mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled (використаний вище) налаштовано як non-root, а mcr.microsoft.com/dotnet/samples:aspnetapp - як root. Я зміню значення image в маніфесті на mcr.microsoft.com/dotnet/samples:aspnetapp, а потім подивлюся, чи не відбудеться збій при завантаженні.
Як бачите, навантаження не проходить.
Якщо копнути трохи глибше, то можна зрозуміти причину.
Це відповідає очікуванням. Добре.
Змініть користувача на root
Бувають випадки, коли користувачеві потрібно встановити права користувача root. Зробити це дуже просто.
Можна (за допомогою Docker) запустити команду від імені користувача root у запущеному контейнері за допомогою docker exec -u. Найчастіше це буде команда bash, але ми будемо використовувати whoami, оскільки вона пропонує кращу демонстрацію.
Зверніть увагу, що kubectl exec не пропонує аргумент -u (з поважної причини).
Аналогічно, контейнер можна запустити від імені певного користувача, перевизначивши користувача, вказаного у метаданих зображення.
Нарешті, конкретний користувач може бути використаний при створенні образу за допомогою ContainerUser.
Вказаний ContainerUser повинен існувати.
Однак ви можете використовувати дійсний UID.
Як ви можете бачити, у зображеннях контейнерів, які ми публікуємо, визначені як користувач root, так і користувач app.
Закриття
Користувач для виробничих програм є ключовою частиною будь-якого плану безпеки. На жаль, його легко пропустити, оскільки все працює без вказівки користувача. Насправді, все працює занадто добре. Можна сказати, що це і є корінь проблеми.
Додати користувача до Dockerfile дуже просто. Створити наскрізні робочі процеси, які надійно встановлюють бажані результати безпеки, набагато складніше. Як бачите, тепер легко створювати non-root образи контейнерів за допомогою dotnet publish або Dockerfiles. Образи будуть коректно працювати з функціями безпеки Kubernetes, що є критично важливим для забезпечення бажаних політик безпеки.
Завжди будуть потрібні додаткові налаштування безпеки. Non-root хостинг - це одна з найвпливовіших змін, яку ви можете зробити.