トップ回答者
SFTPでのファイルアップロード方法

質問
-
先方からSFTPでアップロードしてほしいとの依頼がありました。
とあるサイトからFTPでのアップロード方法を調査し、下記のスクリプトに
$ftpReq.EnableSsl = $true
と言う一行を追加し、実行したところし「検証プロシージャによると、リモート証明書は無効です。」
と言うエラーが発生しました。
SFTPでファイルをアップロードするにはFTPでのアップロードに加え、どのような情報が必要なのでしょうか。
先方からはアドレス、ID、パスワードに加え、ポートを990でと言う指示もあります。
ポートはどのように設定すれば良いのでしょうか。===========コード==============
$ftpFileName = "ftp://address/" + $fileName
$ftpReq = [System.Net.FtpWebRequest]::Create($ftpFileName)
$ftpReq.Credentials = New-Object System.Net.NetworkCredential("id","pass")
$ftpReq.Method = [System.Net.WebRequestMethods+ftp]::UploadFile
$ftpReq.KeepAlive = $true
$ftpReq.UseBinary = $true
$ftpReq.EnableSsl = $true
$ftpReq.UsePassive = $false
$ftpReq.TimeOut = 10000
$stream = $ftpReq.GetRequestStream()
$fileStream = New-Object System.IO.FileStream($fileName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
回答
-
FTPサーバー側で自己署名証明書を使用しているのではないでしょうか?
その証明書の妥当性をクライアントが検証できないため、エラーになっているものと思われます。
もしクライアント側にサーバーで使用している自己署名証明書をインストールする権限があるのなら、実施すればOKです。
仮にできない場合でも、クライアントでの妥当性検証方法をコードで指定することで、この問題に対処できます。
具体的には、以下のコードをスクリプト先頭に挿入しておくことになります。
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
このコードでは{}の中身のスクリプトが、証明書の妥当性検証を行うときに実行されるようになりますが、単に$trueを返すようにしておけば、すべての検証がOK(証明書は妥当)ということになります。本来であれば、妥当性を検証するコードをちゃんと書くべきですが、他にデータのセキュアなリモートダウンロードを行うコードがスクリプト中に含まれていないならば、これでも一応用は足りるかと思います。
なお、より詳細な話をすると、上記のコードはスクリプトブロックからデリゲートへの型変換機能を使っています。この機能はたしかPowerShell 3.0からのものなので、2.0以下の場合はもうちょっと複雑になると思います。その場合はまた聞いてください。
- 回答としてマーク UltraKatan 2014年7月28日 10:48
すべての返信
-
FTPサーバー側で自己署名証明書を使用しているのではないでしょうか?
その証明書の妥当性をクライアントが検証できないため、エラーになっているものと思われます。
もしクライアント側にサーバーで使用している自己署名証明書をインストールする権限があるのなら、実施すればOKです。
仮にできない場合でも、クライアントでの妥当性検証方法をコードで指定することで、この問題に対処できます。
具体的には、以下のコードをスクリプト先頭に挿入しておくことになります。
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
このコードでは{}の中身のスクリプトが、証明書の妥当性検証を行うときに実行されるようになりますが、単に$trueを返すようにしておけば、すべての検証がOK(証明書は妥当)ということになります。本来であれば、妥当性を検証するコードをちゃんと書くべきですが、他にデータのセキュアなリモートダウンロードを行うコードがスクリプト中に含まれていないならば、これでも一応用は足りるかと思います。
なお、より詳細な話をすると、上記のコードはスクリプトブロックからデリゲートへの型変換機能を使っています。この機能はたしかPowerShell 3.0からのものなので、2.0以下の場合はもうちょっと複雑になると思います。その場合はまた聞いてください。
- 回答としてマーク UltraKatan 2014年7月28日 10:48
-
あとポート番号指定ですが、
$ftpFileName = "ftp://address:990/" + $fileName
のようにURIに指定するだけでいけるんじゃないでしょうか。
- 回答としてマーク UltraKatan 2014年7月28日 10:48
- 回答としてマークされていない UltraKatan 2014年7月28日 10:48
-
余談ですが…
先方の指定したsftpの正式名称はSSH File Transfer ProtocolでSSHを使うもので、.NET Frameworkでは実現できません。sftpとは別にftpsというものがありこちらはFile Transfer Protocol over SSL/TLSです。こちらは.NET Frameworkも対応しています。ポート番号は990が一般的なので、たぶん先方の指示が間違っているのだと思います。
また今回のエラーとは別ですがUsePassiveを$trueにした方がつながりやすいです。
- 回答としてマーク UltraKatan 2014年7月28日 10:48
- 回答としてマークされていない UltraKatan 2014年7月28日 10:49