自分に対するメモ。
.NET Core で、REST-API にアクセスしたいときに、サーバー証明書の検証をスキップしたい時がある。その時のコードの書き方。今やりたいのは、Kubernetesの REST API のアクセスを.NET Core からしたい。その時に、Kubernetes は独自の証明書を使っているから普通にはアクセスできません。次のサイトにまとまっています。
本来の方法は、上記のブログにかいてあるとおり、ルート証明書を k8s から取得してコンフィグするのでしょうが、最初のステップとして、SSL証明書をスキップして、ちゃんとREST-API が呼べるかどうかを確認しましょう。
実装
.Net Core での書き方は依然とは異なるようで、基本的には、下記のように書いてあげればOK. つまりコールバックの関数をわたすところで、カスタムのコールバックとして、常にTrueを返すという感じ。
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPlicyErrors) => true;
client = new HttpClient(httpClientHandler);
ちなみにソースコードは、Resource のところに、GitHub に置いておきました。
エラーメッセージ
実は、サーバー証明書の検証をスキップするところで結構はまりました。もともと、curl
では、動いていたのですが、C#で実装すると、セキュリティエラー
というあいまいなエラーメッセージがでて全然原因がわかりませんでした。結局 curl
のほうで、--insecure
オプションをつけていたのを忘れたので、気づいたのですが、エラーメッセージからわからないのはつらすぎるので、コントリビュートしてみることを画策中です。
System.Net.Http.HttpRequestException
HResult=0x80072F8F
Message=An error occurred while sending the request.
Source=System.Private.CoreLib
StackTrace:
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at System.Net.Http.DiagnosticsHandler.<SendAsync>d__2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at System.Net.Http.HttpClient.<FinishSendAsyncBuffered>d__58.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at KubernetesRestSpike.Program.<RunAsync>d__7.MoveNext() in C:\Users\tsushi\Source\Repos\CustomBindingsSample\KubernetesRestSpike\Program.cs:line 42
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at KubernetesRestSpike.Program.Main(String[] args) in C:\Users\tsushi\Source\Repos\CustomBindingsSample\KubernetesRestSpike\Program.cs:line 31
Inner Exception 1:
WinHttpException: セキュリティ エラーが発生しました
実装はたぶんこの辺り。まだ見つけられていないので、見つけたらおしえてください。
ServerCertificate
と、思ったら元同僚が助けてくれた。やっぱ彼イケメン!ありがとう!
ちなみに、エラーメッセージはどうやら、Windows からとっているようなので、多分Windows のほうがこのメッセージを変えることは望み薄なので、まずはIssue から始めるといいんじゃない?ってアドバイスくれました。
Hi Tsuyoshi,
Looking at the code, it seems that whenever there is a ServerCertificateValidationCallback set and it returns false, a generic WinHttpException is created with an error message from an error message id:
The message is coming from Windows itself via a call to the Windows API function FormatMessage (https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx) passing in ERROR_WINHTTP_SECURE_FAILURE (12175).
Given Windows is unlikely to change this message, perhaps the CoreFx maintainers would accept a PR to improve the experience.
Your best bet is to file an issue in the dotnet/corefx repo with a full repro.
I hope that helps!
Peter
Issue をポストしておきました。(Resource参照)
今回の反省としては、コードを読めば自分でも理解できる(かも)レベルだったのに、実装のありかにとらわれてエラーメッセージを変更したいという本来のゴールをわすれていたので、探すのに苦労しました。もっと目的にフォーカスしよう。