Docker

DockerでStreamlit+Nginx+OAuth2 Proxyを動かす

前回はStreamlitとNginxを連携させる構成を作りました。
今回は、このシステムにOAuth2認証を付け加えたいと思います。
OAuth2認証はGoogleのサービスを利用します。

環境

Windows 10 Pro
Docker Desktop 4.1.1
Visual Studio Code 1.62.2 + Docker extension

Googleの設定

Google Could Platformにログインし、新しいプロジェクトを作成します。

プロジェクト名は任意の名前を入れます。ここではStreamlitProxyとします。
作成をクリックします。

プロジェクトが作成されたら、そのプロジェクトを選択し、「APIとサービス」からOAuth同意画面を選択します。

OAuth同意画面では、Google Workspaceユーザーでない場合には外部しか選択できないので、外部を選択して、作成をクリックします。

アプリ名、その他必要情報を入力し、保存して次へをクリックします。

スコープ、テストユーザーは何も入力せずに、保存して次へをクリックします。

次に認証情報ページに移動します。

認証情報を作成からOAuthクライアントIDを選択します。

アプリケーションの種類はウエブアプリケーションを選択し、名前はデフォルトのままで大丈夫です。
URIにはhttp://localhost/oauth2/callbackと入力し、作成ボタンをクリックします。

するとクライアントIDとクライアントシークレットが表示されます。
後に使うので、これをメモしておきます(実際には何度でも見れるので、メモの必要はありません)。

以上でGoogle側の設定は完了です。

OAuth2 Proxyの設定

次に、認証を行うプログラムの設定をします。認証にはOAuth2 Proxyというプログラムを利用します。
以下の設定を前回作成したdocker-compose.ymlファイルに追加します。

  authproxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:latest
    networks:
      shared-nw:
    ports:
      - "4180:4180"
    command: --cookie-secure=false --upstream="http://0.0.0.0:80" --http-address="0.0.0.0:4180" --redirect-url="http://localhost/oauth2/callback" --email-domain="*"
    environment:
      OAUTH2_PROXY_COOKIE_SECRET: <クッキーシークレットをここにコピー>
      OAUTH2_PROXY_CLIENT_ID: <クライアントIDをここにコピー>
      OAUTH2_PROXY_CLIENT_SECRET: <クライアントシークレットをここにコピー>
      OAUTH2_PROXY_COOKIE_EXPIRE: 30m

クライアントIDとクライアントシークレットはGoogleで取得したものをそのままコピーします。
クッキーシークレットはこちらのサイトに書かれている方法のどれかを使って作ります。
ここでは、Powershellを使ってやってみます。

以下のコードをVSCodeのTeminalで実行します。

Add-Type -AssemblyName System.Web
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes([System.Web.Security.Membership]::GeneratePassword(32,4))).Replace("+","-").Replace("/","_")

生成された文字列をコピーして、docker-compose.ymlの該当箇所に貼り付けます。

その他の設定項目としては、OAUTH2_PROXY_COOKIE_EXPIREはセッションが切れる時間です。
ここでは30mということで、30分で再認証が必要になる設定にしてあります。


docker-compose.ymlファイルは全体で以下のようになります。

version: '3.8'

services:
  streamlit:
    build:
      context: ./Streamlit
    networks:
      shared-nw:
    ports:
      - 8501:8501
    command: hello
  nginx:
    build:
      context: ./Nginx
    ports:
      - 80:80
    networks:
      shared-nw:
  authproxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:latest
    networks:
      shared-nw:
    ports:
      - "4180:4180"
    command: --cookie-secure=false --upstream="http://0.0.0.0:80" --http-address="0.0.0.0:4180" --redirect-url="http://localhost/oauth2/callback" --email-domain="*"
    environment:
      OAUTH2_PROXY_COOKIE_SECRET: bl1mWUtRUl9CZjE4cFVjOjJrWTokSUNlazgkcCElSno=
      OAUTH2_PROXY_CLIENT_ID: <クライアントIDをここにコピー>
      OAUTH2_PROXY_CLIENT_SECRET: <クライアントシークレットをここにコピー>
      OAUTH2_PROXY_COOKIE_EXPIRE: 30m
networks:
  shared-nw:
    driver: bridge

Nginxの設定

最後にNginxの設定です。
OAuth2 Proxyへの転送設定を追加して、以下のようになります。

events {
    worker_connections  16;
}
http {
    server {
        listen 80;
        server_name localhost;

        location /oauth2/ {
            proxy_pass       http://authproxy:4180;
            proxy_set_header Host                    $host;
            proxy_set_header X-Real-IP               $remote_addr;
            proxy_set_header X-Scheme                $scheme;
            proxy_set_header X-Auth-Request-Redirect $request_uri;
        }

        location = /oauth2/auth {
            proxy_pass       http://authproxy:4180;
            proxy_set_header Host             $host;
            proxy_set_header X-Real-IP        $remote_addr;
            proxy_set_header X-Scheme         $scheme;
            proxy_set_header Content-Length   "";
            proxy_pass_request_body           off;
        }

        location / {
            auth_request /oauth2/auth;
            error_page 401 = /oauth2/sign_in;
            proxy_pass http://streamlit:8501/;
        }
        location ^~ /static {
            proxy_pass http://streamlit:8501/static/;
        }
        location ^~ /healthz {
            proxy_pass http://streamlit:8501/healthz;
        }
        location ^~ /vendor {
            proxy_pass http://streamlit:8501/vendor;
        }
        location /stream {
            proxy_pass http://streamlit:8501/stream;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }        
    }
}

コンテナを起動

では、コンテナを起動します。
docker-compose.ymlファイルを選択、右クリックし、Compose Upを選択します。

コンテナが起動したら、ブラウザでhttp://localhostにアクセスします。
OAuth2 Proxyの画面が出てくるので、Sign in with Googleボタンをクリックします。

Googleのサイトに飛びますので、アカウントを選択します。

Streamlitのデモ画面が見れれば完成です。