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程式碼)時的證書錯誤問題,因此這裡一併分享下

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一起升級到最新版

參考如下步驟解決:

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 都遇到了。