【Oracle】プロキシユーザー(PROXY USER)完全ガイド|ALTER USER GRANT CONNECT THROUGH で共有アカウントを監査可能にする方法・WITH ROLE・DBA_PROXIES・監査ログまで解説

【Oracle】プロキシユーザー(PROXY USER)完全ガイド|ALTER USER GRANT CONNECT THROUGH で共有アカウントを監査可能にする方法・WITH ROLE・DBA_PROXIES・監査ログまで解説 Oracle

Oracle の運用現場で必ず出てくる悩みが「アプリケーションスキーマのパスワードをどう扱うか」です。開発者や保守担当が共通のスキーマユーザー(例: APP_OWNER)で接続すると、監査ログに残る「誰が操作したか」は APP_OWNER 固定になり、内部統制の観点では致命的です。かといって個人ユーザーに APP_OWNER の全権を付与して回るのも、権限設計が崩壊します。

この問題を Oracle 標準機能だけで解決するのが プロキシユーザー(Proxy User / CONNECT THROUGH)です。個人ユーザー(プロキシ)の認証情報で接続し、実行権限はアプリスキーマ(ターゲット)として働く——監査証跡には「プロキシとターゲットの両方」が残ります。この記事では ALTER USER ... GRANT CONNECT THROUGH の全構文、ロール制限、3 種類の認証オプション、SQL*Plus / JDBC / SQL Developer からの接続方法、DBA_PROXIESUNIFIED_AUDIT_TRAIL による実ユーザー追跡まで、2026 年 4 月時点の Oracle 19c / 23ai の仕様を前提に網羅解説します。

スポンサーリンク

プロキシユーザーとは何か

プロキシユーザーは「自分の認証情報で、別ユーザーとしてログインする」仕組みです。図式化すると以下の流れになります。

登場人物 役割 認証情報の扱い
プロキシ(Proxy User) 実際に接続する個人ユーザー(例: TANAKA このユーザーのパスワードで認証する
ターゲット(Client User) 最終的に振る舞うスキーマ(例: APP_OWNER 通常パスワード不要。実行時の権限はこのユーザー
認可設定 ALTER USER target GRANT CONNECT THROUGH proxy 誰が誰として振る舞えるかを DB 側で定義
ここが本質: プロキシで接続しても、実行権限はすべてターゲット側のものになります。つまり「個人を認証して、アプリスキーマの権限でだけ動かす」を安全に実現できます。個人ユーザーにアプリスキーマの権限をばらまく必要がなくなり、離任時は個人プロキシを DROP USER するだけで退場させられます。

基本構文 ── ALTER USER … GRANT CONNECT THROUGH

プロキシ関係の定義は、必ず ターゲット側の ALTER USER で行います。「target に対して、proxy が CONNECT THROUGH できる」という読み方です。

プロキシの作成 ── 最小構成
-- ① まずプロキシとターゲットを作成(既存であればスキップ)
CREATE USER tanaka     IDENTIFIED BY "Tanaka#Pass_2026";
CREATE USER app_owner  IDENTIFIED BY "App#Owner_2026";

GRANT CREATE SESSION TO tanaka;

-- ② tanaka が app_owner として接続できるように認可
ALTER USER app_owner GRANT CONNECT THROUGH tanaka;

-- ③ 解除(やり方は逆に target 側で REVOKE)
ALTER USER app_owner REVOKE CONNECT THROUGH tanaka;
ターゲット(app_owner)には CREATE SESSION が必要ありません。 プロキシ経由で接続する場合、ターゲットが自分で直接ログインすることは想定しないため、CREATE SESSION を付けないでおくと、ターゲットのパスワードが漏れても直接ログインは阻止できます。これはプロキシユーザー運用のセキュリティ上の大きな利点です。

接続方法 ── SQL*Plus / JDBC / SQL Developer

SQL*Plus での接続構文

SQL*Plus は [ターゲット] をユーザー名の後に角括弧で付けます。シェル環境によっては括弧をクォートする必要があります。

sqlplus でプロキシ接続
# 基本構文: sqlplus プロキシ[ターゲット]/プロキシのパスワード@接続識別子
sqlplus tanaka[app_owner]/Tanaka#Pass_2026@orclpdb1

# bash/zsh では角括弧を明示クォート(ファイル名展開を防ぐ)
sqlplus "tanaka[app_owner]"/Tanaka#Pass_2026@orclpdb1

# CONNECT コマンドでも同じ書き方
SQL> CONNECT tanaka[app_owner]/Tanaka#Pass_2026@orclpdb1

# 接続後、セッションは app_owner として動く
SQL> SHOW USER
USER は "APP_OWNER"

JDBC Thin でのプロキシ接続

JDBC Thin ドライバはプロキシ専用の API(OracleConnection.openProxySession())を用意しています。最初にプロキシの認証情報で接続し、後からプロキシセッションを開く 2 段階構成です。

Java/JDBC Thin でのプロキシセッション
import java.sql.*;
import java.util.Properties;
import oracle.jdbc.OracleConnection;

// ① プロキシユーザーで普通に接続
Connection conn = DriverManager.getConnection(
    "jdbc:oracle:thin:@//db.example.com:1521/orclpdb1",
    "tanaka",
    "Tanaka#Pass_2026"
);

// ② プロキシセッションに切り替え
Properties prop = new Properties();
prop.put(OracleConnection.PROXY_USER_NAME, "app_owner");
// パスワード認証を要求されている場合のみ
// prop.put(OracleConnection.PROXY_USER_PASSWORD, "App#Owner_2026");

((OracleConnection) conn).openProxySession(
    OracleConnection.PROXYTYPE_USER_NAME, prop);

// ③ この時点からセッションは app_owner として動く
try (Statement st = conn.createStatement();
     ResultSet rs = st.executeQuery("SELECT USER FROM dual")) {
    while (rs.next()) {
        System.out.println(rs.getString(1));   // APP_OWNER
    }
}

SQL Developer での設定

SQL Developer では接続プロパティの 「プロキシ接続」 タブで「Proxy User」に実際に認証するプロキシを、通常の「ユーザー名」欄にターゲットを指定します。SQL*Plus の proxy[target]/pw と同じことを GUI でやる形です。

DBA Studio / Toad / OCI のユーザー: 商用ツールはほとんど「Proxy Authentication」オプションを備えています。チーム全体のツール選定時は、プロキシをサポートしているかを必ず確認してください。サポート外のツールを混ぜると、個人認証運用の穴になります。

3 種類の認証オプション

プロキシ関係には「ターゲット側の追加認証をどうするか」で 3 つの選択肢があります。セキュリティ要件に応じて使い分けます。

① デフォルト(プロキシの認証のみ)

プロキシのパスワードのみで接続可能
ALTER USER app_owner GRANT CONNECT THROUGH tanaka;

-- 接続: プロキシのパスワードだけで OK
-- sqlplus tanaka[app_owner]/Tanaka#Pass@db

もっともシンプル。個人認証だけ通れば、ターゲットのパスワードを知らなくても(むしろ知らないまま)プロキシできる。日常運用ではこれが基本形です。

② AUTHENTICATED USING PASSWORD(ターゲットのパスワードも要求)

ターゲットのパスワードも提示を要求
ALTER USER app_owner GRANT CONNECT THROUGH tanaka
  AUTHENTICATED USING PASSWORD;

-- 接続: ターゲットのパスワードも送る必要がある
-- sqlplus tanaka[app_owner/App#Owner_2026]/Tanaka#Pass@db
-- ※ Oracle 内部では AUTHENTICATION REQUIRED に変換される
AUTHENTICATED USING PASSWORD はセキュリティ的に逆効果になりがち: ターゲットのパスワードを知らなくてもプロキシできるのが本機能の核心メリットなのに、このオプションを付けるとターゲットのパスワードが JDBC 文字列や SQL*Plus コマンドに書かれる結果になります。明確な互換性要件(古いミドルウェアが要求する等)がなければ、デフォルトで運用するのが安全です。

③ AUTHENTICATED USING DISTINGUISHED NAME(証明書 / DN)

グローバルユーザーに DN 認証を要求
-- ターゲットをグローバルユーザーで作成
CREATE USER jeff IDENTIFIED GLOBALLY AS
  'CN=jeff,OU=americas,O=oracle,L=redwoodshores,ST=ca,C=us';

-- プロキシに DN 認証を設定
ALTER USER jeff GRANT CONNECT THROUGH hr
  AUTHENTICATED USING DISTINGUISHED NAME;
AUTHENTICATED USING DISTINGUISHED NAME / CERTIFICATEAUTHENTICATION REQUIRED を省略したのと同等の扱いになります。Oracle Internet Directory(OID)や OCI IAM などのエンタープライズ認証基盤と連携する場合にのみ使う上級オプションです。

WITH ROLE ── 権限を絞り込む

プロキシで接続した瞬間、ターゲットが持つすべてのロールがデフォルトで有効化されます。これを絞り込むのが WITH ROLE 句です。「最小権限の原則」を守るためにも、役割が限定される場合は必ずロール制限を掛けるべきです。

ロール制限の 4 パターン
-- ① 特定ロールだけ有効化(read_role のみ)
ALTER USER app_owner GRANT CONNECT THROUGH readonly_user
  WITH ROLE read_role;

-- ② 複数ロールをカンマ区切りで
ALTER USER app_owner GRANT CONNECT THROUGH support_user
  WITH ROLE read_role, support_role;

-- ③ 指定ロール以外すべて(デバッグ用ロールを除外)
ALTER USER app_owner GRANT CONNECT THROUGH admin_user
  WITH ROLE ALL EXCEPT debug_role;

-- ④ すべてのロールを無効化(超最小)
ALTER USER app_owner GRANT CONNECT THROUGH audit_user
  WITH NO ROLES;
プロキシセッションは「ターゲットが直接持つ権限+指定したロールで得られる権限」です。 ロール経由ではない直接 GRANT された権限は WITH NO ROLES でも有効なので、「直接 GRANT は誰に何を渡すかを特に慎重に設計する」のが鉄則になります。ロール設計全般は ユーザー・権限・ロール完全ガイド を参照してください。

プロキシ関係の確認 ── DBA_PROXIES / V$SESSION

DBA_PROXIES ── 現在の認可設定一覧

誰が誰として接続できるかを棚卸し
SELECT
  proxy,                          -- プロキシユーザー名
  client,                         -- ターゲット(クライアント)ユーザー名
  authentication,                 -- N / Y(AUTHENTICATION REQUIRED か)
  authorization_constraint,       -- PROXY MAY ACTIVATE ALL CLIENT ROLES / NO CLIENT ROLES など
  role,                           -- WITH ROLE で許可されているロール
  flags                           -- PROXY MAY ACTIVATE ROLE 等のフラグ
FROM   dba_proxies
ORDER  BY client, proxy;

-- USER_LEVEL で見るには PROXY_USERS ビュー(自分がプロキシできる相手のみ)

V$SESSION ── 稼働中のプロキシセッション可視化

現在プロキシ接続中のセッションを検出
SELECT
  s.sid,
  s.serial#,
  s.username          AS target_user,         -- app_owner
  p.username          AS proxy_user,          -- tanaka
  s.osuser,
  s.machine,
  s.program,
  s.logon_time,
  s.proxy_sessionid   AS proxy_sid            -- プロキシセッションの識別子
FROM   v$session s
LEFT   JOIN v$session p
  ON   s.proxy_sessionid = p.sid
WHERE  s.proxy_sessionid IS NOT NULL
ORDER  BY s.logon_time DESC;
V$SESSION の見方: 普通のセッション(プロキシ接続でない)では PROXY_SESSIONID が NULL です。値が入っていれば必ずプロキシ接続。USERNAME はターゲットで、プロキシ本人を知りたい時は PROXY_SESSIONID を使って V$SESSION を自己結合します。

SYS_CONTEXT でセッションの内実を見る

アプリから自分のプロキシ状態を確認
SELECT
  SYS_CONTEXT('USERENV','SESSION_USER')           AS session_user,   -- APP_OWNER(ターゲット)
  SYS_CONTEXT('USERENV','PROXY_USER')             AS proxy_user,     -- TANAKA(プロキシ)
  SYS_CONTEXT('USERENV','AUTHENTICATED_IDENTITY') AS authn_user,     -- TANAKA
  SYS_CONTEXT('USERENV','IDENTIFICATION_TYPE')    AS id_type         -- PROXY 等
FROM dual;

-- プロキシ接続でない時は PROXY_USER が NULL

監査ログで実ユーザーを追跡する

プロキシユーザーの最大の価値は「監査で実ユーザーが追える」ことです。Unified Audit では DBUSERNAME(ターゲット)と DBPROXY_USERNAME(プロキシ)が別カラムで記録され、「APP_OWNER として何をした」と「それを実行した実ユーザーは誰だった」が両方わかります。

プロキシ経由で発行された SQL を個人単位で追跡
-- Unified Audit が有効(12c 以降デフォルト)前提
SELECT event_timestamp,
       dbproxy_username    AS proxy_user,     -- 個人(TANAKA)
       dbusername          AS target_user,    -- スキーマ(APP_OWNER)
       os_username,
       action_name,
       SUBSTR(sql_text, 1, 80) AS sql_text
FROM   unified_audit_trail
WHERE  dbproxy_username IS NOT NULL
  AND  event_timestamp > SYSDATE - 1
ORDER  BY event_timestamp DESC
FETCH FIRST 100 ROWS ONLY;
特定個人のすべての操作を抽出(退職時レビューなど)
SELECT event_timestamp,
       dbusername,
       action_name,
       object_schema || '.' || object_name AS target_obj,
       SUBSTR(sql_text, 1, 120) AS sql_text
FROM   unified_audit_trail
WHERE  dbproxy_username = 'TANAKA'
  AND  event_timestamp BETWEEN TIMESTAMP '2026-01-01 00:00:00'
                           AND TIMESTAMP '2026-04-01 00:00:00'
ORDER  BY event_timestamp;
古い監査(伝統的監査)だけを使っている場合は要注意。 Unified Audit(統合監査)を有効にしていない古い環境では、プロキシユーザーの情報が DBA_AUDIT_TRAIL に十分に残らないケースがあります。2026 年時点では Unified Audit への移行が強く推奨されています。詳細は 統合監査(Unified Audit)完全ガイド を参照してください。

実務ユースケースと移行パターン

ユースケース① 共有アカウント運用の解消

「APP_OWNER のパスワードを開発チーム全員で共有している」という状態を、監査可能な形に移行する典型パターンです。

  1. 各メンバーに個人ユーザー(TANAKASATOSUZUKI …)を作成
  2. APP_OWNER を対象に GRANT CONNECT THROUGH で全員を認可
  3. APP_OWNER から CREATE SESSION を剥奪して直接ログインを封じる
  4. APP_OWNER のパスワードを強制ローテーションし、金庫に封印
  5. 監査で DBPROXY_USERNAME IS NOT NULL が常態になっていることを確認

ユースケース② 参照専用 BI ツール接続

BI ツールが APP_OWNER にフル権限で接続していると、誤操作で UPDATE / DELETE が走るリスクがあります。プロキシと WITH ROLE で参照のみに絞り込みます。

BI 専用プロキシの設計例
-- ① 参照専用ロールを作成
CREATE ROLE app_read_only;
GRANT SELECT ANY TABLE TO app_read_only;     -- または個別テーブル

-- ② BI 接続用のプロキシユーザー
CREATE USER bi_readonly IDENTIFIED BY "BIRead#2026";
GRANT CREATE SESSION TO bi_readonly;

-- ③ app_read_only ロールだけ有効にしてプロキシ
ALTER USER app_owner GRANT CONNECT THROUGH bi_readonly
  WITH ROLE app_read_only;

-- BI ツールは bi_readonly[app_owner] で接続
-- → UPDATE / DELETE はロールに含まれないため実行不可

ユースケース③ 自動化 / バッチからの接続

CI/CD や夜間バッチが接続する場合、ジョブごとに専用プロキシを作るとログで追跡しやすくなります。ジョブを廃止する時は該当プロキシを DROP USER するだけで、アプリスキーマに影響を与えずに撤去できます。

ユースケース④ マルチテナント環境での PDB 管理

CDB/PDB 構成で、PDB 内のアプリスキーマを複数の DBA で管理する場合、各 DBA にプロキシ経由でアクセスさせると、どの DBA がどの PDB を触ったかが監査で追えます。マルチテナントの全体設計は マルチテナント完全ガイド を参照してください。

プロキシ関係の解除と棚卸し

解除とクリーンアップ
-- ① 個別解除(target の ALTER USER で REVOKE)
ALTER USER app_owner REVOKE CONNECT THROUGH tanaka;

-- ② 特定ユーザーがプロキシできる相手を全部洗い出し
SELECT proxy, client
FROM   dba_proxies
WHERE  proxy = 'TANAKA';

-- ③ 退職者のプロキシを一括解除(PL/SQL 例)
BEGIN
  FOR r IN (SELECT client FROM dba_proxies WHERE proxy = 'RETIRED_USER') LOOP
    EXECUTE IMMEDIATE 'ALTER USER ' || r.client ||
                      ' REVOKE CONNECT THROUGH retired_user';
  END LOOP;
  EXECUTE IMMEDIATE 'DROP USER retired_user CASCADE';
END;
/
退職・異動時の定型作業: 個人プロキシユーザーを DROP USER ... CASCADE すると、DBA_PROXIES の関連エントリも自動的に消えます。ただしターゲット側のオブジェクト(スキーマのテーブルなど)には影響しません。個人単位でアクセス停止できるのがプロキシ運用の最大の利点です。

落とし穴と注意点

プロキシに付与した権限は接続後は無効になる

プロキシユーザー自身に SELECT ANY TABLE などを付与しても、プロキシ経由で接続した後はターゲットの権限で動くため、プロキシ側の権限は一切使えません。プロキシにはログインに必要な CREATE SESSION だけ付与するのが原則です。

AUTHENTICATION REQUIRED はクライアント実装依存

AUTHENTICATED USING PASSWORD を指定すると、ターゲットのパスワードを JDBC / OCI の接続文字列に含める必要があります。多くの JDBC プールはこのパターンをサポートしていないため、一般的な Web アプリでは使いにくい構成です。安易に付けると運用が詰みます。

プロキシセッションは ALTER SESSION SET CURRENT_SCHEMA とは別物

ALTER SESSION SET CURRENT_SCHEMA = app_owner はスキーマ名の解決先を変えるだけで、権限はプロキシユーザーのままです。「実行者は APP_OWNER」にしたいならプロキシが必須です。混同しないように注意。

SQL*Plus の角括弧はシェルで展開される

bash / zsh で sqlplus tanaka[app_owner]/pw@db を書くと、シェルが [app_owner] をグロブ展開しようとして失敗することがあります。必ず "tanaka[app_owner]" のようにクォートしてください。

ダブルクォートで囲んだユーザー名は大文字小文字区別

Oracle のユーザー名は通常大文字化されますが、CREATE USER "tanaka" のようにダブルクォートで作ったユーザー名は小文字のまま登録されます。プロキシ関係の ALTER USER でも同じ表記を使う必要があります。混在するとメンテ時に必ずハマるため、組織として命名規則を統一してください。

よくある質問

Qプロキシユーザーとロール経由の権限付与は何が違いますか?
A監査の粒度がまったく違います。ロール経由では「個人がそのロールで何をしたか」までは追えますが、「アプリスキーマのオブジェクトとしての所有者視点」では追跡できません。プロキシは DBUSERNAME(ターゲット)と DBPROXY_USERNAME(個人)を両方記録するため、「APP_OWNER として発行された SQL を、実際には TANAKA が実行した」という 2 軸で記録が残ります。スキーマ所有者単位のアクセス制御を維持しつつ個人認証が欲しい時はプロキシが唯一の解です。
Qプロキシで接続すると CURRENT_SCHEMA は変わりますか?
A自動的にターゲットスキーマに切り替わります。sqlplus tanaka[app_owner]/pw@db で接続すると CURRENT_SCHEMA = APP_OWNER の状態で始まるため、スキーマ修飾なしで APP_OWNER のオブジェクトにアクセスできます。追加で別スキーマに切り替えたい場合は ALTER SESSION SET CURRENT_SCHEMA を使えますが、権限はプロキシセッションのまま(ターゲット+WITH ROLE 指定分)なので注意してください。
QSYS や SYSTEM をターゲットにできますか?
A技術的には可能ですが推奨されません。SYS は CONNECT THROUGH できますが、管理権限(SYSDBA)はプロキシ経由では継承されない挙動があり、想定通り動かない場合があります。SYS への個人認証が欲しい場合はプロキシではなく、個人 DBA ユーザーに SYSDBA 権限を直接付与する運用(SYS・SYSTEM・SYSDBA の違い完全ガイド参照)のほうがシンプルで監査しやすいです。
QJDBC 接続プールとプロキシユーザーは併用できますか?
Aはい。Oracle Universal Connection Pool (UCP) や OracleDataSource が PROXYTYPE_USER_NAME を明示的にサポートしており、プール内の物理接続はプロキシユーザーで張り、論理接続ごとに異なるターゲットに openProxySession() できます。Web アプリで「リクエストごとにエンドユーザーとしてふるまう」実装が可能になるため、DBA_AUDIT レベルで個人まで追跡したいシステムに最適です。
Qプロキシユーザー本人のパスワード変更を忘れるとどうなりますか?
A個人プロキシユーザーのパスワードが期限切れ(PASSWORD_LIFE_TIME)になると ORA-28001 でログイン自体が不可能になります。ターゲットは直接 CREATE SESSION を持たない設計が推奨なので、対処は個人プロキシのパスワードを変更するだけです。プロファイル設計は プロファイル完全ガイド を参考にしてください。
Q接続してきた後に「実は APP_OWNER ではなく APP_READONLY として振る舞いたい」と切り替えできますか?
A既存セッション内でターゲットを切り替えることはできません。プロキシセッションはログイン時に決まります。切り替えたい場合は一度接続を閉じて、別のターゲットを指定して再接続する必要があります(sqlplus tanaka[app_readonly]/pw@db)。1 つのセッションで複数スキーマを扱いたい場合は ALTER SESSION SET CURRENT_SCHEMA を使いますが、権限は変わらないためアクセス制御の目的では不十分です。
Qプロキシユーザーを作っただけで、既存のアプリ接続は影響ありますか?
AGRANT CONNECT THROUGH を設定するだけでは既存の直接接続には影響しません。既存接続を強制的にプロキシ化したい場合は、ターゲットから CREATE SESSION 権限を剥奪します(REVOKE CREATE SESSION FROM app_owner)。ただし剥奪するとアプリが一斉に接続できなくなるため、必ず先にアプリ側の接続文字列をプロキシ形式に変更してからリリースしてください。
QOracle Autonomous Database や OCI でもプロキシユーザーは使えますか?
A使えます。Oracle Autonomous Database(ADB)でも ALTER USER ... GRANT CONNECT THROUGH が利用可能で、OCI IAM との統合プロキシ認証もサポートされています。特にマルチテナント SaaS や BaaS でのマルチユーザー運用では、ADB 側のプロキシと OCI IAM の統合が個人トレーサビリティの標準構成になります。

まとめ

  • プロキシユーザーは「個人認証 × スキーマ権限」を両立する仕組み。ターゲットのパスワードを配らずに個人単位で追跡可能な接続が実現できる
  • 構文は ALTER USER target GRANT CONNECT THROUGH proxy。必ずターゲット側で実行する
  • 認証は 3 種類(デフォルト / AUTHENTICATED USING PASSWORD / DISTINGUISHED NAME)。基本はデフォルトで運用。PASSWORD 指定は互換性要件がなければ使わない
  • WITH ROLE / WITH NO ROLES / WITH ROLE ALL EXCEPT でロール制限。参照専用 BI や自動バッチは必ず絞る
  • SQL*Plus は proxy[target]/pw@db 形式、JDBC Thin は openProxySession()。SQL Developer など商用ツールも多くが対応
  • 確認ビュー: DBA_PROXIES(認可設定)・V$SESSION.PROXY_SESSIONID(稼働中セッション)・SYS_CONTEXT(‘USERENV’,’PROXY_USER’)(アプリからの確認)
  • 監査は UNIFIED_AUDIT_TRAIL.DBPROXY_USERNAME で実ユーザー追跡。退職者のアクセス履歴レビューもワンクエリで完結
  • ターゲットから CREATE SESSION を剥奪して直接ログインを封じると、アプリスキーマのパスワード漏洩リスクが実質ゼロになる

権限確認の SQL 全体は Oracle ユーザ権限を確認する方法完全ガイド、管理ユーザーと管理権限の設計は SYS・SYSTEM・SYSDBA の違い完全ガイド、ユーザー作成から権限ロール管理の全体像は ユーザー・権限・ロール完全ガイド、パスワード有効期限や複雑性ポリシーは プロファイル完全ガイド、監査ログの読み方は 統合監査(Unified Audit)完全ガイド もあわせて参照してください。