FlaskをSSLに対応させる
ウェブアプリケーションをSSLに対応させる際はnginxなどでリバースプロキシを作ることが一般的ですが、テスト環境でサクッとapiをssl化したいときはFlaskの機能を使ってnginxを通さずにSSL化することができます。
このトピックに関して色々な記事が出回っていますが、使えなくなっているものが大量にあるので2024年8月に使えるコードを共有したいと思います。シンプルすぎてびっくりしました。
index.htmlを表示させるだけのコードは
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=443)
これで実行できますが、これに
CERTFILE = "C://ssl/certificate/location"
KEYFILE = "C://ssl/key/location"
context = (CERTFILE, KEYFILE)
....中略....
app.run(host='0.0.0.0', port=443, ssl_context=context)
これを追加するだけです。完成版のコードは
from flask import Flask, render_template
app = Flask(__name__)
CERTFILE = "C://ssl/certificate/location"
KEYFILE = "C://ssl/key/location"
context = (CERTFILE, KEYFILE)
@app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=443, ssl_context=context)
こうなります。SSL証明書はLet's Encrypt等でもらったpemファイルをそのまま使えます。
余談(もう使えなくなったコードたち)
ここから先は古い情報なので、SSL化する方法だけ知りたい方は読まなくても大丈夫です。
Flaskはwerkzeugというライブラリをもとに作られています。従ってwerkzeugに変更が入ったらFlaskにも変更が入るということです。
数年前の記事を見てみると、大きく二つの方法でSSL化していたようです。
- OpenSSLのライブラリをimportして使う(pyOpenSSL)
- python標準のsslのライブラリを使う
Google検索してみると
import ssl
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain('fullchain.pem', 'privkey.pem')
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file('key.key')
context.use_certificate_file('cert.crt')
app.run(host='0.0.0.0', port=80, ssl_context=context, threaded=True, debug=True)
こんな感じのコードがいっぱい出てきますが、load_cert_chain
がうまく認識されなかったり(load_verify_location
もだめでした)、ssl.PROTOCOL_TLSv1_2
はもうサポートしてないよ!って言われたりしてどれもうまくいきませんでした。なんだかんだStackoverflowの記事を漁っていたら前述の方法でSSL化できたので、ぜひ試してみてください。