You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Airflow SFTPHook私钥认证失败:UI测试正常DAG执行报错

Airflow SFTPHook 执行时密码认证失败(UI测试连接成功)

问题核心

使用apache/airflow:2.3.2-python3.10镜像运行Airflow,已指定paramiko==2.7.2,SFTP连接在UI测试时成功,但DAG执行时触发Authentication (password) failed错误——日志显示系统尝试密码认证而非配置的私钥。

关键原因

UI测试连接与DAG执行的环境/配置解析逻辑存在差异:UI对私钥格式的容错性更高,但DAG执行时JSON配置中的换行符会导致私钥解析失败,Paramiko会自动 fallback 到密码认证流程。

解决方案

1. 修正Connections Extra中的私钥格式

JSON不允许直接包含换行符,需将私钥中的换行替换为\n转义字符,或对整个私钥进行Base64编码:

方式一:转义换行符

{
  "private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\nabcdefghijklmnopqrstuvwxyz...\n-----END OPENSSH PRIVATE KEY-----",
  "no_host_key_check": true
}

方式二:Base64编码私钥

将本地私钥文件编码为Base64字符串(Linux/macOS可执行base64 -w0 your_private_key),然后配置:

{
  "private_key": "YOUR_BASE64_ENCODED_PRIVATE_KEY",
  "no_host_key_check": true,
  "private_key_passphrase": "YOUR_PASSPHRASE_IF_ANY"
}

2. 自定义SFTPHook强制密钥认证

若默认Hook仍自动切换认证方式,可重写Hook逻辑,强制仅使用私钥认证:

from airflow.providers.sftp.hooks.sftp import SFTPHook
import paramiko

class CustomSFTPHook(SFTPHook):
    def get_conn(self):
        conn = self.get_connection(self.conn_id)
        ssh_client = paramiko.SSHClient()
        
        # 关闭主机密钥检查
        if conn.extra_dejson.get("no_host_key_check"):
            ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        # 加载私钥
        private_key_str = conn.extra_dejson.get("private_key")
        try:
            # 处理带密码的私钥
            passphrase = conn.extra_dejson.get("private_key_passphrase")
            private_key = paramiko.RSAKey.from_private_key_str(private_key_str, password=passphrase)
        except paramiko.PasswordRequiredException:
            # 无密码的私钥
            private_key = paramiko.RSAKey.from_private_key_str(private_key_str)
        
        # 强制使用私钥认证,禁用本地密钥查找和代理
        ssh_client.connect(
            hostname=conn.host,
            username=conn.login,
            pkey=private_key,
            port=conn.port or 22,
            look_for_keys=False,
            allow_agent=False,
            password=None  # 显式禁用密码认证
        )
        self.ssh_client = ssh_client
        return ssh_client.open_sftp()

在DAG中使用自定义Hook替代默认SFTPHook:

hook = CustomSFTPHook("your_sftp_connection_id")

3. 确认Worker环境一致性

确保Airflow Worker容器与Webserver使用相同镜像,且paramiko==2.7.2已正确安装——版本不一致可能导致私钥解析逻辑差异。

内容的提问来源于stack exchange,提问作者Ryan Czarny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:03:37