GAE/Go環境の deploy 実行時に SSL: CERTIFICATE_VERIFY_FAILED が発生した

先日、開発を行なっている環境に向けて、 `appcfg.py deploy` コマンドを実行したとき、 `SSL: CERTIFICATION_VERIFY_FAILED` が発生しました。
そのときに行なった解決方法がちょっとめんどくさかったので忘れないようにメモ。

## 事象の発生
いつも通り、 `appcfg.py deploy` を用いてデプロイを行なった。
※開発環境の都合により、 `gcloud` コマンドはあえて使っていない。

```bash
appcfg.py -A application-name -V varsion-name update $GOPATH/src/sample/app.yaml
```

その時に、以下のエラーが発生。

```
Traceback (most recent call last):
  File "/usr/local/bin/appcfg.py", line 133, in <module>
    run_file(__file__, globals())
  File "/usr/local/bin/appcfg.py", line 129, in run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 5510, in <module>
    main(sys.argv)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 5501, in main
    result = AppCfgApp(argv).Run()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 2975, in Run
    self.action(self)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 5157, in __call__
    return method()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 3889, in Update
    self._UpdateWithParsedAppYaml(appyaml, self.basepath)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 3942, in _UpdateWithParsedAppYaml
    self.UpdateVersion(rpcserver, basepath, appyaml, APP_YAML_FILENAME)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 3824, in UpdateVersion
    return appversion.DoUpload(paths, openfunc)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 2410, in DoUpload
    self.error_fh)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 497, in GetResourceLimits
    resource_limits.update(_GetRemoteResourceLimits(logging_context))
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 467, in _GetRemoteResourceLimits
    yaml_data = logging_context.Send('/api/appversion/getresourcelimits')
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appcfg.py", line 1719, in Send
    result = self.rpcserver.Send(url, payload=payload, **kwargs)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appengine_rpc_httplib2.py", line 240, in Send
    self._Authenticate(self.http, auth_errors[0] > 0)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/appengine_rpc_httplib2.py", line 465, in _Authenticate
    self.credentials = tools.run_flow(flow, self.storage, self.flags)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/oauth2client/oauth2client/util.py", line 137, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/oauth2client/oauth2client/tools.py", line 225, in run_flow
    credential = flow.step2_exchange(code, http=http)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/oauth2client/oauth2client/util.py", line 137, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/oauth2client/oauth2client/client.py", line 2000, in step2_exchange
    headers=headers)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/httplib2/httplib2/__init__.py", line 1584, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/httplib2/httplib2/__init__.py", line 1332, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/httplib2/httplib2/__init__.py", line 1268, in _conn_request
    conn.connect()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/lib/httplib2/httplib2/__init__.py", line 1037, in connect
    raise SSLHandshakeError(e)
httplib2.SSLHandshakeError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)

```

なんでしっかりGoogleログインのブラウザ画面が立ち上がったのに、認証エラーが起きるのだ？？
ともう少しエラーログを調査してみると、GoogleCloudSDKのversion が古く、 Goのversionが duplicated になっていたことがこの認証エラーの原因だった様子。

## GoogleCloudSDK のversion を最新にする
ならば善は急げで Gcloud コマンドを使って、SDKを最新化。
```
gcloud components update
```

最新化できたかどうかを確認してみる

```
gcloud components list


Your current Cloud SDK version is: 207.0.0
The latest available version is: 207.0.0

┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                  Components                                                 │
├───────────────┬──────────────────────────────────────────────────────┬──────────────────────────┬───────────┤
│     Status    │                         Name                         │            ID            │    Size   │
├───────────────┼──────────────────────────────────────────────────────┼──────────────────────────┼───────────┤
│ Not Installed │ Cloud Bigtable Command Line Tool                     │ cbt                      │   4.9 MiB │
│ Not Installed │ Cloud Bigtable Emulator                              │ bigtable                 │   4.3 MiB │
│ Not Installed │ Cloud Datalab Command Line Tool                      │ datalab                  │   < 1 MiB │
│ Not Installed │ Cloud Datastore Emulator                             │ cloud-datastore-emulator │  18.0 MiB │
│ Not Installed │ Cloud Datastore Emulator (Legacy)                    │ gcd-emulator             │  38.1 MiB │
│ Not Installed │ Cloud Pub/Sub Emulator                               │ pubsub-emulator          │  33.4 MiB │
│ Not Installed │ Emulator Reverse Proxy                               │ emulator-reverse-proxy   │  14.5 MiB │
│ Not Installed │ Google Container Local Builder                       │ container-builder-local  │   4.4 MiB │
│ Not Installed │ Google Container Registry's Docker credential helper │ docker-credential-gcr    │   1.8 MiB │
│ Not Installed │ gcloud Alpha Commands                                │ alpha                    │   < 1 MiB │
│ Not Installed │ gcloud Beta Commands                                 │ beta                     │   < 1 MiB │
│ Not Installed │ gcloud app Java Extensions                           │ app-engine-java          │ 118.6 MiB │
│ Not Installed │ gcloud app PHP Extensions                            │ app-engine-php           │  21.9 MiB │
│ Not Installed │ gcloud app Python Extensions (Extra Libraries)       │ app-engine-python-extras │  28.5 MiB │
│ Not Installed │ kubectl                                              │ kubectl                  │  14.8 MiB │
│ Installed     │ App Engine Go Extensions                             │ app-engine-go            │ 152.8 MiB │
│ Installed     │ BigQuery Command Line Tool                           │ bq                       │   < 1 MiB │
│ Installed     │ Cloud SDK Core Libraries                             │ core                     │   7.7 MiB │
│ Installed     │ Cloud Storage Command Line Tool                      │ gsutil                   │   3.5 MiB │
│ Installed     │ gcloud app Python Extensions                         │ app-engine-python        │   6.1 MiB │
└───────────────┴──────────────────────────────────────────────────────┴──────────────────────────┴───────────┘
```

ちゃんと最新化できたみたいなので、もう一度チャレンジ。

```
httplib2.SSLHandshakeError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)
```

なぜか通らない。
しかも、まだversion が古いぜとか言ってる。

goが古いのか？と思い、version　をチェックして見たが、versionはしっかり更新されていた。

```
go version
```

ならばと、appcfg.py に関係ある、 goapp のバージョンを確認して見る。

```
goapp version
```

gcloud で更新しているものだから、当然上がっているはずなのだが、どういうわけかversionがとてつもなく古い。

## goappの謎の旧version
数回gcloud を用いて繰り返し update を試みたが、一向にgoapp のversion が上がらなかった。
そこで、ふと homebrew のインストールリストを確認して見たところ、
goapp が brew package として存在していた。

brew のpackage を除去し、 Gcloud で install した google_appengine 内部の goapp, appcfg.py を参照することができれば状況は改善するはず。

## 改善方法
色々調査していると、以下のいけてる記事を発見。
[goappコマンドを入れ直した話](https://ema-hiro.hatenablog.com/entry/2018/06/26/025917)

こちらの記事で書かれているものを参考に作業を進めると、旧versionとなっていた goapp の version が無事に最新になった。

この状態で、もう一度チャレンジした結果、無事にデプロイすることができた。

## 要約
1. appcfg.py を用いたdeploy で SSLエラーが発生したら、 goapp の version が最新になっていないので、更新する。
2. gcloud を使って更新されていない場合、 brew のパッケージを確認する。


## 所管
gcp 関連のモジュールは、gcloud にまとまっているので、色々なコマンドは使わない方が後々いいかもしれない。。(主観です)