SuperAPI AI 工具集

dotnet-devcert-trust

部署与运维

查看项目

更新于 10-15 13:49

技能介绍

该技能面向 Linux 环境下的 .NET HTTPS 开发证书信任问题,提供诊断与修复方法,覆盖从证书生成到系统 CA 捆绑包收录的完整生命周期。

适用场景 当出现以下情况时可使用该技能:Aspire 中 Redis TLS 连接失败并报 UntrustedRoot 或 RemoteCertificateNameMismatch;dotnet dev-certs https --check --trust 返回退出码 7;HTTPS localhost 连接出现证书校验错误;运行 dotnet dev-certs https --clean 后需要恢复信任;为新 Linux 开发机配置 .NET HTTPS 开发环境;Aspire 仪表板或服务间 gRPC 调用出现 TLS 错误;从 Aspire 13.1.0 之前版本升级(此前 Redis 默认不使用 TLS)。

问题背景 在 Windows 和 macOS 上,dotnet dev-certs https --trust 会自动完成证书生成、安装到用户存储并加入系统信任存储。而在 Linux 上,该命令几乎不起作用:它会生成证书并放入用户存储,但不会将证书导出到系统 CA 目录,不会运行 update-ca-certificates 重建 CA 捆绑包,也不会将证书加入浏览器信任存储(NSS/NSSDB);--trust 标志会静默成功,但证书仍不受信任。因此 .NET 应用、OpenSSL、curl 和浏览器都会拒绝该开发证书,即便 dotnet dev-certs https --check 报告证书存在。

与 Aspire 13.1.0+ 的关系 Aspire 13.1.0 之前 Redis 连接使用明文;从 13.1.0 开始,Aspire 默认在 Redis 上启用 TLS。若开发证书未在系统级受信任,Redis 连接会立即失败并报证书链 UntrustedRoot。

Linux 证书信任机制 应用(.NET、curl、OpenSSL)读取的是合并后的 CA 捆绑包 /etc/ssl/certs/ca-certificates.crt,该捆绑包由 update-ca-certificates 构建,其输入为 /usr/share/ca-certificates/(发行版 CA)和 /usr/local/share/ca-certificates/(本地 CA),并写出 /etc/ssl/certs/ca-certificates.crt 和 /etc/ssl/certs/*.pem 符号链接。关键点:将 .crt 文件放入 /usr/local/share/ca-certificates/ 是必要但不充分的,必须运行 update-ca-certificates 重建捆绑包;应用读取的是捆绑包,而非单个文件。

五步诊断流程 按顺序执行,遇到第一个 FAIL 即应用对应修复后再继续。

检查 1:开发证书是否存在。运行 dotnet dev-certs https --check 并查看退出码;退出码 0 表示用户存储中存在证书,通过;非零表示无有效开发证书,需运行 dotnet dev-certs https。

检查 2:系统信任存储中的单个证书与正确权限。执行 ls -la /usr/local/share/ca-certificates/ | grep -iE 'dotnet|aspnet'。仅存在 dotnet-dev-cert.crt 且权限为 -rw-r--r--(644)为通过;存在多个证书文件、权限错误或残留 aspnet* 文件为失败。常见残留文件包括:aspnetcore-dev.crt(常以 0600 权限创建,update-ca-certificates 无法读取)、aspnet/https.crt(旧约定,指纹可能与当前开发证书不同)、dotnet-dev-cert.crt 权限为 0600(名称正确但权限错误)。修复方式为删除所有残留证书文件并确保权限为 644。

检查 3:CA 捆绑包收录。这是最常失败的检查:证书文件存在但从未加入捆绑包。使用 openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt 验证。返回 dotnet-dev-cert.crt: OK 为通过;返回 unable to get local issuer certificate 或 unable to get issuer certificate(不同 OpenSSL 版本)为失败,说明捆绑包从未重建。修复方式为运行 sudo update-ca-certificates(预期输出包含“1 added”之类),然后重新验证。

检查 4:环境变量覆盖。SSL 相关环境变量可能将证书查找重定向到系统捆绑包之外:SSL_CERT_DIR、SSL_CERT_FILE、DOTNET_SSL_CERT_DIR、DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER。全部未设置为通过;任一变量被设置则为失败,需从 shell 配置文件(~/.bashrc、~/.zshrc、~/.profile)中移除并开启新 shell。

检查 5:符号链接完整性。执行 find /etc/ssl/certs/ -xtype l 2>/dev/null | head -5。无输出为通过;列出损坏符号链接为失败,需运行 sudo update-ca-certificates --fresh 从头重建所有符号链接。

完整恢复流程 当多项检查失败或需要干净状态时,可运行一段 bash 脚本:删除所有残留证书文件;执行 dotnet dev-certs https --clean 与 dotnet dev-certs https 重新生成;导出为 PEM 并安装到系统信任存储(复制到 /usr/local/share/ca-certificates/dotnet-dev-cert.crt 并设 644);运行 sudo update-ca-certificates 重建 CA 捆绑包(关键且最常被遗漏的步骤);最后用 openssl verify 验证。脚本可保存为 ~/fix-devcert.sh 并按需运行。

各发行版差异 Ubuntu/Debian 使用上述流程,CA 目录为 /usr/local/share/ca-certificates/,重建命令为 sudo update-ca-certificates,捆绑包为 /etc/ssl/certs/ca-certificates.crt,证书为 PEM 且需 .crt 扩展名。Fedora/RHEL/CentOS 使用 update-ca-trust,CA 目录为 /etc/pki/ca-trust/source/anchors/,捆绑包为 /etc/pki/tls/certs/ca-bundle.crt,扩展名 .pem(任意扩展名均可),流程为导出、复制、chmod 644、运行 sudo update-ca-trust 并验证。Arch Linux 与 Fedora 类似,使用 /etc/ca-certificates/trust-source/anchors/ 和 sudo update-ca-trust。WSL2 运行真实 Linux 内核、拥有独立证书存储,标准 Ubuntu/Debian 流程适用,但需注意:共享文件系统(/mnt/c/)上的证书文件可能不具备 644 权限,应始终先复制到原生 Linux 路径;部分较旧 WSL2 未运行 systemd,若命令挂起可尝试 sudo dpkg-reconfigure ca-certificates;使用 Docker Desktop 的 WSL2 后端时,容器继承 WSL2 发行版的 CA 捆绑包,修复 WSL2 即可修复容器。

Aspire 相关注意事项 Redis TLS(Aspire 13.1.0+):若 Redis 连接错误出现 UntrustedRoot,说明开发证书未在系统级受信任,应执行完整恢复流程。Aspire 仪表板 HTTPS:仪表板使用开发证书,若浏览器显示证书警告,说明证书不在浏览器信任存储中;开发时点击跳过警告可以接受,系统级信任(Redis、gRPC 等所需)才是优先项。ASPIRE_ALLOW_UNSECURED_TRANSPORT:设为 true 是权宜之计而非修复,它禁用服务间通信的 TLS,会掩盖底层信任问题、与生产行为不符,并可能产生与生产不同的 bug,应改为修复证书信任。

证书生命周期 开发证书自创建起有效期为 1 年。过期时 dotnet dev-certs https --check 会报告无有效证书,需运行完整恢复流程生成新证书;/usr/local/share/ca-certificates/ 中的旧证书文件会被替换,update-ca-certificates 会在捆绑包中用新证书替换旧证书。无需重启系统,应用会在下次 TLS 握手时使用新捆绑包(重启应用即可)。

CI/CD 自动化 在 Linux 运行器上的 CI/CD 中很少需要开发证书(通常测试真实证书或禁用 TLS 校验),但如果集成测试需要受信任的开发证书,可在 GitHub Actions 或 Azure DevOps 中依次执行:dotnet dev-certs https、导出 PEM、复制到 /usr/local/share/ca-certificates/dotnet-dev-cert.crt、chmod 644、删除临时文件、sudo update-ca-certificates。

常见陷阱

  1. 证书已放置但捆绑包从未重建:症状为证书文件存在但 openssl verify 失败;原因是放置文件后未运行 update-ca-certificates;修复为 sudo update-ca-certificates。这是最常见的错误,CA 目录只是捆绑包生成过程的输入,而非捆绑包本身。2. 权限错误的残留证书文件:update-ca-certificates 报告 0 added;原因是 0600 权限文件不可读;修复为 chmod 644。3. 不同会话的多个证书文件:旧证书文件残留导致指纹不匹配;修复为删除所有 dotnet* 和 aspnet* 文件后重新导出当前证书。4. clean/regenerate 后指纹不匹配:openssl verify 通过但 .NET 仍报 UntrustedRoot;原因是系统信任的是旧证书;修复为重新导出并重新安装,然后运行 update-ca-certificates。5. 误以为 --trust 生效:dotnet dev-certs https --trust 返回 0 但实际未信任;原因是 Linux 上 --trust 不会调用 update-ca-certificates;修复为不要依赖 --trust,改用本技能的手动流程。

快速参考命令包括:生成开发证书、导出 PEM、安装到系统信任(Ubuntu/Debian)、验证信任、查看证书详情(openssl x509 -in ... -noout -subject -dates -fingerprint),以及彻底清理并重建(dotnet dev-certs https --clean && dotnet dev-certs https)。相关技能有 dotnet-skills:aspire-configuration(Aspire AppHost 配置含 TLS 设置)和 dotnet-skills:aspire-service-defaults(服务默认值含 HTTPS 配置)。