Airflow connections: как не хранить пароли в DAG
Управление Connections в Airflow: UI, CLI, переменные среды (AIRFLOW_CONN_*), Secrets Backend (Vault, AWS SSM). Как пере
Если вы хоть раз коммитили DAG с зашитым в него паролем от продовой базы — вы не одиноки. Но после этого обычно наступает холодный пот и мысль «надо срочно всё переделать». Хранить креденшелы в коде — это билет в один конец к компрометации данных. К счастью, Airflow предлагает несколько встроенных механизмов для безопасной работы с подключениями. Разберём их по нарастающей сложности и безопасности.
Способ 1: Connections в UI — для локальной разработки
Самый простой и известный метод — создать connection через веб-интерфейс (Admin -> Connections). DAG при этом ссылается только на conn_id.
from airflow.providers.postgres.hooks.postgres import PostgresHook
def query_data():
hook = PostgresHook(postgres_conn_id='my_prod_db')
conn = hook.get_conn()
# работа с соединением
Плюс: быстро и наглядно. Минус: пароли хранятся в базе Airflow. При резервном копировании метаданных они тоже уезжают. Не подходит для командной работы или продакшена.
Способ 2: CLI — для автоматизации
Добавлять и обновлять подключения можно через CLI, что удобно для скриптов развертывания.
airflow connections add 'my_prod_db' \
--conn-type 'postgres' \
--conn-host 'localhost' \
--conn-login 'user' \
--conn-password 'pass' \
--conn-port 5432
Но пароль снова оказывается в истории командной строки. Можно передать его через --conn-password $DB_PASS, но корень проблемы тот же.
Способ 3: Переменные окружения AIRFLOW_CONN_*
Мощный и часто недооценённый способ. Airflow автоматически создаёт connection, если найдёт переменную окружения с именем AIRFLOW_CONN_<CONN_ID> в верхнем регистре. Значение — URI подключения.
export AIRFLOW_CONN_MY_PROD_DB='postgres://user:password@localhost:5432/dbname'
В коде DAG обращаемся как обычно к conn_id='my_prod_db'. Особенно удобно в Docker и Kubernetes: подставляйте секреты через механизмы контейнерной платформы (Kubernetes Secrets, Docker Secrets). Пароли никогда не попадают в код или базу Airflow.
Способ 4: Secrets Backend — продакшен-решение
Для серьёзных инсталляций используйте внешние хранилища секретов: HashiCorp Vault, AWS SSM Parameter Store, AWS Secrets Manager, GCP Secret Manager. Конфигурация задаётся в airflow.cfg или через env-переменные.
Пример для HashiCorp Vault:
[secrets]
backend = airflow.providers.hashicorp.secrets.vault.VaultBackend
backend_kwargs = {"connections_path": "airflow/connections", "url": "http://127.0.0.1:8200"}
В Vault по пути airflow/connections/my_prod_db кладёте JSON:
{"conn_type": "postgres", "host": "localhost", "login": "user", "password": "pass", "port": 5432}
Airflow будет запрашивать секрет при каждом обращении к hook. Плюсы: централизованное управление, аудит, ротация паролей без остановки Airflow.
Типичные грабли
- Путаница с приоритетами. Airflow ищет connection в порядке: Secrets Backend -> Переменные окружения
AIRFLOW_CONN_*-> База данных Airflow. Убедитесь, что в базе не осталось старых подключений, перекрывающих ваши env-переменные. - Экранирование спецсимволов в URI. Если в пароле есть
@,#,%, их нужно percent-encode. Дляp@ss%wordстрока будетpostgres://user:p%40ss%25word@host/db. - Лишние права. Для работы с внешними Secrets Backend (например, Vault) инстанс Airflow должен иметь права на чтение секретов. Настройте политики доступа аккуратно, по принципу наименьших привилегий.
- Кэширование. Некоторые Secrets Backend кэшируют значения для производительности. Учитывайте это при смене паролей.
Выбор метода зависит от вашего стека: для локального развития хватит UI, в продакшене на Kubernetes используйте связку AIRFLOW_CONN_* + Kubernetes Secrets, а в зрелой инфраструктуре — внешний Secrets Backend. Главное — ни один пароль не должен оказаться в вашем репозитории с DAG.