1. 为什么需要配置Airflow API认证
最近在部署Airflow 3.1.5时遇到了API访问控制的问题。默认安装的Airflow虽然功能强大,但API接口是完全开放的,这在生产环境中存在严重安全隐患。想象一下,如果你的任务调度系统API可以被任何人随意调用,那将导致多么混乱的局面。
我选择3.1.5版本是因为它修复了之前版本中的多个安全漏洞,同时引入了更灵活的API认证机制。这次配置主要解决两个核心问题:一是防止未授权访问,二是实现细粒度的权限控制。
2. 认证方案选型与对比
2.1 可用认证方式分析
Airflow 3.1.5支持多种认证方式,经过实测对比,我整理出以下方案特点:
| 认证类型 | 实现复杂度 | 安全性 | 适用场景 | 维护成本 |
|---|---|---|---|---|
| Basic Auth | 低 | 中 | 内部测试环境 | 低 |
| JWT | 中 | 高 | 前后端分离架构 | 中 |
| OAuth | 高 | 极高 | 企业级系统集成 | 高 |
| Kerberos | 极高 | 极高 | 金融等特殊行业 | 极高 |
2.2 最终选择JWT的原因
考虑到我们团队的技术栈和实际需求,最终选择了JWT方案:
- 前端使用Vue.js,天然适配JWT的无状态特性
- 不需要额外的认证服务器
- 可以灵活设置token有效期
- 支持自定义claims实现细粒度权限控制
重要提示:如果选择Basic Auth,务必配合HTTPS使用,否则密码将以明文传输
3. 详细配置步骤
3.1 基础环境准备
首先确保已安装以下组件:
- Airflow 3.1.5(必须精确版本)
- Python 3.8+(建议3.9)
- cryptography库(用于JWT签名)
bash复制pip install apache-airflow==3.1.5 cryptography
3.2 核心配置参数
在airflow.cfg中添加以下配置项:
ini复制[api]
auth_backends = airflow.api.auth.backend.jwt
enable_experimental_api = true
[api_auth]
jwt_secret_key = your-256-bit-secret
jwt_algorithm = HS256
jwt_issuer = airflow.example.com
jwt_audience = airflow-client
jwt_leeway = 30
参数说明:
jwt_secret_key:至少32字符的强密码jwt_leeway:解决服务器间时钟偏差的缓冲时间(秒)jwt_algorithm:生产环境建议使用RS256而非HS256
3.3 JWT签发与验证实现
创建自定义认证中间件:
python复制from airflow.api.auth.backend.jwt import JWTAuthenticationBackend
from datetime import datetime, timedelta
import jwt
class CustomJWTBackend(JWTAuthenticationBackend):
def create_jwt_token(self, user):
payload = {
'sub': user.username,
'exp': datetime.utcnow() + timedelta(hours=1),
'iat': datetime.utcnow(),
'roles': ['user'] # 自定义claims
}
return jwt.encode(
payload,
self.secret_key,
algorithm=self.algorithm
)
4. 生产环境强化措施
4.1 密钥管理最佳实践
千万不要像示例那样硬编码密钥!推荐方案:
- 使用环境变量注入密钥
- 定期轮换密钥(建议每月)
- 不同环境使用不同密钥
python复制import os
secret_key = os.getenv('AIRFLOW_JWT_SECRET')
4.2 权限细粒度控制
在DAG定义中增加权限校验:
python复制from airflow.decorators import dag
from airflow.operators.python import PythonOperator
from airflow.api.common.experimental import check_authorization
@dag(schedule_interval='@daily')
def sensitive_operations_dag():
@check_authorization(required_roles=['admin'])
def critical_operation():
# 敏感操作代码
pass
PythonOperator(
task_id='critical_task',
python_callable=critical_operation
)
5. 常见问题排查指南
5.1 Token失效问题
症状:频繁收到401 Unauthorized
- 检查服务器时钟是否同步(NTP服务)
- 确认token没有超过exp设置的时间
- 验证jwt_leeway配置是否合理
5.2 跨域访问问题
解决方案:
python复制from flask_cors import CORS
CORS(app, resources={r"/api/*": {"origins": ["https://your-domain.com"]}})
5.3 性能优化建议
当API调用频繁时:
- 启用JWT缓存(建议Redis)
- 适当延长token有效期(但不超过24小时)
- 使用RS256替代HS256算法
6. 监控与日志配置
添加专门的API审计日志:
python复制from airflow.utils.log.logging_mixin import LoggingMixin
class APIAuditLogger(LoggingMixin):
def log_access(self, request):
self.log.info(
f"API访问记录 - 用户:{request.user} "
f"路径:{request.path} "
f"状态:{request.status_code}"
)
在config中启用:
ini复制[logging]
remote_logging = True
remote_base_log_folder = s3://your-bucket/airflow-logs/
7. 版本升级注意事项
从旧版本迁移时需要特别注意:
- 先备份现有jwt_secret_key
- 逐步切换不要立即停用旧密钥
- 使用双写策略过渡期间
python复制# 过渡期配置示例
jwt_secret_keys = [
os.getenv('JWT_SECRET_NEW'),
os.getenv('JWT_SECRET_OLD') # 保留旧密钥
]
8. 客户端集成示例
前端调用示例(Axios):
javascript复制const login = async () => {
const res = await axios.post('/api/v1/auth/login', {
username: 'admin',
password: 'admin'
});
// 将token存入localStorage
localStorage.setItem('airflow_token', res.data.token);
// 后续请求携带token
axios.defaults.headers.common['Authorization'] = `Bearer ${res.data.token}`;
};
9. 安全加固进阶方案
对于金融级安全要求:
- 实现IP白名单过滤
- 添加请求频率限制
- 启用双因素认证
- 对接企业SSO系统
python复制from airflow.models import Variable
ALLOWED_IPS = Variable.get('api_allowed_ips', default_var='').split(',')
10. 压力测试建议
使用Locust进行API性能测试:
python复制from locust import HttpUser, task
class AirflowAPIUser(HttpUser):
@task
def trigger_dag(self):
self.client.post(
"/api/v1/dags/example_dag/dagRuns",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"conf": {}}
)
测试要点:
- 逐步增加并发用户数
- 监控API响应时间
- 观察数据库连接数变化
11. 备份与恢复策略
API配置备份方案:
- 定期导出airflow.cfg
- 备份webserver_config.py
- 保存JWT密钥副本(加密存储)
恢复流程:
bash复制# 恢复配置
cp airflow.cfg.bak airflow.cfg
# 重启服务
airflow webserver --reload
12. 容器化部署调整
Docker环境下需要特别注意:
- 密钥通过secret注入
- 确保容器时间同步
- 配置健康检查端点
示例Dockerfile片段:
dockerfile复制ENV AIRFLOW__API__AUTH_BACKENDS=airflow.api.auth.backend.jwt
HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/api/v1/health
13. 替代方案评估
如果JWT方案不满足需求,可以考虑:
- 使用OAuth2代理(如Keycloak Gatekeeper)
- 配置Nginx基础认证层
- 实现自定义认证插件
python复制from airflow.plugins_manager import AirflowPlugin
class CustomAuthPlugin(AirflowPlugin):
name = "custom_auth"
flask_blueprints = [blueprint]
appbuilder_views = [view]
14. 性能监控指标
建议监控的关键指标:
- API平均响应时间
- JWT验证耗时
- 401错误率
- 并发连接数
Prometheus配置示例:
yaml复制- job_name: 'airflow_api'
metrics_path: '/metrics'
static_configs:
- targets: ['airflow-webserver:8080']
15. 自动化测试方案
编写API测试用例:
python复制import pytest
from airflow.api.common.experimental import trigger_dag
class TestAPI:
def test_unauthorized_access(self):
with pytest.raises(AirflowException):
trigger_dag('example_dag', run_id='test')
def test_authorized_access(self, auth_header):
assert trigger_dag('example_dag', run_id='test', headers=auth_header)
16. 密钥轮换自动化
使用HashiCorp Vault实现自动轮换:
python复制import hvac
vault_client = hvac.Client(url='https://vault.example.com')
secret = vault_client.read('secret/airflow/jwt')['data']
17. 客户端缓存策略
合理设置缓存头减少API调用:
python复制from flask import make_response
@app.after_request
def add_cache_header(response):
if request.path.startswith('/api/'):
response.cache_control.max_age = 300
return response
18. 文档自动化生成
集成Swagger UI:
python复制from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL = '/api/docs'
API_URL = '/static/openapi.json'
swagger_ui = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={'app_name': "Airflow API"}
)
19. 请求验证增强
添加请求参数校验:
python复制from marshmallow import Schema, fields
class DagRunSchema(Schema):
conf = fields.Dict(required=False)
execution_date = fields.DateTime(required=False)
20. 灾备方案设计
多活API部署要点:
- 共享同一JWT密钥库
- 配置统一的Redis缓存
- 负载均衡器健康检查
nginx复制upstream airflow_apis {
server api1:8080;
server api2:8080;
check interval=3000 rise=2 fall=5 timeout=1000;
}