もうプロキシやら証明書やらで迷わない

Git にせよ AWS CLI にせよ、プロキシや証明書まわりの設定は（特に会社から使う場合だと）面倒で、よくわからなくて、毎度ググりながらテキトーにしていた。けど、いいかげんちゃんとするべきだと思ったので、気合入れて調べた＆まとめた。

# 知識として押さえておくこと
設定対象は二つある。

- プロキシを適切に設定する必要がある
- CA 証明書を適切に証明する必要がある

設定箇所は手段ごとに違う。

- ツールによって設定箇所が異なる(ので適切な設定箇所に設定する必要がある)
- 例: Git の場合はここ、AWS CLI の場合はここ、Python の Requests ライブラリの場合は……

## プロキシとは
- 中継サーバのこと
- `https://(your-proxy-address-or-domain):(port)` ← こんな風に URL で表現
- プロキシを設定する≒ 指定箇所に `https://(your-proxy-address-or-domain):(port)` という値をセットする
- 会社ではプロキシがデフォで動いてて「このプロキシ通さないとインターネットに出れないよ」となっていることが多い
- そしてツール設定にはデフォでプロキシが指定されていないことが多い(のでインターネットに出れず通信エラーがでがち)

## CA証明書とは
※以下証明書と略します

- ウェブサーバーに安全にアクセスするためになんか必要なもの
- 証明書 ≒ 「このウェブサーバーは安全ですよ」と第三者によって保証された URL のリスト
    - :warning: このへんの説明は超ざっくりしていますのであしからず
- 証明書は .pem .crt といったファイルとして存在
- 今どきのブラウザや通信処理は、アクセス先 URL が（自身が持つ証明書内に見当たらなければ） **こいつ信用できないぜ？** とみなしてアクセスをやめる
- Q: ブラウザで普通にウェブサイトとか読めるのはなぜ？
    - Ans: ブラウザに証明書が組み込まれているから
- Q: git, pip, AWS CLI その他ツールで通信できないのはなぜ？
    - Ans: （たぶん）証明書が上手く読み込まれてないから
- 証明書を設定する≒ 指定箇所に **証明書ファイルのフルパス** をセットする

# 導通までに必要なこと
- a) 必要な設定値とファイルを入手する
  - プロキシの URL
  - 証明書ファイル
- b) 自分が使うツールの、適切な設定箇所に a) を設定する

# a) 必要な設定値とファイルを入手する

## プロキシ
会社では「このプロキシを使え」という決まりや指示があると思うので、適宜確認すること。

## 証明書
ややこしいが必要な証明書は二種類に分かれる。

- a) インターネット上の「安全なウェブサーバー」を保証した証明書
- b) イントラネット内の「安全なウェブサーバー」を保証した証明書

インターネット上の何らかのサービスと繋ぐ時は a) が必要。たとえば GitHub や Qiita や Slack などは全部 a) が必要。

社内サーバーに繋ぐ時は b) が必要。

## 証明書 > インターネット上
a) は各種ツールに大体デフォで同梱されており（ブラウザしかり Git しかり）、**明示的に設定値として設定する機会はあまりないはず**。もしある場合は、以下の手段で入手する。

- 同梱された証明書ファイルから
    - 例: Git for Windows の crt: `C:\Program Files\Git\mingw64\ssl\certs\ca-bundle.crt`
- curl の公式サイトから
    - [curl - Extract CA Certs from Mozilla](https://curl.haxx.se/docs/caextract.html) ← 配布もされている
    - もっと言うと http://curl.haxx.se/ca/cacert.pem ← これとか

## 証明書 > イントラネット内
社内で稼働しているサーバーについては、第三者による証明書証明が無いのでデフォではアクセスできないことがある。

どうするかというと、（社内サーバーの）運用側が「この証明書使ってください」ってのを用意して、それを利用者に使ってもらう（設定してもらう）ことで対処する。こういう証明書は自己署名証明書（オレオレ証明書）と呼ばれる。

名前はさておき、とにかく社内サーバーアクセス時には専用の証明書が別途必要、ということになる。入手については社内サーバーの運用部門に問い合わせたり運用ページに書いてあったりするはず。

# b) 自分が使うツールの適切な設定箇所に設定する
プロキシと証明書を手に入れたら、あとはツールに設定するだけ。

## ツールと設定箇所の対応
ここではツールの例として Git、AWS CLI、Python の requests ライブラリの三つを取り上げる。

最初にまとめを書くと、こうなる。

| ツール | プロキシ | 証明書 |
| -------------- | ---------------------- | ---------------------- |
| Git | `.gitconfig` の `http.proxy`| `.gitconfig` の `sslCAInfo` |
| AWS CLI | 環境変数 `HTTP(S)_PROXY` | 環境変数 `AWS_CA_BUNDLE` |
| AWS CLI | 環境変数 `HTTP(S)_PROXY` | `.aws/config` の `ca_bundle` |
| Python requests | 環境変数 `HTTP(S)_PROXY` | `verify=True` なら環境変数 `REQUESTS_CA_BUNDLE` |
| Python requests | 環境変数 `HTTP(S)_PROXY` | `verify=(証明書ファイルのパス)` |

たとえば Git の場合は **とにかく gitconfig という設定ファイル内に設定する** ことになる。環境変数 `HTTP(S)_PROXY` に設定しても意味はない。

逆に AWS CLI の場合は、プロキシは環境変数 `HTTP(S)_PROXY` から読まれるので、.gitconfig や .aws/config を見てウンウン唸っても意味はない。

このように「このツールはここから読まれるのでここに設定する」というのをしっかりと把握した上で設定する（とハマりづらい）。

## 環境変数 `HTTP(S)_PROXY` について
ここでは `HTTP(S)_PROXY` と端折って書いているが、実際は `HTTP_PROXY` と `HTTPS_PROXY` がある。

Windows での設定例:

```
set HTTP_PROXY=http://(your-proxy-address-or-domain):(port)
set HTTPS_PROXY=https://(your-proxy-address-or-domain):(port)
```

ここで「設定が二つあってややこしい」と思われがちだが、**とりあえず二つとも設定しておくのが無難** だろう。……というのは手抜きだが、両者の使い分けは筆者もよくわかっていない（ので教えてほしいです :bow:）。

## 証明書ファイルのパスについて
証明書ファイルのパスの書き方にも罠がある。上手く行かない場合は、以下観点でチェックしてみると良い。

- フルパスで書くこと
    - :x: ca_bundle.pem
    - :o: D:\data\cert\ca_bundle.pem
- 指定したパスが正しいか（ちゃんとファイルが存在しているか）確認すること
- 区切り文字を変えてみること
    - `D:\data\cert\ca_bundle.pem`
    - `D:/data/cert/ca_bundle.pem`
    - `D/data/cert/ca_bundle.pem`
    - `D:\\data\\cert\\ca_bundle.pem`
    - どれで動作し、どれで動作しないのかはツール次第で異なる
    - とはいえ 2019/12 現在なら Win/Lin 両対応で（たぶん）どの書き方でも動くと思う？

## 証明書ファイルの変換について
たとえば ca_bundle.crt だとダメで ca_bundle.pem が必要……みたいなことがある。

これを行うには変換コマンドを使う

以下は Git for Windows 同梱の openssl コマンドを使う例

```
$ openssl x509 -in ca_bundle.crt -out ca_bundle.pem -outform PEM
```

## Git の .gitconfig について
- http.proxy
- **https.proxy という設定は存在しない**

```
[http]
	proxy = https://(your-proxy-address-or-domain):(port)
	sslCAInfo = D:\data\cert\ca_bundle.pem
```

また特定のドメイン毎に設定を使い分けることもできる。

```
[http]
	proxy = https://(your-proxy-address-or-domain):(port)
	sslCAInfo = D:\data\cert\ca_bundle.pem
[http "https://(intranet-webserver-1-domain)"]
	sslCAInfo = D:\data\cert\cert-from-webserver-1.pem
```