プライマリ・コンテンツに移動
Oracle® Databaseセキュリティ・ガイド
12c リリース1 (12.1)
B71285-10
目次へ移動
目次
索引へ移動
索引

前
次

5 定義者権限および実行者権限のセキュリティの管理

ユーザー作成プロシージャの実行権限へのアクセス制御で実行者権限および定義者権限を使用すると、セキュリティ上のメリットが得られます。

内容は次のとおりです。

定義者権限および実行者権限について

定義者権限および実行者権限は、ユーザー作成プロシージャまたはプログラム・ユニットの実行に必要な権限へのアクセスを制御するときに使用されます。

定義者権限プロシージャでは、プロシージャが所有者の権限で実行されます。権限は、作成されたスキーマにバインドされます。実行者の権限プロシージャは現行ユーザー(プロシージャを実行するユーザー)の権限で実行されます。

たとえば、ユーザーbixbyが表cust_recordsを変更するために設計されるプロシージャを作成し、このプロシージャのEXECUTE権限をユーザーrlaytonに付与するとします。bixbyが定義者権限でプロシージャを作成した場合、プロシージャはbixbyのスキーマの表cust_recordsを検索します。プロシージャが実行者権限で作成された場合、rlaytonが実行すると、プロシージャはrlaytonのスキーマの表cust_recordsを検索します。

デフォルトでは、すべてのプロシージャは、定義者権限とみなされます。作成時または変更時に、AUTHID CURRENT_USER句を使用してプロシージャを実行者権限プロシージャに指定するか、AUTHID DEFINER句を使用して定義者権限プロシージャに変更できます。

関連項目:

定義者権限および実行者権限プロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください

プロシージャに対する権限が定義者権限に与える影響

定義者と呼ばれるプロシージャの所有者は、プロシージャが参照するオブジェクトに対する必要なオブジェクト権限を所有している必要があります。

プロシージャ所有者が別のユーザーにそのプロシージャを使用する権限を付与すると、(プロシージャで参照されるオブジェクトに対する)プロシージャ所有者の権限が、権限受領者のプロシージャ実行に適用されます。プロシージャの定義者の権限は、ロールを介してではなく、プロシージャ所有者に直接付与する必要があります。これらは、定義者権限と呼ばれます。

所有者以外のプロシージャのユーザーは、実行者と呼ばれます。実行者権限プロシージャの場合は、参照オブジェクトに対する追加の権限が必要ですが、 定義者権限プロシージャの場合は不要です。

定義者権限プロシージャのユーザーに必要なのは、そのプロシージャを実行する権限のみで、そのプロシージャでアクセスする基礎となるオブジェクトに対する権限は不要です。これは、定義者権限プロシージャは、その実行者に関係なく、プロシージャを所有するユーザーのセキュリティ・ドメインの下で動作するためです。プロシージャの所有者は、参照オブジェクトに対する必要なオブジェクト権限をすべて所有している必要があります。定義者権限プロシージャのユーザーに付与する権限は、できるかぎり控えめに付与してください。これによって、データベース・アクセスを厳密に制御できます。

定義者権限プロシージャを使用すると、プライベート・データベース・オブジェクトへのアクセスを制御し、データベースのセキュリティ・レベルを強化できます。定義者権限プロシージャを記述し、ユーザーにEXECUTE権限のみを付与することによって、そのプロシージャを介さない場合には、このユーザーが参照オブジェクトにアクセスできないように規定できます。

実行時には、定義者権限プロシージャの所有者の権限によってそのプロシージャの参照オブジェクトへのアクセスが許可されているかどうかが、プロシージャの実行前にチェックされます。参照オブジェクトに対して必要な権限が、定義者権限プロシージャの所有者から取り消されていると、所有者を含むユーザーは、プロシージャを実行できません。

定義者権限プロシージャを使用する場合の例は次のとおりです。表へのアクセスが制限されていないプロシージャを持つAPIを作成する必要があるとします。ただし、一般ユーザーが表のデータを直接選択し、INSERT文、UPDATE文およびDELETE文を使用して変更しないようにする必要があります。これを実行するには、個別の権限の弱いスキーマで、APIを構成する表およびプロシージャを作成します。デフォルトでは各プロシージャは定義者権限ユニットであるため、作成時にAUTHID DEFINERを指定する必要がありません。次に、EXECUTE権限をこのAPIを使用する必要があるユーザーに付与しますが、データ・アクセスを許可する権限を付与しないでください。この解決策は、API動作の完全な制御およびユーザーが基礎オブジェクトにアクセスする方法を提供します。

独自のスキーマで、定義者権限プロシージャおよびこれらのプロシージャにアクセスするビューを作成することをお薦めします。このスキーマに非常に弱い権限を付与するか、権限を付与しません。これによって、他のユーザーがこれらのプロシージャまたはビューを実行する場合、このスキーマの不要な高い権限にアクセスしません。

注意:

トリガーの処理は、定義者権限プロシージャと同じパターンに従います。ユーザーは、実行権限があるSQL文を実行します。このSQL文の実行結果として、トリガーが起動されます。トリガーされたアクション内の文は、そのトリガーを所有するユーザーのセキュリティ・ドメインで一時的に実行されます。詳細は、『Oracle Database概要』のトリガーの概要に関する項を参照してください。

プロシージャに対する権限が実行者権限に与える影響

実行者権限プロシージャは、すべての実行者権限で実行されます。

実行者の使用可能な任意のロールを介してその実行者に付与された権限は、定義者権限プロシージャによって実行者権限プロシージャが直接または間接的にコールされないかぎり有効です。実行者権限プロシージャのユーザーには、そのプロシージャが実行者のスキーマ内で解決される外部参照を介してアクセスする、オブジェクトに対する権限(直接またはロールを介して付与されたもの)が必要です。実行者が実行者権限プロシージャを実行する場合、このユーザーは、実行者のすべての権限を一時的に保持します。(実行者権限プロシージャのこの側面の詳細は、プロシージャ・コールおよびビュー・アクセスの実行者権限の制御を参照してください。)

実行者には、DML文または動的SQL文に埋め込まれているプログラム参照にアクセスする権限が実行時に必要です。これは、この種のプログラム参照は実質的に実行時に再コンパイルされるためです。

PL/SQLファンクションの直接コールなど、他のすべての外部参照の場合、所有者権限はコンパイル時にチェックされ、実行時にはチェックされません。したがって、実行者権限プロシージャのユーザーには、DML文や動的SQL文の外側にある外部参照に対する権限は不要です。また、実行者権限プロシージャの開発者による権限の付与が必要なのは、プロシージャ自体に対する権限付与のみで、その実行者権限プロシージャによって直接参照されるすべてのオブジェクトに対する権限付与は必要ありません。

複数のプログラム・ユニットからなり、そのうちのいくつかは定義者権限、その他は実行者権限とするソフトウェア・バンドルを作成して、プログラム・エントリ・ポイントを制限できます(制御されたステップイン)。エントリ・ポイント・プロシージャの実行権限があるユーザーは、内部プログラム・ユニットも間接的に実行できますが、内部プログラムを直接コールすることはできません。問合せ処理を厳密に制御するには、PL/SQLパッケージ仕様を明示的なカーソルを使用して作成できます。

実行者権限プロシージャを作成する場合

特定の状況で実行者権限プロシージャを作成することをお薦めします。

これらの状況は次のとおりです。

  • 権限の高いスキーマのPL/SQLプロシージャを作成する場合。権限の弱いユーザーがプロシージャを起動する場合、それらのユーザーが実行を許可された部分のみ実行できます。つまり、実行者権限プロシージャは、実行するユーザーの権限で実行されます。

  • PL/SQLプロシージャがSQLを含まず、PL/SQLプロシージャを他のユーザーが使用できる場合。DBMS_OUTPUT PL/SQLパッケージは、SQLを含まないすべてのユーザーが使用できるPL/SQLサブプログラムの例です。この状況で実行者権限プロシージャを使用する必要がある理由は、ユニットが実行時にSQL文を発行しないので、実行時システムが権限をチェックする必要がないためです。AUTHID CURRENT_USERを指定すると、実行者権限プロシージャがコール・スタックを使用する場合にCURRENT_USERおよびCURRENT_SCHEMAの値と現在有効なロールが変更されないため、プロシージャの起動がより効率的になります。

関連項目:

  • Oracle Virtual Private Databaseのポリシーの構成

  • ANY権限とPUBLICロールの概要

  • Oracle Databaseで名前の解決を処理する方法と、実行者権限および定義者権限を使用して実行時の権限チェックを処理する方法の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

  • 実行者権限と定義者権限のユニットの違いの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

  • CREATE PACKAGE文で明示的なカーソルを定義する方法の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

プロシージャ・コールおよびビュー・アクセスの実行者権限の制御

INHERIT PRIVILEGES権限とINHERIT ANY PRIVILEGES権限を使用して、実行者権限プロシージャの実行時に使用される権限を規制できます。

内容は次のとおりです。

スキーマの権限が実行者権限プロシージャの使用に与える影響

権限の低いユーザーが権限の高いユーザーが所有するプロシージャを実行するような場合は、実行者権限プロシージャが便利です。

ユーザーが実行者権限プロシージャ(またはAUTHID CURRENT_USER句で作成されたPL/SQLプログラム・ユニット)を実行する場合、プロシージャの実行中に実行するユーザーのすべての権限を一時的に継承します。

その期間中に、プロシージャ所有者は、プロシージャを通じて、この実行するユーザーの権限にアクセスできます。次の使用例を考えてみます。

  1. ユーザーebrownは、check_syntax実行者権限プロシージャを作成し、ユーザーjwardにそのEXECUTE権限を付与します。

  2. 準プログラマのユーザーebrownは、仕事に必要な最低限のセットの権限のみです。check_syntaxプロシージャは、ebrownのスキーマにあります。

  3. マネージャのユーザーjwardは、ユーザーebrownよりさらに強力なセットの権限を持ちます。

  4. ユーザーjwardcheck_syntax実行者権限プロシージャを実行する場合、プロシージャは実行中にユーザーjwardより高い権限を継承します。

  5. ユーザーebrowncheck_syntaxプロシージャを所有するため、jwardcheck_syntaxプロシージャを実行するたびに、ユーザーjwardの権限にアクセスできます。

jwardがプロシージャを実行するたびに権限の弱いebrownのプロシージャがjwardの高い権限にアクセスできるこのタイプの状況の危険性は、プロシージャ所有者が実行するユーザーの高い権限を悪用できるリスクがあることです。たとえば、ユーザーebrownは、check_syntaxプロシージャをリライトしてebrownを上げるかebrownの不良なパフォーマンス評価レコードを削除して、jwardの高い権限を使用する可能性があります。また、ebrownは、元から定義者権限プロシージャとしてプロシージャを作成し、EXECUTE権限をjwardに付与して、後でjwardに通知することなく不正な可能性のある実行者権限プロシージャに変更できた可能性があります。アプリケーション・ユーザーなどのランダムなユーザーが実行者権限プロシージャを使用するデータベースにアクセスできる場合、これらのタイプのリスクが増加します。

ユーザーjwardebrownの実行者権限プロシージャを実行する場合、信頼要素が含まれます。ebrownjwardの権限にアクセスする場合に悪質な方法でcheck_syntaxプロシージャを使用しないことを確認する必要があります。INHERIT PRIVILEGESおよびINHERIT ANY PRIVILEGES権限は、ユーザーjwardに対してユーザーebrownのプロシージャがjwardの権限にアクセスできるかどうかの制御をサポートできます。ユーザーは、実行する実行者権限プロシージャのユーザーへのINHERIT PRIVILEGES権限を付与または取り消すことができます。SYSユーザーは、INHERIT ANY PRIVILEGES権限を管理します。

INHERIT [ANY] PRIVILEGES権限による権限アクセスの制御方法

INHERIT PRIVILEGESおよびINHERIT ANY PRIVILEGES権限を使用して、実行者権限プロシージャを保護します。

INHERIT PRIVILEGESおよびINHERIT ANY PRIVILEGES権限は、ユーザーが実行者権限プロシージャを実行するか、実行者権限プロシージャを参照するBEQUEATH CURRENT_USERビューに問い合せる場合に使用される権限を規制します。

ユーザーが実行者権限プロシージャを実行する場合、Oracle Databaseは、プロシージャ所有者が実行するユーザーのINHERIT PRIVILEGES権限を持っているか、所有者にINHERIT ANY PRIVILEGES権限が付与されているかを確認します。権限チェックに失敗した場合、Oracle Databaseは、 ORA-06598: INHERIT PRIVILEGES権限が不十分ですエラーを戻しません。

これらの2つの権限の利点は、実行者権限プロシージャを実行するか、BEQUEATH CURRENT_USERビューに問い合せる場合、実行するユーザーに権限にアクセスできるユーザーの制御を提供することです。

他のユーザーへのINHERIT PRIVILEGES権限の付与

デフォルトで、すべてのユーザーにINHERIT PRIVILEGES ON USER newuser TO PUBLICが付与されます。

付与が行われるのは、ユーザー・アカウントの作成時または以前に作成されたアカウントが現在のリリースにアップグレードされたときです。

実行するユーザーは、他のユーザーのINHERIT PRIVILEGE権限を取り消して、信頼するユーザーにのみ付与できます。

INHERIT PRIVILEGES権限の付与の構文は次のとおりです。

GRANT INHERIT PRIVILEGES ON USER invoking_user TO procedure_owner;

次のように値を指定します。

  • invoking_userは、実行者権限プロシージャを実行するユーザーです。このユーザーは、データベース・ユーザー・アカウントである必要があります。

  • procedure_ownerは、実行者権限プロシージャを所有するユーザーです。この値は、データベース・ユーザー・アカウントである必要があります。INHERIT PRIVILEGES権限をプロシージャの所有者に付与するかわりに、プロシージャに付与されるロールに権限を付与できます。

次のユーザーまたはロールは、実行者権限プロシージャを実行するユーザーによって付与されるINHERIT PRIVILEGES権限を持つ必要があります。

  • 実行者権限プロシージャを所有するユーザーまたはロール

  • BEQUEATH CURRENT_USERビューを所有するユーザーまたはロール

例: 実行するユーザーへのINHERIT PRIVILEGESの付与

GRANT文で、実行するユーザーのINHERIT PRIVILEGES権限をプロシージャ所有者に付与できます。

例5-1は、実行するユーザーjwardがユーザーebrownINHERIT PRIVILEGES権限を付与する方法を示しています。

例5-1 プロシージャ所有者への実行するユーザーのINHERIT PRIVILEGESの付与

GRANT INHERIT PRIVILEGES ON USER jward TO ebrown;

この文により、jwardが実行するとき、ebrownが書き込むまたは今後書き込む実行者権限プロシージャがjwardの権限にアクセスできます。

例: INHERIT PRIVILEGESの取消し

REVOKE文で、ユーザーのINHERIT PRIVILEGES権限を取り消すことができます。

例5-2は、ユーザーjwardebrownの権限の使用を取り消す方法を示しています。

例5-2 INHERIT PRIVILEGESの取消し

REVOKE INHERIT PRIVILEGES ON USER jward FROM ebrown;

他のユーザーへのINHERIT ANY PRIVILEGES権限の付与

デフォルトでは、ユーザーSYSは、INHERIT ANY PRIVILEGESシステム権限を持ち、この権限を他のデータベース・ユーザーまたはロールに付与できます。

すべてのANY権限と同様に、信頼できるユーザーまたはロールにのみこの権限を付与します。ユーザーまたはロールにINHERIT ANY PRIVILEGES権限が付与されると、このユーザーの実行者権限プロシージャは、実行するユーザーの権限にアクセスできます。DBA_SYS_PRIVSデータ・ディクショナリ・ビューを問い合せて、INHERIT ANY PRIVILEGES権限を付与されたユーザーを確認できます。

例: 信頼できるプロシージャ所有者へのINHERIT ANY PRIVILEGESの付与

GRANT文で、INHERIT ANY PRIVILEGES権限を信頼できるプロシージャ所有者に付与できます。

例5-3は、ユーザーebrownへのINHERIT ANY PRIVILEGES権限の付与方法を示しています。

例5-3 信頼できるプロシージャ所有者へのINHERIT ANY PRIVILEGESの付与

GRANT INHERIT ANY PRIVILEGES TO ebrown;

強力なユーザーのINHERIT ANY PRIVILEGES権限の取消しに注意してください。たとえば、ユーザーSYSTEMが一連の実行者権限プロシージャを作成したとします。SYSTEMINHERIT ANY PRIVILEGESを取り消す場合、INHERIT PRIVILEGE権限を特に付与しないかぎり、他のユーザーはプロシージャを実行できません。

INHERIT PRIVILEGESおよびINHERIT ANY PRIVILEGESの管理

デフォルトでは、PUBLICは、新しいユーザー・アカウントおよびアップグレードされたユーザー・アカウントのINHERIT PRIVILEGE権限を持ち、SYSユーザーは、INHERIT ANY PRIVILEGES権限を持ちます。

デフォルトでは、様々なOracleで定義されているユーザーの権限の悪用に対して保護できるよう設計されている一連のINHERIT PRIVILEGESの付与を構成します。

顧客が定義するユーザーのINHERIT PRIVILEGES ON USER user_name TO PUBLICのデフォルトの付与を取り消して、その特定のユーザーに応じて詳細な付与のINHERIT PRIVILEGESを付与できます。INHERIT ANY PRIVILEGES権限を付与されたユーザーを確認するには、DBA_SYS_PRIVSデータ・ディクショナリ・ビューを問い合せます。

  1. PUBLICからINHERIT PRIVILEGES権限を取り消します。

    例:

    REVOKE INHERIT PRIVILEGES ON invoking_user FROM PUBLIC;
    

    失敗したINHERIT PRIVILEGESチェックの実行時エラーのため、この時点で実行者権限プロシージャを実行するユーザーは実行できないことに注意してください。

  2. INHERIT PRIVILEGES権限を信頼できるユーザーまたはロールに選択的に付与します。
  3. 同様に、INHERIT ANY PRIVILEGES権限を信頼できるユーザーまたはロールにのみ選択的に付与します。

監査ポリシーを作成してこれらの2つの権限の付与および取消しを監査できますが、失敗したINHERIT PRIVILEGES権限チェックによって発生する実行時エラーは監査できません。

関連項目:

  • SQLインジェクション攻撃の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

  • GRANT文およびデフォルトの権限の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

ビューの定義者権限および実行者権限

CREATE VIEW SQL文でBEQEATH句を使用して、ユーザー作成ビューで定義者権限と実行者権限を制御できます。

内容は次のとおりです。

ビューの定義者権限および実行者権限の制御について

ユーザー定義ビューを構成して、ビューで参照される実行者権限関数に対応できます。

ユーザーがIDまたは権限依存のSQL関数または実行者権限のPL/SQLまたはJava関数を起動すると、現在のスキーマ、現在のユーザーおよび操作の実行内の現在有効なロールがビューの所有者に設定することなく問い合せたユーザーの環境から継承できます。

この構成は、ビュー自体から実行者権限のオブジェクトに変更しません。ビュー所有者のスキーマを使用してビュー内の名前解決が引き続き処理され、ビュー所有者の権限を使用してビューの権限チェックが実行されます。ただし、実行時に、ビューで参照される関数は、ビュー所有者ではなく実行するユーザーの権限で実行されます。

この機能の利点は、関数をビューで参照する場合に一貫した結果を戻すために実行するユーザーに正確な情報を戻す必要がある SYS_CONTEXTUSERENVなどの関数を有効にすることです。

CREATE VIEW文のBEQUEATH句の使用

BEQUEATHは、実行ユーザーの権限を使用してどのように実行者権限関数を実行するかを制御します。

ビューを参照するSQLを発行するユーザーの権限を使用して実行者権限関数を実行するには、CREATE VIEW文で、BEQUEATH句をCURRENT_USERに設定します。

ビューに対するSQL問合せまたはDML文を発行する場合、ビュー所有者は、実行するユーザーのINHERIT PRIVILEGES権限を付与するか、INHERIT ANY PRIVILEGES権限を持つ必要があります。そうしないと、SELECT問合せまたはDML文がBEQUEATH CURRENT_USERビューを含む場合、実行時システムは、エラー「ORA-06598: INHERIT PRIVILEGES権限が不十分です」を表示します。

  • BEQUEATH CURRENT_USER句を使用して、実行者権限を使用して実行するビューの関数を設定します。

例:

CREATE VIEW MY_OBJECTS_VIEW BEQUEATH CURRENT_USER AS
 SELECT GET_OBJS_FUNCTION;

ビューの所有者の権限を使用してビュー内の関数を実行する場合、BEQUEATH句を省略するか、DEFINERに設定します。

例:

CREATE VIEW my_objects_view BEQUEATH DEFINER AS
 SELECT OBJECT_NAME FROM USER_OBJECTS;

関連項目:

  • INHERIT PRIVILEGE権限の使用方法の詳細は、プロシージャ・コールおよびビュー・アクセスの実行者権限の制御を参照してください

  • INHERIT PRIVILEGESおよびINHERIT ANY PRIVILEGES権限の付与の詳細は、『Oracle Database SQL言語リファレンス』を参照してください

  • Oracle Database Real Application SecurityアプリケーションでのBEQUEATH CURRENT_USERビューの使用方法の詳細は、『Oracle Database Real Application Security管理者および開発者ガイド』を参照してください。

実行するユーザーのユーザー名またはユーザーIDの確認

実行者権限または定義者権限を使用するかどうかに基づいて、PL/SQLファンクションを使用して、実行するユーザーを確認できます。

  • 実行者権限または定義者権限のどちらを使用するかに基づいて、ORA_INVOKING_USER関数またはORA_INVOKING_USERID関数を使用して、実行するユーザーを確認します。

    • ORA_INVOKING_USER: この関数を使用して、現在の文またはビューを実行しているユーザーの名前を戻します。この関数は、介在しているビューをBEQUEATH句で指定されたとみなします。実行するユーザーがOracle Database Real Application Securityで定義されているユーザーの場合、この関数はXS$NULLを戻します。

    • ORA_INVOKING_USERID: この関数を使用して、現在の文またはビューを実行しているユーザーの識別子(ID)を戻します。この関数は、介在しているビューをBEQUEATH句で指定されたとみなします。実行するユーザーがOracle Database Real Application Securityで定義されているユーザーである場合、この関数は、すべてのReal Application Securityセッションに共通でデータベース・ユーザーのIDとは異なるIDを戻します。

      例:

      CONNECT HR
      Enter password: password
      
      SELECT ORA_INVOKING_USER FROM DUAL;
      
      ORA_INVOKING_USER
      --------------------
      HR

関連項目:

Oracle Database Real Application Securityアプリケーションに使用される類似の関数の詳細は、『Oracle Database Real Application Security管理者および開発者ガイド』を参照してください。

BEQUEATH DEFINERおよびBEQUEATH_CURRENT_USERビューの確認

ビューがBEQUEATH DEFINERまたはBEQUEATH CURRENT_USERビューであるかどうかを確認できます。

  • ビューがBEQUEATH DEFINERまたはBEQUEATH CURRENT_USERビューであるかどうかを確認するには、そのビューの*_VIEWSまたは*_VIEWS_AE静的データ・ディクショナリ・ビューのBEQUEATH列を問い合せます。

関連項目:

  • 静的データ・ディクショナリ・ビュー*_VIEWSの詳細は、『Oracle Databaseリファレンス』を参照してください。

  • 静的データ・ディクショナリ・ビュー*_VIEWS_AEの詳細は、『Oracle Databaseリファレンス』を参照してください。

例:

SELECT BEQUEATH FROM USER_VIEWS WHERE VIEW_NAME = 'MY_OBJECTS';

BEQUEATH
------------
CURRENT_USER

定義者権限および実行者権限のコード・ベース・アクセス制御の使用

コード・ベース・アクセス制御を使用して、PL/SQLファンクション、プロシージャまたはパッケージにデータベース・ロールをアタッチできます。この機能は、実行者権限および定義者権限のプログラム・ユニットで効果があります。

内容は次のとおりです。

アプリケーションのコード・ベース・アクセス制御の使用について

コード・ベース・アクセス制御(CBAC)を使用すると、実行者権限のプログラム・ユニットの管理を向上できます。

アプリケーションは、昇格した権限を必要とする一方で、コール側の環境でプログラム・ユニットを頻繁に実行する必要があります。従来PL/SQLプログラムは、定義者権限を使用してプログラムの権限を一時的に昇格します。

ただし、定義者権限ベースのプログラム・ユニットは、実行者のコンテキストではなくプログラム・ユニットの定義者または所有者のコンテキストで実行されます。また、定義者権限ベースのプログラムを使用すると、多くの場合にプログラム・ユニットが必要以上の権限を取得します。

コード・ベース・アクセス制御(CBAC)は、PL/SQLファンクション、プロシージャまたはパッケージへのデータベース・ロールのアタッチを可能にして、解決策を提供します。これらのデータベース・ロールは実行時に有効で、呼び出すユーザーの環境の必要な権限でプログラム・ユニットを実行できます。

コード・ベースのアクセス制御ロールをプログラム・ユニットに付与できる者

次のすべての条件を満たした場合、コード・ベースのアクセス制御ロールをプログラム・ユニットに付与できます。

これらの条件は次のとおりです。

  • 権限付与者は、ユーザーSYS、またはプログラム・ユニットの所有者です。

  • 権限付与者がプログラム・ユニットを所有する場合、権限付与者はGRANT ANY ROLEシステム権限を持つか、プログラム・ユニットに付与するロールに対してADMINまたはDELEGATEオプションを持つ必要があります。

  • 付与対象のロールは、所有者に対して直接付与されるロールです。

  • 付与対象のロールは、標準データベース・ロールです。

これらの3つの条件が満たされない場合、1番目の条件が満たされないときは、エラーORA-28702: プログラム・ユニットの文字列が権限付与者によって所有されていませんが生成され、2番目と3番目の条件が満たされないときは、エラーORA-1924: ロールの文字列は付与されていないか、存在していませんが生成されます。

コード・ベース・アクセス制御による実行者権限のプログラム・ユニットの処理方法

コード・ベース・アクセス制御では、実行ユーザーのコンテキストで、そのコンテキストに関連付けられたロールを使用してプログラム・ユニットを実行できます。

2つのアプリケーション・ユーザー1および2が存在するシナリオを検討します。アプリケーション・ユーザー2は、実行者権限のプログラム・ユニットを作成し、データベース・ロール2を実行者権限ユニットに付与して、実行者権限ユニットの実行権限をアプリケーション・ユーザー1に付与します。

図5-1に、アプリケーション・ユーザー1および2に付与されるデータベース・ロール1および2と実行者権限のプログラム・ユニットを示します。

図5-1 アプリケーション・ユーザーに付与されるロールおよび実行者権限のプログラム・ユニット

図5-1の説明が続きます。
「図5-1 アプリケーション・ユーザーに付与されるロールおよび実行者権限のプログラム・ユニット」の説明

付与は次のとおりです。

  • アプリケーション・ユーザー1に直接データベース・ロール1および4が付与されます。

  • アプリケーション・ユーザー2に直接アプリケーション・ロール3および4を含むデータベース・ロール2が付与されます。

  • 実行者権限のプログラム・ユニットにデータベース・ロール2が付与されます。

アプリケーション・ユーザー1がログインして実行者権限のプログラム・ユニットを実行する場合、実行者権限ユニットは、ユーザー1の結合されたデータベース・ロールおよび実行者権限ユニットに付加されたデータベース・ロールで実行されます。

図5-2は、実行者権限ユニットが実行されるセキュリティ・コンテキストを示しています。アプリケーション・ユーザー1が最初にログオンする場合、アプリケーション・ユーザー1は、データベースPUBLICロール(デフォルト)およびそれに付与されたデータベース・ロール1および4を持ちます。次に、アプリケーション・ユーザー1は、アプリケーション・ユーザー2によって作成された実行者権限のプログラム・ユニットを実行します。

実行者権限のユニットは、アプリケーション・ユーザー1のコンテキストで実行され、それに付加される追加のデータベース・ロール2を持ちます。データベース・ロール2の一部であるため、データベース・ロール3および4が含まれます。実行者権限ユニットを終了した後、アプリケーション・ユーザー1のみ、それに付与されたアプリケーション・ロール、PUBLIC、ロール1およびロール4を持ちます。

図5-2 実行者権限のプログラム・ユニットIRが実行されるセキュリティ・コンテキスト

図5-2の説明が続きます。
「図5-2 実行者権限のプログラム・ユニットIRが実行されるセキュリティ・コンテキスト」の説明

コード・ベース・アクセス制御による定義者権限のプログラム・ユニットの処理方法

コード・ベース・アクセス制御を使用して定義者権限を保護できます。

コード・ベース・アクセス制御は、定義するユーザーの権限で動作するプログラム・ユニットを有効にすることで定義者権限のプログラム・ユニットと連携し、このユーザーに関連付けられるデータベース・ロールを組み合せた権限で機能します。

アプリケーション・ユーザー2が定義者権限のプログラム・ユニットを作成し、定義者権限のプログラム・ユニットにロール2を付与して、定義者権限のプログラム・ユニットのEXECUTE権限をアプリケーション・ユーザー1に付与するシナリオを検討します。

図5-3に、アプリケーション・ユーザー1および2に付与されるデータベース・ロールと定義者権限のプログラム・ユニットを示します。

図5-3 アプリケーション・ユーザーに付与されるロールおよび定義者権限のプログラム・ユニット

図5-3の説明が続きます。
「図5-3 アプリケーション・ユーザーに付与されるロールおよび定義者権限のプログラム・ユニット」の説明

付与は次のとおりです。

  • アプリケーション・ユーザー1に直接データベース・ロール1および4が付与されます。

  • アプリケーション・ユーザー2に直接データベース・ロール3および4を含むデータベース・ロール2が付与されます。

  • 定義者権限のプログラム・ユニットにデータベース・ロール2が付与されます。

アプリケーション・ユーザー1がログインして定義者権限のプログラム・ユニットを実行する場合、定義者権限ユニットは、アプリケーション・ユーザー2の結合されたデータベース・ロールおよび定義者権限ユニットに付加されたデータベース・ロール(ロール23および4)で実行されます。

図5-4は、定義者権限のプログラム・ユニットが実行されるセキュリティ・コンテキストを示しています。アプリケーション・ユーザー1が最初にログオンする場合、アプリケーション・ユーザー1は、データベースPUBLICロール(デフォルト)およびそれに付与されたデータベース・ロール1および4を持ちます。次に、アプリケーション・ユーザー1は、アプリケーション・ユーザー2によって作成された定義者権限のプログラム・ユニットを実行します。

定義者権限のプログラム・ユニットは、アプリケーション・ユーザー2のコンテキストで実行され、それに付加される追加のデータベース・ロール2を持ちます。データベース・ロール2の一部であるため、データベース・ロール3および4が含まれます。定義者権限ユニットを終了した後、アプリケーション・ユーザー1のみ、それに付与されたデータベース・ロール(PUBLIC、ロール1およびロール4)を持ちます。

図5-4 定義者権限のプログラム・ユニットDRが実行されるセキュリティ・コンテキスト

図5-4の説明が続きます。
「図5-4 定義者権限のプログラム・ユニットDRが実行されるセキュリティ・コンテキスト」の説明

CBAC付与のためのユーザーへのデータベース・ロールの付与

GRANT文のDELEGATEオプションで、CBAC付与を行うユーザーによるロールへの権限付与を制限できます。

データベース・ロールをCBAC付与を行うユーザーに付与する場合、GRANT文にDELEGATEオプションを含めて、権限受領者にロールに対する追加権限が付与されないようにすることができます。

DELEGATEオプションを使用すると、ロールはプログラム・ユニットに付与されますが、他のプリンシパルまたはロール自体の管理にロールを付与することはできません。他のプリンシパルへのロールの付与を可能にするADMINオプションを付与に使用することもできます。ADMINDELEGATEオプションは共存できます。オプションごとに別のGRANT文で付与する必要はありますが、両方をユーザーに付与することができます。これらのオプション付きでユーザーにロールが付与されているかどうかを確認するには、ユーザーのUSER_ROLE_PRIVSまたはDBA_ROLE_PRIVSDELEGATE_OPTION列またはADMIN_OPTION列を問い合せます。

DELEGATEおよびADMINオプションを使用するための構文は次のとおりです。

GRANT role_list to user_list WITH DELEGATE OPTION;

GRANT role_list to user_list WITH ADMIN OPTION;

例:

GRANT cb_role1 to usr1 WITH DELEGATE OPTION;

GRANT cb_role1 to usr1 WITH ADMIN OPTION;

GRANT cb_role1, cb_role2 to usr1, usr2 with DELEGATE OPTION;

GRANT cb_role1, cb_role2 to usr1, usr2 with ADMIN OPTION;

マルチテナント環境では、ADMINオプションの場合と同様に共通ロールの共通ユーザーへの付与などの共通付与にDELEGATEオプションを使用できます。

例:

GRANT c##cb_role1 to c##usr1 WITH DELEGATE OPTION CONTAINER = ALL;

CBAC付与自体は、PDBでローカルにのみ行えることに注意してください。

関連項目:

ADMINオプションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

プログラム・ユニットに対するデータベース・ロールの付与と取消し

GRANTおよびREVOKE文で、プログラム・ユニットに対するデータベース・ロールの付与または取消しを行うことができます。

次の構文を使用して、PL/SQLファンクション、プロシージャまたはパッケージのデータベース・ロールを付与または取り消します。

GRANT role_list TO code_list 
REVOKE {role_list | ALL} FROM code_list
 

次のように値を指定します。

role_list ::=  code-based_role_name[, role_list]
code_list ::=  {
      {FUNCTION  [schema.]function_name}
   |  {PROCEDURE [schema.]procedure_name}
   |  {PACKAGE   [schema.]package_name}
                 }[, code_list]

例:

GRANT cb_role1 TO FUNCTION func1, PACKAGE pack1;

GRANT cb_role2, cb_role3 TO FUNCTION HR.func2, PACKAGE SYS.pack2;

REVOKE cb_role1 FROM FUNCTION func1, PACKAGE pack1;

REVOKE ALL FROM FUNCTION HR.func2, PACKAGE SYS.pack2;

チュートリアル: コード・ベース・アクセス制御による機密データへのアクセス制御

このチュートリアルでは、コード・ベース・アクセス制御を使用して、HRスキーマの機密データへのアクセスを制御する方法を示します。

内容は次のとおりです。

このチュートリアルの概要

このチュートリアルでは、自分の部門のために特定の従業員情報に対するアクセス権が必要なユーザーを作成します。

ただし、HR.EMPLOYEES表には従業員給与などの機密情報が含まれており、ユーザーにはアクセスできないようにする必要があります。アクセス制御は、コード・ベース・アクセス制御を使用して実装します。従業員データは、実行者権限プロシージャを通じてユーザーに表示されます。SELECT権限をユーザーに直接付与するかわりに、データベース・ロールを通じてSELECT権限を実行者権限プロシージャに付与します。このプロシージャでは、給与のような機密情報を非表示にします。このプロシージャは実行者権限プロシージャであるため、プロシージャ内で呼出し元のコンテキストがわかります。この場合、呼出し元のコンテキストは財務部門です。ユーザーの名前は"Finance"であるため、ユーザーは財務部門に勤務する従業員のデータのみにアクセス可能です。

ステップ1: ユーザーを作成してHRにCREATE ROLE権限を付与

開始するには、"Finance"ユーザー・アカウントを作成し、このHRユーザーにCREATE ROLE権限を付与する必要があります。

  1. ユーザー・アカウントおよびロールを作成する権限を持つ管理者としてデータベース・インスタンスにログインします。

    例:

    sqlplus sec_admin
    Enter password: password
    
  2. "Finance"ユーザー・アカウントを作成します。
    GRANT CONNECT TO "Finance" IDENTIFIED BY password;
    

    "Finance"が、大文字と小文字はこのまま、二重引用符で囲んで入力されていることを確認します。passwordを安全なパスワードに置き換えます。詳細は、パスワードの最低要件を参照してください。

  3. CREATE ROLE権限をユーザーHRに付与します。
    GRANT CREATE ROLE TO HR;

ステップ2: print_employees実行者権限プロシージャを作成

print_employees実行者権限プロシージャは、現在のユーザーの部門内の従業員情報を表示します。

プロシージャ内で呼出し元がだれであるかを知る必要があるため、このプロシージャを実行者権限プロシージャとして作成する必要があります。
  1. ユーザーHRとして接続します。
    CONNECT HR
    Enter password: password
    
  2. 次のようにprint_employeesプロシージャを作成します。
    create or replace procedure print_employees
    authid current_user
    as 
    begin
      dbms_output.put_line(rpad('ID', 10) ||
                           rpad('First Name', 15)  ||
                           rpad('Last Name', 15)   ||
                           rpad('Email', 15)       ||
                           rpad('Phone Number', 20));
      for rec in (select e.employee_id, e.first_name, e.last_name, 
                         e.email, e.phone_number
                    from hr.employees e, hr.departments d 
                   where e.department_id = d.department_id
                     and d.department_name = 
                         sys_context('userenv', 'current_user'))
      loop
        dbms_output.put_line(rpad(rec.employee_ID, 10)  ||
                             rpad(rec.first_name, 15)   || 
                             rpad(rec.last_name, 15)    ||
                             rpad(rec.email, 15)        ||
                             rpad(rec.phone_number, 20));
      end loop;
    end;
    /

    この例の説明は、次のとおりです。

    • dbms_output.put_lineは、表ヘッダーを印刷します。

    • for rec in (select ...は、呼出し元の部門の従業員情報を検索します。このチュートリアルでは、ユーザー"Finance"の財務部門となります。"Marketing"(これもHR.EMPLOYEES表のDEPARTMENT_NAME列にリストされています)という名前のユーザーを作成していた場合には、プロシージャはマーケティング部門従業員の情報を取得できました。

    • loopおよびdbms_output.put_lineは、出力に財務部門の従業員データを移入します。

ステップ3: hr_clerkロールを作成して権限を付与

次に、hr_clerkロールを作成し、print_employeesプロシージャに対するEXECUTE権限を付与する必要があります。

このロールを作成したら、これを"Finance"に付与する必要があります。
  1. hr_clerkロールを作成します。
    CREATE ROLE hr_clerk;
    
  2. print_employeesプロシージャのEXECUTE権限をhr_clerkロールに付与します。
    GRANT EXECUTE ON print_employees TO hr_clerk;
    
  3. hr_clerkロールを"Finance"に付与します。
    GRANT hr_clerk TO "Finance";

ステップ4: コード・ベース・アクセス制御HR.print_employeesプロシージャのテスト

コード・ベース・アクセス制御HR.print_employeesプロシージャをテストする準備が整いました。

コード・ベース・アクセス制御のHR.print_employeesプロシージャをテストするには、ユーザー"Finance"HR.EMPLOYEES表を問い合せて、HR.print_employeesプロシージャの実行を試みる必要があります。
  1. データベース・インスタンスにユーザー"Finance"として接続します。
    CONNECT "Finance"
    Enter password: password
    
  2. HR.EMPLOYEES表の直接問合せを試行します。
    SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY FROM HR.EMPLOYEES;
    

    ユーザーFinanceにはHR.EMPLOYEESへのSELECT権限がないため、問合せは失敗します。

    ERROR at line 1:
    ORA-00942: table or view does not exist
    
  3. HR.print_employeesプロシージャを実行します。
    EXEC HR.print_employees;
    

    ユーザー"Finance"が適切な権限を持っていないため、問合せは失敗します。

    ERROR at line 1:
    ORA-00942: table or view does not exist
    ORA-06512: at "HR.PRINT_EMPLOYEES", line 13ORA-06512: at line 1

ステップ5: view_emp_roleロールを作成して権限を付与

ここでは、ユーザーHRview_emp_roleロールを作成し、このロールに権限を付与する必要があります。

ユーザーHRSELECT権限HR.EMPLOYEESHR.DEPARTMENTSview_emp_roleロールに付与し、HR.EMPLOYEESHR.DEPARTMENTSSELECTview_emp_roleロールに付与します。
  1. ユーザーHRとして接続します。
    CONNECT HR
    Enter password: password
    
  2. view_emp_roleロールを作成します。
    CREATE ROLE view_emp_role;
    
  3. view_emp_roleロールにHR.EMPLOYEESHR.DEPARTMENTSSELECT権限を付与します。
    GRANT SELECT ON HR.EMPLOYEES TO view_emp_role;
    GRANT SELECT ON HR.DEPARTMENTS TO view_emp_role;
    
  4. view_emp_roleロールをHR.print_employees実行者権限プロシージャに付与します。
    GRANT view_emp_role TO PROCEDURE HR.print_employees;

ステップ6: HR.print_employeesプロシージャの再テスト

適切な権限がある場合、ユーザー"Finance"は、HR.print_employeesプロシージャを再試行できます。

  1. ユーザー"Finance"として接続します。
    CONNECT "Finance"
    Enter password: password
    
  2. サーバー出力をディスプレイに設定します。
    SET SERVEROUTPUT ON;
    
  3. HR.EMPLOYEES表の直接問合せを試行します。
    SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY FROM HR.EMPLOYEES;
    

    問合せが失敗します。

    ERROR at line 1:
    ORA-00942: table or view does not exist
    
  4. HR.print_employeesプロシージャを実行して、従業員情報を表示します。
    EXEC HR.print_employees;
    

    呼出しが成功します。

    ID        First Name     Last Name      Email          Phone Number
    108       Nancy          Greenberg      NGREENBE       515.124.4569
    109       Daniel         Faviet         DFAVIET        515.124.4169
    110       John           Chen           JCHEN          515.124.4269
    111       Ismael         Sciarra        ISCIARRA       515.124.4369
    112       Jose Manuel    Urman          JMURMAN        515.124.4469
    113       Luis           Popp           LPOPP          515.124.4567
    
    PL/SQL procedure successfully completed.

手順7: このチュートリアルのコンポーネントの削除

このチュートリアルのコンポーネントが不要になった場合、それらを削除できます。

  1. 管理者権限を持つユーザーとして接続します。

    例:

    CONNECT sec_admin
    Enter password: password
    
  2. ユーザー"Finance"を削除します。
    DROP USER "Finance";
    
  3. hr_clerkロールを削除します。
    DROP ROLE hr_clerk;
    
  4. ユーザーHRとして接続します。
    CONNECT HR
    Enter password: password
    
  5. view_emp_roleロールとHR.print_employeesプロシージャを削除します。
    DROP ROLE view_emp_role;
    DROP PROCEDURE print_employees;
    
  6. 管理者権限ユーザーとして接続します。
    CONNECT sec_admin
    Enter password: password
    
  7. HRからCREATE ROLE権限を取り消します。
    REVOKE CREATE ROLE FROM HR;