问题背景:
.NET CORE环境配置好了,跑hello world正常,引用TencentCloud .NET SDK里的TencentCloudTencentCloud.csproj项目后,在编译的时候就有如下报错,甚至代码还是hello world都没改一个字也报这个错。
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : Unable to load the service index for source https://api.nuget.org/v3/index.json.
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : The SSL connection could not be established, see inner exception.
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : The remote certificate is invalid according to the validation procedure.
分析报错本身,第1句可能是NuGet源的问题,第2句和第3句ssl、certificate 都跟https有关,结合分析后,第一个思路:NuGet源URL从https换成http试试?
网上查了下,NuGet源配置文件名称是NuGet.Config
执行find / -name NuGet.Config找到了路径/root/.nuget/NuGet/NuGet.Config,vim修改,替换https URL为http URL,并没有解决问题,报错信息里https URL变成了http URL而已,其他的一个字都没变。
宣告失败,再次分析报错本身,我推断跟证书信任有关系,继续查资料,想起微软官网一篇关于.NET Core证书处理的文档,但是从微软官网文档提供的办法并没有解决,而这个办法确实有解决我Windows上.net sdk 调试web代码(非console代码)时的证书错误问题,因此这里一并分享下
https://docs.microsoft.com/zh-cn/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.1&tabs=visual-studio#trust
随后产生了几个思路:
①curl跟https密切相关,低版本的curl对tls1.2不支持,升级curl有没有可能解决?待第2天白天验证
②在使用php sdk的时候有遇到curl报https相关错误,以为是curl版本较低,升级了curl版本并不管用,最后更新根证书解决,那当前case更新CA根证书ca-bundle能否解决?待第2天白天验证
第2天上午验证这2个思路时
①升级curl,源码编译安装后,curl -V 查看版本确实是高版本7.69了,但是执行curl命令时说curl7.69依赖libcurl7.69,yum update libcurl查看结果原来是libcurl还是低版本,于是想办法把curl 、libcurl一起升级到最新版
参考如下步骤解决:
rpm -ivh http://mirror.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm
vim /etc/yum.repos.d/city-fan.org.repo编辑city-fan.org源把 enabled=0 改为 enabled=1
yum upgrade libcurl curl
这样处理后,curl、libcurl已经是最新版,但dotnet build仍然报这3句错
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : Unable to load the service index for source https://api.nuget.org/v3/index.json.
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : The SSL connection could not be established, see inner exception.
/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : The remote certificate is invalid according to the validation procedure.
②更新CA根证书
网上的资料多有误导,只是让执行curl http://curl.haxx.se/ca/cacert.pem -o /etc/pki/tls/certs/ca-bundle.crt
实际上这样没有用,原因如下:
ls -l /etc/ssl/certs查看/etc/ssl/certs软链接到/etc/pki/tls/certs
ls -l /etc/pki/tls/certs/ca-bundle.crt软链接到/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
真正要更新的是/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
更新证书后,dotnet build仍然报那3句错
绝望之际,我有想到上周调试几种SDK的时候都有引用路径问题,如果CA根证书和dotnet运行环境都没有问题,那是不是在编译的时候没找对CA根证书路径?
此时我搜到了一篇至关重要的文档,这个文档跟我的思路一致,大概看了下文档我就马上去按自己的思路执行了
https://blog.skitisu.com/2020/02/solve-dotnet-restore-nuget-invalid-certificate/
我先是openssl version -a查看了路径:OPENSSLDIR: "/etc/pki/tls",路径没错呀,就是我之前操作的/etc/pki目录,里面有2个子目录比较重要 tls和ca-trust
这里需要注意的就是软链接,不过这个我已经处理好了:/etc/ssl/certs软链接到/etc/pki/tls/certs,/etc/pki/tls/certs/ca-bundle.crt软链接到/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem都是系统默认的,只需要把真正的那个CA根证书文件更新即可
然后我想,是不是系统里还有其他路径的certs
于是我用find / -name certs命令找到了这些,排除其他的可能锁定了/usr/local/openssl/certs
/usr/local/openssl/certs是个空文件夹,而/etc/ssl/certs是个软链接
排查的情况完全跟刚查到的文档吻合了,我激动万分
我马上就去创建软链接了ln -s /etc/pki/tls/certs /usr/local/openssl/certs
然后dotnet build还是报那3句错,真的快崩溃了
我ls -l /usr/local/openssl/certs查看发现它不是软链接
刚才创建的软链接竟然是/usr/local/openssl/certs/certs,因为/usr/local/openssl/certs是个文件夹,我在创建软链接之前没有删除这个同名文件夹,执行创建软链接的命令就把软链接创建到文件夹里面去了
此事告诫我们创建软链接之前,先备份同路径同名文件或文件夹然后删除之再创建
重整旗鼓,删除/usr/local/openssl/certs文件夹,重新执行命令ln -s /etc/pki/tls/certs /usr/local/openssl/certs ,这次创建的软链接没有错
再回到项目目录执行dotnet build,终于不报那3句错了,但是报了154个其他的错
不过这个报错我看了下,不难,就是.net sdk源码包里的.cs文件could not be found,大不了我重新git clone一份
我回到sdk的上层目录
git clone https://github.com/tencentcloud/tencentcloud-sdk-dotnet TencentCloudSDK
获取了一份完整SDK到TencentCloudSDK目录
然后按照如下步骤
①cd TencentCloudSDK
mkdir shawyang
cd shawyang
dotnet new console
dotnet add reference ../TencentCloud/TencentCloud.csproj
dotnet build
dotnet run
以上均无报错,此时再修改Program.cs源代码,换成api explorer里面的接口代码即可
然后再执行dotnet build无报错
再执行dotnet run,成功!
请注意:
1、如果有多个路径的/usr/local/openssl*/*/certs 空文件夹,都得删了这个certs空文件夹然后创建软链接到/etc/pki/tls/certs
如下图,一开始只处理了/usr/local/openssl/certs 并没有成效,后来把另一个路径openssl111里的certs空文件夹处理成软链接才得以解决。
2、使用SDK时,直接下载压缩包解压的这种方式大概率会有依赖文件缺失,之前在使用PHP SDK的时候就有遇到。
最稳妥的办法就是git clone获取完整的SDK,请大家记住!!!
至少在PHP SDK、.NET SDK 都遇到了。