ローカルで動作確認するときHTTPSでないと動かないAPIがあるので。

ブツ

動機

主要なAPIが、HTTPSであることを求めており、実質HTTPSサーバでないと動作確認すらできません。

これではDOMでHTMLを作るくらいしかできません。困ります。

HTTPなら簡単

私は今まで、HTTPでやっていました。以下でHTTPローカルサーバを立てられます。

PORT=8000
URL="http://0.0.0.0:$PORT/"
chromium-browser $URL
python3 -m http.server $PORT

HTTPであっても、それなりに動作確認する環境としての価値はあります。ローカルのindex.htmlファイルを直接参照したfile://プロトコルだと実行できないものもあるためです。

ですが、先述のAPIは動作しません。

HTTPSが必要なAPIを動作させるときはGitHub Pagesにアップして動作確認していました。が、デプロイに時間がかかるし、リクエスト上限にひっかかって確認できなくなったりして開発が滞ります。いいかげん、環境を整えねばと思い、重い腰を上げました。

今までの試み

らいうさんの記事mpurseを使ったアプリ開発のための環境構築で、HTTPSサーバをローカルで立てる方法が紹介されていました。このうちオレオレ証明書の方法をやってみたのですが、うまくできませんでした。

おそらく証明書を作ってブラウザに読み込ませるだけでは足りなかったのでしょう。でも、そこから先どうしたらいいかわからなかったので、そこで断念していました。

vueを導入すればイケたかもしれませんが、余計なものはできるだけ省きたかったのです。その環境構築のための学習からはじめねばならず、長い間コーディングできない状態になりそうだったので。

基礎も知らないうちからフレームワークだのライブラリだのを導入したら、わけがわからなくなるんです。経験上。はたしていつになったらそこまで行けることやら。

また、ラズパイがシステムクラッシュを半年に一回ペースで起こしやがるので、できるだけ開発環境はシンプルにしたかった事情もありました。

どうやるか

やっと本題。ググったところ、PythonでHTTPSサーバを動作させる方法があるようです。

以下のようなファイル構成になります。

  • project-root/
    • index.html
    • localhost.pem
    • run_server.py

index.html

<h1>Hello HTTPS !!</h1>
<input id="address" value="" placeholder="モナコインのアドレス">
<script>
window.addEventListener('DOMContentLoaded', async(event) => {
  document.getElementById('address').value = await window.mpurse.getAddress()
});
</script>

自己証明書をつくる

openssl req -x509 -new -days 365 -nodes \
  -keyout localhost.pem \
  -out localhost.pem \
  -subj "/CN=localhost"

localhost.pemファイルが作成されます。これをindex.htmlがあるところに配置します。

ところで、-days 365が不穏な気がします。もしかして365日後に期限切れで使えなくなるのでは? そのときはまた作成する必要があるのかもしれません。

HTTPSサーバを作る

run_server.py

import ssl
from http.server import HTTPServer, SimpleHTTPRequestHandler

PORT = 443
CERTFILE = "./localhost.pem"

Handler = SimpleHTTPRequestHandler

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(CERTFILE)

with HTTPServer(("", PORT), Handler) as httpd:
    print("serving at address", httpd.server_address, "using cert file", CERTFILE)
    httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever()

run_server.pyindex.htmlがある場所に配置します。

HTTPSサーバを起動する

index.htmlがある場所で以下コマンドを叩きます。

URL="https://localhost/"
chromium-browser $URL
sudo python3 run_server.py

するとサーバが起動し、ブラウザがそれを表示します。

以下のように「プライバシーが保護されません」と警告されます。ここで「詳細設定」ボタンをクリックします。

https_0.png

すると証明書がうんたらと説明があります。ここで「localhost にアクセスする(安全ではありません)」をクリックする。

https_1.png

これで表示できました。

https_2.png

APIも動作しています。これでローカルでも動作テストができそうです。

すでに開発をはじめて一ヶ月くらい経っていますが、ようやくローカルでHTTPS環境ができました。

疑問

  • 自己証明書があるのに、なんで警告されるの?
  • 保護されてない通信になってるけどいいの?

ネットワークの知識がなさすぎてヤバイ。

セキュリティの懸念

たぶんこうしてローカルサーバが起動している間は、指定したポートに穴があいている状態なのでしょう。今回でいうと443。このポートは外部からの侵入経路になると思われます。

なのでポート番号を変えたり、テストが終わったらサーバを閉じたりしたほうがいいのでしょう。でも、ポート総当りとかされるのでは?

でもそれは今までHTTPでやっていたときも同じだったはずで。HTTPとHTTPSの違いすら理解できていない。HTTPSのほうがセキュアらしいことしか知らない。知らなかったらセキュリティもクソもない。危ないことをやっていても気づけない。あかん。

所感

こんなに何もわからずにやっちゃって大丈夫なのか。ファイアウォールがどうとかも理解できていないし。やはり今の私にサーバを立てることは無謀すぎる。

とりあえずローカルで動作確認さえできればいいので、今回はこれで良しとします。