Golang の http コンポーネントを利用して証明書の有効期限日を取得する #golang


以前の記事（[Golang と Line Notify を利用して API の証明書期限切れチェック](https://qiita.com/ynozue/items/d00a76e16d5a3d5a784c)）を作りましたが TLS 情報も取得して証明書の有効期限も通知できるようにします。

# 実際どの様な値を取得できるのかを確認
curl を利用して証明書の有効期限切れ情報がどのようなの形式で取得できるのかを確認する。

```sh
$ curl -v https://www.google.co.jp > /dev/null

* Rebuilt URL to: https://www.google.co.jp/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 2404:6800:400a:809::2003...
* TCP_NODELAY set
* Connected to www.google.co.jp (2404:6800:400a:809::2003) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [96 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [3915 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [148 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [70 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=*.google.com
*  start date: Sep 13 17:09:00 2017 GMT
*  expire date: Dec  6 17:09:00 2017 GMT <= 証明書の有効期限切日
*  subjectAltName: host "www.google.co.jp" matched cert's "*.google.co.jp"
*  issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f8fcf80a800)
> GET / HTTP/2
> Host: www.google.co.jp
> User-Agent: curl/7.54.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200 
< date: Tue, 03 Oct 2017 15:48:54 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=Shift_JIS
< p3p: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
< server: gws
< x-xss-protection: 1; mode=block
< x-frame-options: SAMEORIGIN
< set-cookie: NID=113=fzc3UUxCLsPfVZUG5QzerFhtGWI0kvPIoc26ECb3jWjzFiX1FJnSMT9DX0VNGhBNH6KYDJO3EuZCWY2gCJq9WOn25JGsWiubljuxRQu54IqDzeRREv8_SBvq6uZS4sNp; expires=Wed, 04-Apr-2018 15:48:54 GMT; path=/; domain=.google.co.jp; HttpOnly
< alt-svc: quic=":443"; ma=2592000; v="39,38,37,35"
< accept-ranges: none
< vary: Accept-Encoding
< 
{ [1170 bytes data]
100 11792    0 11792    0     0  28236      0 --:--:-- --:--:-- --:--:-- 28278
* Connection #0 to host www.google.co.jp left intact
```

# Golang を利用して証明書の有効期限日の情報を取得する

```go
resp, err := http.Get("https://google.co.jp")

expireUTCTime := resp.TLS.PeerCertificates[0].NotAfter
expireJSTTime := expireUTCTime.In(time.FixedZone("Asia/Tokyo", 9 * 60 * 60))
expireDate = expireJSTTime.Format("2006/01/02 15:04")
```
expireDate には「2017/12/07 02:09」の情報が格納される。

# 実際に通知のアプリに組み込んだイメージ
![IMG_0864.jpg](https://qiita-image-store.s3.amazonaws.com/0/203864/c101ac20-46ee-9651-5b14-b8fc1ddec7fa.jpeg "IMG_0864.jpg")



# Appendix
* [ソースコード](https://github.com/ynozue/apichecker/tree/expire)