PowerShell で GitHub に wget(Invoke-WebRequest) できない場合の対処方法

久しぶりに PowerShell で wget(Invoke-WebRequest) を使ったら、下記エラーが発生して目的のファイルを取得できませんでした。
※下記では Ruby 2.5.0 を取得しようとしています

```powershell
> wget https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-2.5.0-1/rubyinstaller-2.5.0-1-x64.7z -OutFile rubyinstaller-2.5.0-1-x64.7z
wget : 要求は中止されました: SSL/TLS のセキュリティで保護されているチャネルを作成できませんでした
発生場所 行:1 文字:1
+ wget https://github.com/oneclick/rubyinstaller2/releases/download/rub ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]、WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
```

どうやら 2018/02/23 04:00 JST から [GitHub が TLS 1.2 のみサポートするようになった](https://githubengineering.com/crypto-removal-notice/) とのことで、 PowerShell のデフォルト設定では TLS 1.2 には対応しておらず、エラーとなっていました。

## 対処方法

PowerShell を起動し、下記手順を実施して TLS 1.2 を有効化すると、 GitHub に wget できるようになりました。

1. PowerShell で有効になっている暗号化形式を確認します

    ```powershell
> [Net.ServicePointManager]::SecurityProtocol
Ssl3, Tls
```
    上記実行結果より、 SSL 3.0, TLS 1.0 が有効化されていることが分かります。ここで Tls12 と表示される場合は TLS 1.2 が有効になっているため、別の原因が考えられます。

1. PowerShell で TLS 1.2 を有効化します

    ```powershell
> [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
```
    1. のコマンドを再度実行し `Tls12` と表示されれば、 TLS 1.2 が有効になっていることを確認できます。

なお、上記手順では PowerShell を起動する度に、 TLS 1.2 を有効化するコマンドを入力する必要があるため、少々面倒です。

そこで、 PowerShell を起動したら、自動的に TLS 1.2 を有効化するように設定します。
bash でいう .bash_profile のようなものが PowerShell にもあるので、そこから設定していきます。
※レジストリから設定する方法もあるようですが、レジストリはあまりいじりたくないので

下記コマンドで PowerShell のプロファイルの場所を確認します。

```powershell
> $profile
C:\Users\xxxxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
```

コマンドの実行結果より、
 `C:\Users\xxxxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` のファイルをテキストエディタで開きます。
※ユーザ名部分は xxxxx でマスキングしています。自身の環境に応じて適宜置き換えてください

下記を追記してファイルを保存します。
PowerShell を新たに起動し、 `[Net.ServicePointManager]::SecurityProtocol` の実行結果が `Tls12` と表示されれば設定完了です。
これで毎回 TLS 1.2 を有効化するコマンドを入力しなくても良くなりました。

```powershell
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
```

### TLS 1.2 以外も有効化する

TLS 1.2 のみだと、まだまだ対応していないところもあると思います。その場合は下記コマンドのように、有効化したいバージョンを `-bor` でつなげます。
※下記コマンドは TLS 1.2 と TLS 1.1 を有効化する場合です

```powershell
[System.Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11
```

ちなみに、 PowerShell でサポートしているバージョンは下記コマンドから確認できます。

```powershell
> [enum]::GetNames([Net.SecurityProtocolType])
SystemDefault
Ssl3
Tls
Tls11
Tls12
```

## 参考文献

- [Weak cryptographic standards removal notice | GitHub Engineering](https://githubengineering.com/crypto-removal-notice/)
- [Building PowerShell in Windows results in a mismatch in security certificates · Issue #6233 · PowerShell/PowerShell](https://github.com/PowerShell/PowerShell/issues/6233)
- [Force PowerShell to use TLS 1.2 · pauby.com](https://blog.pauby.com/post/force-powershell-to-use-tls-1-2/)
- [PowerShell で Profile を利用して スクリプトの自動読み込みをしてみよう - tech.guitarrapc.cóm](http://tech.guitarrapc.com/entry/2013/09/23/164357)