通过 SFTP 集成
SFTP(Secure File Transfer Protocol)是 QI DTVM 提供基金报告下载的渠道。可用的报告模板、每个文件逐列的格式说明以及可下载的示例,参见 DTVM 报告文档。
集成时,建议使用实现了该协议的库和客户端,例如 Python 的 paramiko、命令行的 sftp 或任何标准 SFTP 客户端。
如需申请访问权限,请联系 integracao.dtvm@qitech.com.br。先开通 Sandbox,再开通生产环境。
认证方式
访问通过 SSH 公钥认证——没有密码。您生成密钥对,自行保管私钥,只将公钥发送给我们,由我们将其注册到您的 SFTP 用户下。
| 提供方 | 提供内容 |
|---|---|
| 您 | 公钥(.pub 文件),OpenSSH 格式 |
| QI DTVM | HOSTNAME、PORT(22)和 USERNAME,以及主机的指纹(fingerprint) |
QI Tech 的任何团队都不会向您索要私钥。如果有人索要——无论是通过邮件、工单还是任何其他渠道——那都不是我们。第 3 步所述的 1Password 共享仅用于公钥(sftp_qitech.pub)。
如果私钥已经发送给他人或作为附件上传到任何地方,请视其为已泄露:生成新的密钥对,并将新公钥发送给我们。
1. 生成密钥对
请生成一对专用于 SFTP 的密钥。不要复用签名 JWT token 的密钥:两者是不同系统的凭证,生命周期也不同——轮换其中一个会迫使另一个也必须轮换,任何一方泄露都会同时影响两者。
将 company-name 替换为贵公司的名称——例如 sftp-acme。该文本只是密钥中的注释,用于帮助我们识别密钥。
- Linux / macOS
- Windows (PowerShell)
- Windows (cmd)
- Windows (WSL)
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
New-Item -ItemType Directory -Force "$env:USERPROFILE\.ssh" | Out-Null
ssh-keygen -t ed25519 -C "sftp-company-name" -f "$env:USERPROFILE\.ssh\sftp_qitech"
if not exist "%USERPROFILE%\.ssh" mkdir "%USERPROFILE%\.ssh"
ssh-keygen -t ed25519 -C "sftp-company-name" -f "%USERPROFILE%\.ssh\sftp_qitech"
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
在 WSL 中,请使用 Linux 路径(~/.ssh)。密钥保存在 WSL 的文件系统中,而不是 Windows 用户目录下。
每个标签页都以对应程序能识别的方式书写目录路径,因此各命令不可互换。如果在其他程序中运行某个标签页的命令,会出现 No such file or directory,且不会生成任何密钥——此时只需返回并复制正确标签页中的命令即可。
在 Windows 上,如果不确定使用哪个,请使用 PowerShell:它是 Windows 终端默认打开的程序。
该命令会询问密码短语(passphrase),并生成两个文件:
| 文件 | 说明 |
|---|---|
sftp_qitech | 私钥。 切勿发送,切勿共享。 |
sftp_qitech.pub | 公钥。 这是需要发送给我们的文件。 |
关于密码短语:
- 自动化集成(由您的服务下载报告):留空,在两次提示时直接按 Enter,并在私钥的存储位置对其加以保护,例如使用访问受限的密钥管理器。运行时必须对进程可用的密码短语并不能提供真正的保护。
- 个人使用:请设置密码短语。
ssh-keygen 创建的私钥默认只对您的用户可读。如果将该文件复制到另一台机器,请恢复其权限——SSH 客户端会拒绝其他用户可读的私钥:
chmod 600 ~/.ssh/sftp_qitech
2. 检查公钥格式
.pub 文件的内容是单独一行,以密钥类型开头,以注释结尾:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE1wA3uBEFYG+Yi7zIw7/YUJJ4fBB0MUZsvUVaqyyv6M sftp-acme
发送前请检查该文件:
ssh-keygen -lf ~/.ssh/sftp_qitech.pub
预期输出为密钥的指纹,格式为 256 SHA256:... sftp-acme (ED25519)。如果命令返回 is not a public key file,说明文件已损坏或不是 OpenSSH 公钥。
如果您的密钥是 PEM/X.509 格式
以 -----BEGIN PUBLIC KEY----- 开头的密钥是 PEM/X.509 格式,即 OpenSSL 的默认格式。该格式无法注册到 SFTP:服务器要求单行的 OpenSSH 格式。
如果该密钥本就专用于 SFTP,则无需重新生成——只需转换即可:
-
您仍持有对应的私钥。 适用于任何类型的密钥:
ssh-keygen -y -f path/to/private_key -
您只有 PEM 格式的公钥。 适用于 RSA 密钥:
ssh-keygen -i -m PKCS8 -f path/to/public_key.pem
两条命令都会将 OpenSSH 格式的密钥输出到标准输出。转换不会保留原始注释;如有需要,可在行尾加上 sftp-company-name。
3. 发送公钥
请通过 1Password 将条目共享给集成团队来发送公钥。我们通过这一渠道接收密钥:它能完整保留您生成的内容,并使发送来源可验证——如果有人能在传输途中替换您的公钥,就能获得您 SFTP 目录的访问权限。
- 在 1Password 中创建一个条目,将
sftp_qitech.pub文件的内容以纯文本形式、单行、不换行粘贴进去。 - 附上密钥的指纹——即上一步
ssh-keygen -lf的输出。我们会将其与收到的密钥指纹进行比对,确认密钥在传输中未被篡改。 - 将该条目共享给集成团队,并发送邮件至 integracao.dtvm@qitech.com.br 告知已完成共享。
.docx 或 .pdf 中这些程序的自动格式化会替换字符(把 + 换成破折号、把直引号换成弯引号)并插入换行。任何一处改动都会使密钥失效,而错误只会在连接时才出现。
公钥注册完成后,我们会确认开通,并发送 HOSTNAME、USERNAME 和主机的指纹。
4. 连接 SFTP
首次连接时核对 host key
首次连接时,客户端会询问您是否信任该服务器。请勿未经核对就接受:将显示的指纹与集成团队发送的指纹进行比对。正是这一比对能防止其他服务器冒充我们的服务器。
ssh-keyscan -t ed25519 <hostname> > qitech_host_key
ssh-keygen -lf qitech_host_key # 与 QI DTVM 发送的指纹进行比对
cat qitech_host_key >> ~/.ssh/known_hosts
核对完成后,known_hosts 即成为客户端的参照,与其他 host key 的连接会被自动拒绝。
连接凭证
| 凭证 | 来源 |
|---|---|
HOSTNAME | 服务器地址,由 QI DTVM 提供 |
PORT | 22 |
USERNAME | 用户名,由 QI DTVM 提供 |
| 私钥 | 您生成的 sftp_qitech 文件 |
这些凭证可直接访问您基金的报告,不得共享。
代码示例
- Python
import paramiko
HOSTNAME = "sftp.example.com" # 由 QI DTVM 提供
PORT = 22
USERNAME = "username" # 由 QI DTVM 提供
PRIVATE_KEY = "/path/to/sftp_qitech" # 您生成的私钥
KNOWN_HOSTS = "/path/to/known_hosts" # 包含已核对的 QI DTVM host key
client = paramiko.SSHClient()
client.load_host_keys(KNOWN_HOSTS)
# 如果 host key 与预期不符,则拒绝连接。
# 不要使用 AutoAddPolicy:它会不加验证地接受任何服务器。
client.set_missing_host_key_policy(paramiko.RejectPolicy())
client.connect(
hostname=HOSTNAME,
port=PORT,
username=USERNAME,
key_filename=PRIVATE_KEY, # paramiko 会根据文件识别密钥类型
look_for_keys=False,
allow_agent=False,
timeout=30,
)
try:
with client.open_sftp() as sftp:
# 列出可用文件
for name in sftp.listdir("/"):
print(name)
# 下载文件
sftp.get("remote/path/file.csv", "local/path/file.csv")
finally:
client.close()
5. 下载文件
文件以基金简称、报告模板和 YYYY-MM-DD 格式的参考日期命名:
example_name_assets_wallet_composition_2026-07-29.csv
可用的报告模板、每个文件逐列的格式说明以及可下载的示例,参见 DTVM 报告文档。
本页所述的报告 SFTP 仅用于下载文件;不允许上传。
密钥轮换与吊销
如需更换密钥,请按第 1 至第 3 步生成新的密钥对,并通过 1Password 将新公钥发送给我们。我们会注册新密钥,并在移除旧密钥时通知您——这样更换过程不会出现服务中断窗口。
如怀疑私钥已泄露,请在同一联系中告知集成团队:我们会在注册新密钥之前立即吊销旧密钥的访问权限。