Хабрахабр

Kubernetes tips & tricks: доступ к dev-площадкам

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

На этот раз будут рассмотрены две темы, условно связанные одной темой: доступом пользователей к dev-окружению.

1. Как мы закрываем dev-контуры от лишних пользователей?

Перед нами часто стоит задача закрыть за basic auth или за белым списком весь dev-контур (десятки/сотни приложений), дабы туда не могли попасть поисковые боты или просто очень сторонние люди.

Управлять ими очень проблематично, когда набирается с десяток приложений. Обычно для ограничения доступов каждому Ingress и приложению надо создавать отдельные секреты basic auth. Поэтому мы организовали централизованное управление доступами.

Для этого был создан nginx с конфигурацией такого типа:

location / { satisfy any; auth_basic "Authentication or whitelist!"; auth_basic_user_file /etc/nginx/htpasswd/htpasswd; allow 10.0.0.0/8; allow 175.28.12.2/32; deny all; try_files FAKE_NON_EXISTENT @return200;
} location @return200 { return 200 Ok;
}

Далее в Ingress'ах приложений мы просто добавляем аннотацию:

ingress.kubernetes.io/auth-url: "http://dev-auth.dev-auth-infra.svc.cluster.local"

Если одно из условий выполнено, запрос подтверждается и проходит в приложение. Таким образом, при обращении к приложению запрос уходит в сервис dev-auth, который проверяет, введен ли корректный basic auth или же клиент входит в whitelist.

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

2. Как мы предоставляем доступ к приложениям внутри Kubernetes в dev-окружении?

… будь то Redis, RabbitMQ, PostgreSQL или любимый PHP-разработчиками Xdebug.

И тогда разработчики, которые привыкли «ходить своей IDE» в базу или в Xdebug, испытывают серьёзные трудности. Очень часто, переводя приложения в Kubernetes, для обеспечения лучшей безопасности нам приходится закрывать доступ снаружи и вовсе.

Общая схема выглядит таким образом, что при подключении к VPN-серверу, запущенному в K8s, в конфигурационном файле OpenVPN мы push'им адрес DNS-сервера, который тоже живёт в K8s. Для решения этой проблемы мы используем VPN прямо в кластере Kubernetes. DNS в Kubernetes резолвит его в адрес 10. OpenVPN конфигурирует VPN таким образом, что при запросе ресурса внутри Kubernetes он сначала попадает в DNS-сервер Kubernetes — например, за адресом сервиса redis.production.svc.cluster.local. 1. 244. 15 и запросы на этот IP-адрес идут через OpenVPN прямо в кластер Kubernetes.

В частности: За время эксплуатации этого решения мы успели его неоднократно расширить.

  1. Так как мы не нашли простой и адекватной (для нашего случая) админки для учёта доступов к VPN, пришлось создать свой простой интерфейс — ведь официальный чарт предусматривает только вариант с запуском консольных команд для выпуска сертификатов.

    также на Docker Hub) выглядит очень аскетично:
    Получившаяся админка (см.

    Можно заводить новых юзеров или отзывать старые сертификаты:

    Также можно посмотреть конфиг для данного клиента:

  2. Мы добавили авторизацию в VPN'е на основе юзеров в GitLab, где проверяется пароль и активен ли юзер в GitLab. Это для случаев, когда клиенту хочется управлять юзерами, которые могут подключиться к dev VPN только на основе GitLab'а, и без использования дополнительных админок — в некотором смысле получается «SSO для бедных». За основу брали уже упомянутый готовый чарт.

    Для этого мы написали Python-скрипт, который при подключении юзера к OpenVPN, используя логин и пароль, сравнивает хэш в базе GitLab и проверяет его статус (активен ли он).

    Вот сам скрипт:

    #!/usr/bin/env python3 # pip3 install psycopg2-binary bcrypt import bcrypt
    import sys
    import os
    import psycopg2
    import yaml with open("/etc/openvpn/setup/config.yaml", 'r') as ymlfile: cfg = yaml.load(ymlfile) def get_user_info(username=''): try: connect_str = "dbname=%s user=%s host=%s password=%s" % (cfg['db'], cfg['user'], cfg['host'], cfg['pass']) # use our connection values to establish a connection conn = psycopg2.connect(connect_str) # create a psycopg2 cursor that can execute queries cursor = conn.cursor() # create a new table with a single column called "name" cursor.execute("""SELECT encrypted_password,state FROM users WHERE username='%s';""" % username) # run a SELECT statement - no data in there, but we can try it rows = cursor.fetchall() print(rows) return(rows[0]) except Exception as e: print("Uh oh, can't connect. Invalid dbname, user or password?") print(e) def check_user_auth(): username = os.environ['username'] password = bytes(os.environ['password'], 'utf-8') # hashed = bcrypt.hashpw(password, bcrypt.gensalt()) user_info = get_user_info(username=username) user_encrypted_password = bytes(user_info[0], 'utf-8') user_state = True if user_info[1] == 'active' else False if bcrypt.checkpw(password, user_encrypted_password) and user_state: print("It matches!") sys.exit(0) else: print("It does not match :(") sys.exit(1) def main(): check_user_auth() if __name__ == '__main__': main()

    А в конфиге OpenVPN просто указываем следующее:

    auth-user-pass-verify /etc/openvpn/auth-user.py via-env
    script-security 3
    client-cert-not-required

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

Вместо заключения

В продолжении цикла статей с практическими рецептами компании «Флант» по эксплуатации Kubernetes я раскрою такие темы, как выделение отдельных узлов под конкретные задачи (зачем и как?) и настройка под большие нагрузки служб вроде php-fpm/gunicorn, запущенных в контейнерах. Подписывайтесь на наш блог, чтобы не пропускать обновления!

P.S.

Другое из цикла K8s tips & tricks:
Читайте также в нашем блоге:

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть