Unable to load the service index for source 排錯過程分享
- 2020 年 3 月 14 日
- 筆記
問題背景:
.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程式碼)時的證書錯誤問題,因此這裡一併分享下

隨後產生了幾個思路:
①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一起升級到最新版
參考如下步驟解決:
l rpm -ivh http://mirror.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm
l vim /etc/yum.repos.d/city-fan.org.repo編輯city-fa源把 enabled=0 改為 enabled=1
l 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,成功!

請注意:
使用SDK時,直接下載壓縮包解壓的這種方式大概率會有依賴文件缺失,之前在使用PHP SDK的時候就有遇到。
最穩妥的辦法就是git clone獲取完整的SDK,請大家記住!!!
至少在PHP SDK、.NET SDK 都遇到了。