2020年8月12日水曜日

HTTPヘッダーによる認証の制御について

 Autonomous DatabaseのAPEXを使う際に、ホワイトリストを設定できないのか、という話がありました。現時点ではそのような機能は提供されていないのですが、HTTPヘッダーを参照することで、限定的には実装することができます。なぜ限定的なのか、というとHTTPヘッダーを誤魔化すのは、それほど難しい作業ではないからです。

とはいえ、何もしないよりはよいかもしれません。古くからのオラクル・ユーザーであれば、OWA_UTILパッケージを知っている人が多いのですが、Oracle APEXでもそれが使えるということはあまり知られていないようです。ですので、OWA_UTILパッケージのプロシージャなどを使って、HTTPヘッダーを使った認証を組み込んでみます。

OWA_UTILパッケージのマニュアルの記載はこちらになります。

まず、Oracle APEXのアプリケーションで参照できるHTTPヘッダーを確認します。

空のページを作成して、それに新規にリージョンを追加します。リージョンのタイプPL/SQL動的コンテンツとします。

ソースPL/SQLコードとして以下を指定します。

owa_util.print_cgi_env;
このリージョンを含むページを開くと、Oracle APEXのアプリケーションで扱うことができるHTTPヘッダーが出力されます。


エンドポイントの特定に使用できる情報は、X-Real-IP、X-Forwarded-ForといったHTTPヘッダーやREMOTE_ADDRのどれかになるでしょう。これらの情報はOracle APEXに限った話ではないので、それぞれどういった情報であるのかといった説明は割愛します。今回はX-Real-IPを認証の制御に使用することにします。

次に、認証スキームにコードを追加します。共有コンポーネントから認証スキームを開きます。


カレントの認証スキームを開きます。くれぐれも本番稼働中のアプリケーションで作業をしないよう気を付けましょう。


PL/SQLコードとして、認証に使用するコードを追加します。そして、そこで定義したファンクション名をセッション無効ファンクション名の確認として指定します。


ファンクションの記述は以下になります。
function check_x_real_ip_header return boolean
is
l_client_ip_addr varchar2(200);
l_c integer;
begin
    l_client_ip_addr := owa_util.get_cgi_env('X-Real-IP');
    apex_debug.info('X-Real-IP is ' || l_client_ip_addr);
    select count(*) into l_c from res_client_ip where ip_address = l_client_ip_addr;
    if l_c > 0 then
        return true;
    end if;
    return false;
end check_x_real_ip_header;
あらかじめ、以下のDDLにて表RES_CLIENT_IPが作成されていて、列IP_ADDRESSにアクセスを許可するIPアドレスが記載されていることを前提としています。
CREATE TABLE "RES_CLIENT_IP" 
   (	"IP_ADDRESS" VARCHAR2(16), 
	 PRIMARY KEY ("IP_ADDRESS")
  USING INDEX  ENABLE
   ) ;
ファンクションがfalseを返す、つまりセッションが無効であると判断すると、移動先として設定されたページに遷移します。X-Real-IPとして渡されるIPアドレスが、あらかじめ表RES_CLIENT_IPに登録されていないと、ログイン画面から先に進めません。

実用的にするには、IPアドレスだけではなくワイルド・カードによる指定や、アクセスの許可、拒否にしたがってログを取得するなど、色々と考慮する必要はあります。今までの説明を元に、必要な機能を追加してゆくことになるかと思います。