Введение в Hashicorp Consul’s Kubernetes Авторизацию
Все верно, после релиза Hashicorp Consul 1.5.0 в начале мая 2019 года в Consul можно делать авторизацию приложений и служб, запущенных в Kubernetes, нативно.
В этом руководстве мы шаг за шагом создадим POC (Проверка концепции (Proof of concept, PoC — доказательство [осуществимости] концепции — прим. перев.), продемонстрировав эту новую функцию. От вас ожидаются базовые знания о Kubernetes и Hashicorp’s Consul. И хотя вы можете использовать любую облачную платформу или локальную среду, в этом руководстве мы будем использовать Google’s Cloud Platform.
Обзор
Если мы перейдем к документации Consul по его методу авторизации, мы получим краткий обзор его назначения и варианта использования, а также некоторые технические детали и общий обзор логики. Я настоятельно рекомендую прочитать ее по крайней мере один раз, прежде чем продолжить, так как сейчас я буду все это объяснять и разжевывать.
Схема 1: Официальный обзор метода авторизации Consul
Конечно, там есть полезная информация, но нет руководства о том, как на самом деле все это использовать. Поэтому, как любой здравомыслящий человек, вы прочесываете Интернет в поисках руководства. А потом… Терпите поражение. Так бывает. Давайте это исправим.
Прежде чем мы перейдем к созданию нашего POC, давайте вернемся к обзору методов авторизации Consul (Схема 1) и уточним его в контексте Kubernetes.
Архитектура
В этом руководстве мы будем создавать Consul-сервер на отдельной машине, которая будет взаимодействовать с кластером Kubernetes с установленным клиентом Consul. Затем мы создадим наше фиктивное приложение в поде и используем наш настроенный метод авторизации для чтения из нашего Consul key/value хранилища.
Схема ниже детально показывает архитектуру, которую мы создаем в этом руководстве, а также логику метода авторизации, которая будет объяснена позже.
Схема 2: Обзор метода авторизации в Kubernetes
Небольшое замечание: Consul-серверу не нужно жить за пределами кластера Kubernetes, чтобы это работало. Но да, он может и так и сяк.
Итак, взяв обзорную схему Consul (Схема 1) и применив к ней Kubernetes, мы получаем схему выше (Схема 2), и тут логика будет следующая:
К каждому поду будет прикреплена служебная учетная запись, содержащая токен JWT, сгенерированный и известный Kubernetes. Этот токен также вставляется в под по умолчанию.
Наше приложение или сервис внутри пода инициирует команду входа в наш Consul-клиент. В запросе на вход в систему также будет указан наш токен и указано имя специально созданного метода авторизации (типа Kubernetes). Этот шаг № 2 соответствует шагу 1 схемы Consul (Схема 1).
Наш Consul-клиент затем направит этот запрос на наш Consul-сервер.
МАГИЯ! Именно здесь Consul-сервер проверяет подлинность запроса, собирает сведения об идентичности запроса и сравнивает их с какими-нибудь ассоциированными предопределенными правилами. Ниже будет другая схема, чтобы это проиллюстрировать. Этот шаг соответствует шагам 3, 4 и 5 обзорной схемы Consul (Схема 1).
Наш Consul-сервер генерирует Consul токен с разрешениями в соответствии с указанными нами правилами метода авторизации (которые мы определили) в отношении личности запрашивающего. Затем он отправит этот токен обратно. Это соответствует шагу 6 схемы Consul (Схема 1).
Наш Consul-клиент перенаправляет токен запрашивающему приложению или сервису.
Наше приложение или сервис теперь могут использовать этот Consul токен для связи с нашими данными Consul, как было определено привилегиями токена.
Волшебство раскрыто!
Для тех из вас, кто не доволен всего лишь кроликом из шляпы и хочет знать, как это работает… позвольте мне «показать вам, насколько глубока кроличья нора».
Как упоминалось ранее, наш «магический» шаг (Схема 2: Шаг 4) заключается в том, что Consul-сервер проверяет подлинность запроса, собирает сведения об запросе и сравнивает их с любыми ассоциированными предопределенными правилами. Этот шаг соответствует шагам 3, 4 и 5 обзорной схемы Consul (Схема 1). Ниже приведена схема (Схема 3), цель которой наглядно показать, что на самом деле происходит под капотом конкретного метода авторизации Kubernetes.
Схема 3: Волшебство раскрыто!
В качестве отправной точки, наш Consul-клиент перенаправляет запрос на вход на наш Consul-сервер с токеном учетной записи Kubernetes и конкретным именем инстанса метода авторизации, который был создан ранее. Этот шаг соответствует шагу 3 в предыдущем объяснении схемы.
Теперь Consul-серверу (или лидеру) необходимо проверить подлинность полученного токена. Поэтому он проконсультируется с кластером Kubernetes (через Consul-клиент) и, при наличии соответствующих разрешений, мы выясним, является ли токен подлинным, и кому он принадлежит.
Затем проверенный запрос возвращается к Consul-лидеру, и на сервере Consul выполняется поиск инстанса метода авторизации с указанным именем из запроса на вход в систему (и типа Kubernetes).
Consul-лидер определяет указанный инстанс метода авторизации (если он найден) и читает набор правил привязки, которые к нему прикреплены. Затем он читает эти правила и сравнивает их с проверенными атрибутами идентичности.
Тада! Переходим к шагу 5 в предыдущем объяснении схемы.
Запустите Consul-server на обычной виртуальной машине
С этого момента я в основном буду давать инструкции по созданию этого POC, часто в пунктах, без пояснительных целых предложений. Также, как отмечалось ранее, я буду использовать GCP для создания всей инфраструктуры, но вы можете создать такую же инфраструктуру в любом другом месте.
Запустите виртуальную машину (инстанс / сервер).
Создайте правило для firewall (группа безопасности в AWS):
Мне нравится присваивать одно и то же имя машины правилу и сетевому тегу, в данном случае это «skywiz-consul-server-poc».
Найдите IP-адрес вашего локального компьютера и добавьте его в список исходных IP-адресов, чтобы мы могли получить доступ к интерфейсу пользователя (UI).
Откройте порт 8500 для UI. Нажмите Create (Создать). Мы скоро опять изменим этот firewall [ссылка].
Добавьте правило для firewall к инстансу. Вернитесь на панель мониторинга VM на Consul-сервере и добавьте «skywiz-consul-server-poc» в поле сетевых тегов. Нажмите Save (Сохранить).
Установите Consul на виртуальную машину, проверьте здесь. Помните, что вам нужна версия Consul ≥ 1.5 [ссылка]
Создадим single node Consul — конфигурация следующая.
groupadd --system consul
useradd -s /sbin/nologin --system -g consul consul
mkdir -p /var/lib/consul
chown -R consul:consul /var/lib/consul
chmod -R 775 /var/lib/consul
mkdir /etc/consul.d
chown -R consul:consul /etc/consul.d
Более подробное руководство по установке Consul и настройке кластера из 3 нод см. здесь.
Создайте файл /etc/consul.d/agent.json следующим образом [ссылка]:
consul agent
-server
-ui
-client 0.0.0.0
-data-dir=/var/lib/consul
-bootstrap-expect=1
-config-dir=/etc/consul.d
Вы должны увидеть кучу выходных данных и в конечном итоге “… update blocked by ACLs”.
Найдите внешний IP-адрес Consul-сервера и откройте браузер с этим IP-адресом на порту 8500. Убедитесь, что открывается UI.
Попробуйте добавить пару ключ/значение. Должна быть ошибка. Это потому, что мы загрузили Consul-сервер с помощью ACL и запретили все правила.
Вернитесь к своей оболочке на Consul-сервере и запустите процесс в фоновом режиме или каким-либо другим способом, чтобы он работал, и введите следующее:
consul acl bootstrap
Найдите значение «SecretID» и вернитесь к UI. На вкладке «ACL» введите секретный идентификатор токена, который вы только что скопировали. Скопируйте SecretID еще куда-нибудь, он понадобится нам позже.
Теперь добавьте пару ключ/значение. Для этого POC добавим следующее: ключ: «custom-ns/test_key», значение: «I’m in the custom-ns folder!»
Запуск Kubernetes-кластера для нашего приложения с Consul-клиентом в качестве Daemonset
Создайте кластер K8s (Kubernetes). Мы создадим его в той же зоне, что и сервер, для более быстрого доступа, и поэтому мы можем использовать ту же подсеть для простого подключения с внутренними IP-адресами. Мы назовем его «skywiz-app-with-consul-client-poc».
Как примечание, вот хорошее руководство, с которым я столкнулся при настройке POC Consul-кластера с Consul Connect.
Мы также будем использовать Hashicorp helm chart с расширенным файлом значений.
Установите и сконфигурируйте Helm. Шаги конфигурации:
Используйте следующий файл значений (обратите внимание, большинство я отключил):
### poc-helm-consul-values.yaml
global:
enabled: false
image: "consul:latest"
# Expose the Consul UI through this LoadBalancer
ui:
enabled: false
# Allow Consul to inject the Connect proxy into Kubernetes containers
connectInject:
enabled: false
# Configure a Consul client on Kubernetes nodes. GRPC listener is required for Connect.
client:
enabled: true
join: ["<PRIVATE_IP_CONSUL_SERVER>"]
extraConfig: |
{
"acl" : {
"enabled": true,
"default_policy": "deny",
"enable_token_persistence": true
}
}
# Minimal Consul configuration. Not suitable for production.
server:
enabled: false
# Sync Kubernetes and Consul services
syncCatalog:
enabled: false
Примените helm chart:
./helm install -f poc-helm-consul-values.yaml ./consul-helm - name skywiz-app-with-consul-client-poc
При попытке запуска, ему понадобятся разрешения для Consul-сервера, так что давайте добавим их.
Обратите внимание на «диапазон адресов Pod», расположенный на приборной панели кластера, и вернитесь к нашему правилу для firewall «skywiz-consul-server-poc».
Добавьте диапазон адресов для пода в список IP-адресов и откройте порты 8301 и 8300.
Перейдите к Consul UI, и через несколько минут вы увидите, что наш кластер появится на вкладке нод.
Настройка метода авторизации путем интеграции Consul с Kubernetes
Вернитесь в оболочку Consul-сервера и экспортируйте токен, который вы сохранили ранее:
export CONSUL_HTTP_TOKEN=<SecretID>
Нам понадобится информация из нашего Kubernetes-кластера, чтобы создать инстанс метода auth:
kubernetes-host
kubectl get endpoints | grep kubernetes
kubernetes-service-account-jwt
kubectl get sa <helm_deployment_name>-consul-client -o yaml | grep "- name:"
kubectl get secret <secret_name_from_prev_command> -o yaml | grep token:
Токен закодирован в base64, поэтому расшифруйте его с помощью вашего любимого инструмента [ссылка]
kubernetes-ca-cert
kubectl get secret <secret_name_from_prev_command> -o yaml | grep ca.crt:
Возьмите сертификат “ca.crt” (после декодирования с base64) и впишите его в файл “ca.crt”.
Теперь создайте инстанс метода auth, заменив placeholders на значения, которые вы только что получили.
consul acl auth-method create
-type "kubernetes"
-name "auth-method-skywiz-consul-poc"
-description "This is an auth method using kubernetes for the cluster skywiz-app-with-consul-client-poc"
-kubernetes-host "<k8s_endpoint_retrieved earlier>"
[email protected]
-kubernetes-service-account-
jwt="<decoded_token_retrieved_earlier>"
Далее мы должны создать правило и прикрепить его к новой роли. Для этой части вы можете использовать Consul UI, но мы будем использовать командную строку.
Затем примените следующую встроенную команду для создания configmap [ссылка]. Обратите внимание, что мы ссылаемся на название нашего сервиса, замените его при необходимости.
Создайте еще несколько ключевых папок с тем же ключом верхнего уровня (т. е. <new_folder>/sample_key) и значением по вашему выбору. Создайте соответствующие политики и роли для новых ключевых путей. Мы сделаем привязки позже.
Пользовательский тест пространства имен:
Создадим наше собственное пространство имен:
kubectl create namespace custom-ns
Создадим под в нашем новом пространстве имен. Напишите конфигурацию для пода.
Вы можете декодировать «Value» base64 и увидеть, что оно соответствует значению в custom-ns/test_key в UI. Если вы использовали то же значение, приведенное выше в этом руководстве, ваше кодированное значение будет IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.
Тест учетной записи пользовательской службы:
Создайте пользовательский ServiceAccount с помощью следующей команды [ссылка].
Permission denied. О, мы забыли добавить новую привязку правил с соответствующими разрешениями, давайте сделаем это сейчас.
Повторите предыдущие шаги выше:
а) Создайте идентичную Политику для префикса «custom-sa/».
б) Создайте Role, назовите ее «custom-sa-role»
в) Прикрепите Политику к Role.
Создайте Rule-Binding (возможно только из cli / api). Обратите внимание на другое значение флага селектора.
consul acl binding-rule create
-method=auth-method-skywiz-consul-poc
-bind-type=role
-bind-name='custom-sa-role'
-selector='serviceaccount.name=="custom-sa"'
Повторите вход в систему из контейнера «poc-ubuntu-custom-sa». Success!
Вы также можете убедиться, что этот токен не предоставляет доступ к kv в «custom-ns/». Просто повторите приведенную выше команду после замены «custom-sa» на префикс «custom-ns».
Permission denied.
Пример оверлея:
Стоит отметить, что все сопоставления rule-binding будут добавлены в токен с этими правами.
Наш контейнер «poc-ubuntu-custom-sa» находится в пространстве имен по умолчанию — так что давайте использовать его для другой rule-binding.
Повторите предыдущие шаги:
а) Создайте идентичную Политику для префикса ключа «default/».
б) Создайте Role, назовите ее “default-ns-role”
в) Прикрепите Политику к Role.
Создайте Rule-Binding (возможно только из cli / api)
consul acl binding-rule create
-method=auth-method-skywiz-consul-poc
-bind-type=role
-bind-name='default-ns-role'
-selector='serviceaccount.namespace=="default"'
Вернитесь к нашему контейнеру «poc-ubuntu-custom-sa» и попробуйте получить доступ к пути «default/» kv.
Permission denied.
Вы можете просмотреть указанные учетные данные для каждого токена в UI в разделе ACL > Tokens. Как видите, к нашему текущему токену прикреплена только одна «custom-sa-role». Токен, который мы используем в настоящее время, был сгенерирован, когда мы вошли в систему, и тогда было только одно rule-binding, которое тогда соответствовало. Нам нужно снова войти в систему и использовать новый токен.
Убедитесь, что вы можете читать как из путей «custom-sa/», так и «default/» kv.
Success!
Это связано с тем, что наш «poc-ubuntu-custom-sa» соответствует привязкам правил «custom-sa» и «default-ns».
Заключение
TTL token mgmt?
На момент написания этой статьи не существует интегрированного способа определения TTL для токенов, сгенерированных этим методом авторизации. Это была бы фантастическая возможность — обеспечить безопасную автоматизацию авторизации Consul.
Существует возможность вручную создать токен с TTL: