🔐

Db2の「SQL0551N 権限がありません」は“誰が・何を・どのオブジェクトに”を読んで最短で潰す

に公開

SQL0551N「認可IDに必要な権限がありません」は、開発中でも本番リリース直後でも遭遇率の高いエラーです。原因は「権限が足りない」のひと言なのですが、現場で時間を取られるのは本当に権限が無いのか、それとも思っている認可ID・スキーマと違うIDで実行しているのかの切り分けです。

GRANT を追加する前に確認すべきことがあります。「権限が無い」と思って手当たり次第に GRANT を積むと、最小権限の原則が崩れ、後で棚卸しができなくなります。まずメッセージを正しく読み、足りない権限を一点だけ特定してから付与するのが正攻法です。

この記事では、SQL0551N が出たときにメッセージの3つのトークンから原因を切り分け、必要な権限だけを付与する手順を解説します。

まず結論:SQL0551N は「認可ID・操作・オブジェクト」の3点で原因が絞れる

SQL0551N の SQLSTATE は 42501。Db2 12.1 のメッセージは、原因特定に必要な3つのトークンを明示します。

SQL0551N  The statement failed because the authorization ID does not
have the required authorization or privilege to perform the operation.
Authorization ID: "APPUSER".  Operation: "SELECT".  Object: "SALES.ORDERS".

読むべきは3つです。

  • Authorization ID … 実際にその文を実行している認可ID。これが「自分が思っているID」と違うことが多い
  • Operation … 足りない権限の種類(SELECTINSERTEXECUTEALTERREFERENCES など)
  • Object … 対象オブジェクト。スキーマ修飾まで見る(SALES.ORDERS なのか、意図せず APPUSER.ORDERS を見に行っていないか)

切り分けの順序はこうです。

  1. 認可IDとオブジェクト名(スキーマ)が想定どおりか を確認する(ここがズレている“権限ではない”ケースが最多)
  2. 想定どおりなら、その認可IDが本当に権限を持っていないかを カタログで確認
  3. 足りない一点だけを GRANT する(ロール/グループ経由で入れるべきかも判断)

ステップ1:まず「別のID・別スキーマで動いていないか」を疑う

SQL0551N の相当数は、権限の付与漏れではなく実行しているIDやスキーマの取り違えです。付与を足す前にここを潰します。現在の認可IDと既定スキーマを確認します。

VALUES (CURRENT USER, CURRENT SCHEMA);
1         2
--------- ---------
DB2INST1  DB2INST1

よくある取り違えは次の3つです。

  • 接続ユーザーが想定と違う。 アプリの接続文字列やデータソースが別のIDで繋いでいる。メッセージの Authorization ID が「開発者個人ではなくアプリ共通ID」になっていないか。
  • スキーマ修飾の漏れ。 SELECT * FROM ORDERS と非修飾で書くと、CURRENT SCHEMA(既定は接続ID)で解決される。APPUSER で繋いでいれば APPUSER.ORDERS を探しに行き、本来見たい SALES.ORDERS とは別物になる。メッセージの Object のスキーマが想定と違えばこれ。
  • 静的SQL(パッケージ)の実行権限。 埋め込みSQLやストアドの実体はパッケージで、実行には EXECUTE 権限が要る。表への直接権限があってもパッケージの EXECUTE が無いと弾かれる。

ここで原因が「取り違え」だと分かれば、スキーマ修飾を直す・正しいIDで繋ぐだけで解消し、GRANT は不要です。

ステップ2:認可IDが持っている権限をカタログで確認する

取り違えでないなら、その認可IDの権限を確認します。オブジェクト単位の権限は SYSCAT.TABAUTH を見ます。

-- 表 SALES.ORDERS に対する権限保持者
SELECT SUBSTR(GRANTEE,1,12) AS GRANTEE, GRANTEETYPE,
       SELECTAUTH, INSERTAUTH, UPDATEAUTH, DELETEAUTH
  FROM SYSCAT.TABAUTH
  WHERE TABSCHEMA = 'SALES' AND TABNAME = 'ORDERS';
GRANTEE      GRANTEETYPE SELECTAUTH INSERTAUTH UPDATEAUTH DELETEAUTH
------------ ----------- ---------- ---------- ---------- ----------
DB2INST1     U           G          G          G          G

読み方は次のとおりです。

  • GRANTEETYPEU=ユーザー / G=グループ / R=ロール。問題のIDが直接持っていなくても、所属グループやロール経由で持っていることがある点に注意。
  • 各AUTH列Y=保持 / G=保持かつ他者へ付与可(WITH GRANT OPTION)/ N=なし。

その認可IDが持つデータベース権限・管理権限SYSCAT.DBAUTH と、まとめて見るなら表関数 AUTH_LIST_AUTHORITIES_FOR_AUTHID が便利です。

-- 認可ID DB2INST1 が持つ権限(直接付与されているものを抽出)
SELECT SUBSTR(AUTHORITY,1,22) AS AUTHORITY, D_USER, D_GROUP, D_ROLE
  FROM TABLE(SYSPROC.AUTH_LIST_AUTHORITIES_FOR_AUTHID('DB2INST1','U'))
  WHERE D_USER = 'Y' OR D_GROUP = 'Y' OR D_ROLE = 'Y';
AUTHORITY              D_USER D_GROUP D_ROLE
---------------------- ------ ------- ------
DBADM                  Y      N       *
SECADM                 Y      N       *
DATAACCESS             Y      N       *
ACCESSCTRL             Y      N       *

D_USERD_GROUPD_ROLE は、その権限を直接(Directly)どの経路で持っているかを示します。DATAACCESS を持っていれば全表の読み書きができる、といった上位権限の有無もここで分かります。

ロール経由の権限を追うときは SYSCAT.ROLEAUTH でロールの所属を確認します。

SELECT SUBSTR(GRANTEE,1,12) AS GRANTEE, GRANTEETYPE, SUBSTR(ROLENAME,1,16) AS ROLENAME
  FROM SYSCAT.ROLEAUTH
  WHERE GRANTEE = 'APPUSER';

ステップ3:足りない権限“だけ”を付与する

原因が権限不足だと確定したら、メッセージの Operation に対応する権限を一点だけ GRANT します。

-- 表への SELECT だけを付与
GRANT SELECT ON SALES.ORDERS TO USER APPUSER;

-- 静的SQL/CLIパッケージの EXECUTE 不足なら
GRANT EXECUTE ON PACKAGE APPSCHEMA.PKG01 TO USER APPUSER;

-- 参照制約の作成に必要な REFERENCES 不足なら(メッセージ Operation が REFERENCES)
GRANT REFERENCES ON SALES.CUSTOMER TO USER APPUSER;

個々のオブジェクトではなく役割としてまとめて渡したいなら、ロールを作って権限をロールに集約し、ユーザーはロールに入れます。個人IDへ直接 GRANT を積むより棚卸ししやすくなります。

CREATE ROLE APP_RO;                                  -- 参照専用ロール
GRANT SELECT ON SALES.ORDERS TO ROLE APP_RO;
GRANT ROLE APP_RO TO USER APPUSER;

現場で効く注意点

  • グループ/ロール経由を見落とさない。 直接 GRANT されていなくても、OSグループやロール経由で権限を持つ/失うことがあります。GRANTEETYPE(U/G/R)を必ず確認し、SYSCAT.ROLEAUTH でロール所属も追います。
  • 静的SQLは「パッケージのBIND者」の権限で動く。 埋め込みSQLやストアドは、実行ユーザーではなくBINDした所有者の権限で解決されることがあります。「表権限はあるのに SQL0551N」なら、パッケージの EXECUTE 権限や、REBIND/再BINDが必要なケース(公式メッセージのシナリオ2)を疑います。
  • REVOKE は依存オブジェクトに波及する。 ある権限を剥がすと、それに依存していたビューやパッケージが無効化され、別の場所で SQL0551N が出ることがあります。剥がす前に依存関係を確認します。
  • メッセージのトークン表記はバージョンで変わる。 旧バージョンでは "APPUSER" does not have the privilege to perform operation "SELECT" on object "SALES.ORDERS" のような表記です。読む要素(誰が・何を・どのオブジェクトに)は同じです。

SQL0551N が出たときのチェックリスト

  1. メッセージの Authorization ID / Operation / Object を読む(SQLSTATEは 42501
  2. 取り違えを先に疑うVALUES (CURRENT USER, CURRENT SCHEMA) で実行ID・既定スキーマを確認。Object のスキーマ修飾が想定どおりか
  3. 取り違えでなければ SYSCAT.TABAUTH でそのオブジェクトの権限保持者と GRANTEETYPE(U/G/R)・保持状況(Y/G/N)を確認
  4. DB権限・管理権限は SYSCAT.DBAUTHAUTH_LIST_AUTHORITIES_FOR_AUTHID、ロールは SYSCAT.ROLEAUTH
  5. 足りない Operation の権限だけGRANT(役割ならロールに集約)
  6. 「表権限はあるのに弾かれる」ならパッケージの EXECUTE/再BINDを疑う
  7. DATAACCESSDBADM の安易な付与で消さない(被害範囲と監査の観点)

📕 もっと深く:Db2運用を12章で体系化した本を書きました

この記事で扱った SQL0551N と権限設計は、Db2運用のほんの一部です。

Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ——そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にしました。実機で検証した内容と、Db2の設計上そうなる理由をまとめました。

認証・暗号化・権限設計をまとめた**第3章「セキュリティ設計の基本と実装」**をはじめ、アーキテクチャ/構成パラメーター選定/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題・解決集まで、全12章+運用シェルスクリプト集です。

https://zenn.dev/firese/books/db2-practical-bible

Db2の運用で踏んだ地雷や、扱ってほしいテーマがあれば、ぜひコメントで教えてください。次の記事のネタにさせてもらいます。

Discussion