2021年5月21日金曜日

認可スキームのスキーム・タイプ - ロールまたはグループ内にある、について

 認可スキームのスキーム・タイプとしてロールまたはグループ内にあるを選んだときの、タイプ名前は具体的に何を意味しているのか確認しました。

タイプとして選択できるのは、アプリケーション・ロールワークスペース・グループおよびカスタムです。それぞれの選択したタイプのロールなりグループを名前に指定します。


アプリケーション・ロール


アプリケーション・ロール共有コンポーネントアプリケーション・アクセス制御から作成します。

ロールの作成(ロールの追加より実施)およびユーザーへのロールの割り当て(ユーザー・ロール割当ての追加より実施)を行うことができます。

タイプとしてアプリケーション・ロールを選択した際に指定する名前は、この画面から参照できるロールです。また、認可に成功するユーザーは、ここで名前として指定されているロールが割り当たっているユーザーになります。


ワークスペース・グループ


ワークスペース・グループ管理メニューのユーザーとグループの管理から編集します。

最初はユーザーの一覧が表示されます。グループ・タブを選択し、グループの一覧に切り替えます。


作成済みのグループが一覧されます。グループの作成は、ユーザー・グループの作成から実施します。


グループに割当てられているユーザーは、グループ割当てのタブから一覧されます。


ユーザーへのグループの割当ては、ユーザーの編集画面のグループ割当てから行います。


タイプとしてワークスペース・グループを選択した際に指定する名前は、この画面から参照できるグループです。また、認可に成功するユーザーは、このグループが割り当たっているユーザーになります。

グループにはグループ権限付与として、他のグループを含めることができます。


しかし認可に成功するのは、名前として指定したグループに直接割り当たっているユーザーのみでした。これはファンクションAPEX_UTIL.CURRENT_USER_IN_GROUPの結果でも同様でした。グループ権限付与されたグループへのユーザー割当ては考慮されないようです。

カスタム


カスタムはプロシージャーAPEX_AUTHORIZATION.ENABLE_DYNAMIC_GROUPSを呼び出すことにより有効にされたグループです。認証スキームApplication Expressアカウントのときは、ワークスペース・グループも対象になります。

プロシージャーAPEX_AUTHORIZATION.ENABLE_DYNAMIC_GROUPSを呼び出すことにより、すでにセッションで認証済みのユーザーに、引数として与えた名前のグループが割り当てられます。

このプロシージャは通常、認証スキーム認証後のプロシージャ名に登録したプロシージャの中から呼び出し、外部のシステムにて定義されたグループ名をOracle APEXのグループ名として認識させるために使用します。実体のあるグループではなく、名前だけのグループがユーザーに割り当てられます。



ロールまたはグループ・スキームのソース


アプリケーションが認識するロールまたはグループを選択するプロパティとして、アプリケーション定義セキュリティ認可のセクションにロールまたはグループ・スキームのソースという属性があります。


選択肢は3つあります。

アクセス制御ユーザー・ロールの割当てを選択すると、アプリケーション・ロールロールまたはグループとして有効になります。そのため、認可スキームスキーム・タイプとしてロールまたはグループ内にあるが選択されていて、タイプアプリケーション・ロールとなっているものだけが認可に成功します。それ以外はソースとして扱われていないので認可に成功することはありません。

認証スキームを選択すると、有効になっている認証スキームに依存してグループが認識されるものと思われます。実際には認証スキームが標準のApplication Expressアカウントを選択している場合のみ選択する意味があり、それ以外の認証スキームではカスタムを選択することになります。認証スキームがAppllication Expressアカウントの場合は、ワークスペース・グループおよびAPEX_AUTHORIZATION.ENABLE_DYNAMIC_GROUPSにて設定した動的グループが有効になります。それ以外はソースとして扱われていないので認可に成功することはありません。

カスタム・コードを選択すると、APEX_AUTHORIZATION.ENABLE_DYNAMIC_GROUPSにて設定した動的グループのみが有効になります。それ以外はソースとして扱われていないので認可に成功することはありません。

確認に使うアプリケーションの作成


今までの説明した内容を、アプリケーションを作成して確認します。

最初に確認に使用するワークスペース・ユーザーとグループを作成します。

ワークスペース・グループとしてAZADMINを作成します。


ユーザーとしてAZTESTを作成し、グループAZADMINを割当てます。


ユーザーAZNONEを作成します。グループは割り当てません。


確認に使用するユーザーの準備は以上です。

検証に使用する空のアプリケーションを作成します。名前ロールとグループの確認とし、機能アクセス制御をチェックします。アプリケーションの作成を実行します。


作成したアプリケーションを実行し、認可に関する初期設定を行います。サインインはアプリケーションを作成した開発者ユーザーで行います。


アプリケーションにサインインした後、管理ページのアクセス制御を開きます。


アクセス制御の構成として、認証されたユーザーは、誰でもこのアプリケーションにアクセスできますONに変更します。変更の適用をクリックします。


アクセス制御の表示が「アプリケーションのアクセス制御リストに定義されたユーザーのみが、このアプリケーションにアクセスできます」から「すべての認証済ユーザーが、このアプリケーションにアクセスできます」に変更されます。


この設定は共有コンポーネントアプリケーション設定からも実施できます。


先程、アプリケーションの管理画面より設定を変更しているため、アプリケーション設定ACCESS_CONTROL_SCOPEの値がALL_USERSになっています。


ACL_ONLYになっていると、ユーザーは少なくてもリーダー権限は持っていないとアプリケーションにアクセスできません。権限なしでのアクセスを許可する場合は、ALL_USERSに変更します。


アプリケーションの機能としてアクセス制御を組み込んでいない場合は、アプリケーション設定のACCESS_CONTROL_SCOPE自体存在しません。

標準ではアプリケーション・ロールとして管理者、コントリビュータ、リーダが作成されます。今回はAZADMINというロールを追加します。ロールの追加は共有コンポーネントアプリケーション・アクセス制御から実施します。


ロールの追加を実行します。


ロール名前AZADMINとします。名前には日本語を使用できますが、静的識別子は英数字のみです。ロールの作成をクリックします。


ロールが作成されたら、ユーザー・ロール割当ての追加を実行します。


ユーザー名AZTESTを入力し、アプリケーション・ロールとしてAZADMINにチェックを入れます。割当ての作成をクリックします。


ユーザー・ロール割当てが追加されます。


アプリケーション・ユーザーについて、と記載されている内容がわかりにくいです。英語の説明は以下です。

About Application Users
Application users are not exported as part of your application. When you deploy your application you will need to manually manage your user to role assignments. Roles are exported as part of an application export and imported with application imports.

私なりに翻訳した内容が以下です。

アプリケーションをSQLファイルやZIPファイルとしてエクスポートしたとき、そのエクスポートにはユーザーは含まれません。 アプリケーションに定義されたロールはエクスポートに含まれ、アプリケーションとともにインポートされます。ユーザーへのアプリケーション・ロールの割当てはアプリケーションをデプロイしたのちマニュアルで実施する必要があります。

ユーザー・ロール割当ての追加は、アプリケーションの管理ページからも実施できます。追加ボタンまたはユーザーから行います。

ユーザーを開くと、先程アプリケーション・ビルダーで追加したユーザーAZTESTとロールAZADMINの割当てを確認することができます。


新たに割当てを追加するには、ユーザーの追加をクリックします。今回はこれ以上の割当ては確認しないため、ユーザーの追加は行いません。

確認に使用する認可スキームを作成します。認可スキームは共有コンポーネント認可スキームから作成します。


作成済みの認可スキームの一覧が表示されます。作成をクリックします。


条件の異なる認可スキームを4つ作成します。

最初にアプリケーション・ロールによる認可スキームを作成します。

認可スキームの作成最初からを選択し、へ進みます。


認可スキームとして名前AZADMIN - Roleを入力します。スキーム・タイプロールまたはグループ内にあるタイプアプリケーション・ロールです。こちらの名前としてAZADMINを選択します。スキームの違反時に表示されるエラー・メッセージの指定として許可されていません。を入力します。認可スキームの検証セッションごとに1回を選択します。以上を入力し、認可スキームの作成を実行します。


同様に名前AZADMIN - Groupとし、タイプワークスペース・グループである認可スキームを作成します。その他の設定はAZADMIN - Roleと同じです。


名前AZADMIN - Customとし、タイプカスタムの認証スキームを作成します。


最後にファンクションAPEX_UTIL.CURRENT_USER_IN_GROUPを呼び出すことで、グループの所属を確認する認可スキームを作成します。

名前AZADMIN - Codeとし、スキーム・タイプブールを戻すPL/SQLファンクションを選択します。PL/SQLファンクション本体として、以下の1行を設定します。

return apex_util.current_user_in_group('AZADMIN');


4つの認可スキームが作成されました。


動的グループの割当てを行うコードを追加します。共有コンポーネント認証スキームを開きます。


認証スキームの一覧より、カレントになっているApplication Expressアカウントを開きます。


ソースPL/SQLコードに以下のコードを入力します。

procedure assign_dynmiac_groups
is
l_group_names apex_t_varchar2 := apex_t_varchar2('AZADMIN');
begin
if :APP_USER != 'AZTEST' then
apex_authorization.enable_dynamic_groups(l_group_names);
end if;
end;

プロシージャassign_dynamc_groupsは、認証されたユーザーがAZTESTでなければ、グループAZADMINを動的に割り当てます。ワークスペース・グループとしてAZADMINが作成済みですが、ワークスペース・グループの存在は必須ではありません。例えばグループ名として、ワークスペース・グループとして存在しない"MYGROUP"を与えても、ユーザーがグループMYGROUPに所属していると認識されます。グループ名は配列が引数なので、一度に複数のグループを指定できます。

ログイン・プロセス認証後のプロシージャ名としてassign_dynamic_groupsを入力します。変更の適用を実行します。


ホーム・ページに認可スキームの評価結果を一覧するクラシック・レポートを作成します。ソースSQL問合せには以下のSQL問合せを使います。

with
function is_auth(scheme in varchar2) return varchar2 is
begin
if apex_authorization.is_authorized(scheme) then
return 'YES';
else
return 'NO';
end if;
end;
select
authorization_scheme_name scheme_name,
is_auth(authorization_scheme_name) "Authorized?",
scheme_type,
scheme_type_code,
attribute_02
from
(
select
authorization_scheme_name,
scheme_type,
scheme_type_code,
attribute_02
from apex_application_authorization
where application_id = :APP_ID
)

ページ・デザイナでホーム・ページを開き、リージョンの作成を行います。名前認可スキームの評価結果とします。タイプクラシック・レポートを選択します。ソースタイプSQL問合せを選択し、SQL問合せとして上記のコードを記述します。


アプリケーションを実行するとORA-32034: WITH句の使用はサポートされていません。とエラーが発生します。クラシック・レポートでWITH句を含むSQL問合せを実行するには、オプティマイザ・ヒントとしてAPEXの擬似ヒントWITH_PLSQLを指定する必要があります。


オプティマイザ・ヒントにWITH_PLSQLを与えたのち、アプリケーションを実行します。今度はORA-14551: 問合せの中でDML操作を実行することはできません。が発生します。


認可スキームの設定の認可スキームの検証セッションごとに1回に設定されています。このため、SQL問合せから呼び出されるファンクションAPEX_AUTHORIZATION.IS_AUTHORIZEDの初回呼び出し時に、結果をキャッシュするためのデータベースへの書き込み処理が発生します。そのためORA-14551が発生します。

認可スキームの検証常時(キャッシュなし)に変更しても良いのですが、今回はあらかじめ評価結果がキャッシュされるよう、ページのロード時にPL/SQLの以下のコードを実行します。

declare
b boolean;
begin
for c in
(
select
authorization_scheme_name
from apex_application_authorization
where application_id = :APP_ID
)
loop
b := apex_authorization.is_authorized(c.authorization_scheme_name);
end loop;
end;

ホーム・ページのヘッダーの前プロセスの作成を行います。名前認可をキャッシュタイプコードの実行とします。ソースPL/SQLコードとして、上記のコードを記述します。


以上でアプリケーションの作成は完了です。アプリケーションを実行すると、以下のようなレポートが表示されます。


認証スキームの評価の確認


アプリケーション定義セキュリティ認可ロールまたはグループ・スキームのソースを、アクセス制御ユーザーのロールの割当てに設定します。


アプリケーション・ロールAZADMINを持つユーザーAZTESTにてサインインした結果です。

アプリケーション・ロールが有効になっているためAZADMIN - Roleが成功しています。また、ユーザーAZTESTはワークスペース・グループAZADMINが割り当てられているためAZADMIN - Codeも成功しています。ワークスペース・グループは有効になっていないため、AZADMIN - GroupとAZADMIN - Customは失敗しています。


ユーザーAZNONEには、動的グループとしてAZADMINが割り当たっています。しかし、グループは有効になっていないため、すべての認証スキームの評価が失敗します。


ロールまたはグループ・スキームのソース認証スキームに変更し、同様の確認を行います。


ユーザーAZTESTにはワークスペース・グループAZADMINが割り当たっているため、AZADMIN - Roleを除いた認証スキームが成功します。


ユーザーAZNONEは動的にグループAZADMINが割り当たり、ワークスペース・グループは割り当てっていないため、AZADMIN - GroupとAZADMIN - Customが成功し、AZADMIN - Codeは失敗します。


ロールまたはグループ・スキームのソースカスタム・コードに変更し、同様の確認を行います。


ユーザーAZTESTでは、AZADMIN - Codeだけが成功します。ワークスペース・グループは有効化されていず、動的にグループも割り当たっていないためです。


ユーザーAZNONEではグループAZADMINが動的に割り当たっているため、AZADMIN - GroupとAZADMIN - Customが成功しています。


以上で確認作業が終了です。

今回の確認作業で使用したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/role-and-group-source.sql

ワークスペース・ユーザー、グループおよびアプリケーション・ロールとユーザーの割当てはエクスポートされたアプリケーションには含まれないため、手動で登録する必要があります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。