Amazon Redshift: クラスタ環境の分析・確認用に権限制御したユーザーを準備する
Amazon Redshiftに於いてクエリパフォーマンスのチューニングを行う場合、アクセス対象のテーブルに対する権限を持ったユーザーで無いと当然の事ながらDBに接続し、中身を調べる事は出来ません。スーパーユーザー権限を持つユーザーであれば、基本的に全てのスキーマ・テーブル・ビューにアクセスする事が出来るのですが、当然ながら『何でも出来てしまう』ため、(意図しない形であっても、故意にであっても)Redshiftクラスタ内の要素に対して更新や削除が出来てしまえます。管理者的な立場にある人ならいざ知らず、他者(他社)に作業を依頼する場合であれば必要最小限のユーザー権限のみ保有するユーザーを作成しておき、余計な事はさせたくない、と思うはずです。(調査を受ける方としても同じ思いでしょう)
そこで当エントリでは、そのような状況になった場合、どういった形でその『調査用』ユーザーを用意するのが良いのかという観点で関連しそうなポイントを調べてみました。
目次
- テスト用グループ・ユーザーの作成
- 想定する構築状況
- ユーザー作成の要素に対する権限付与設定
- システム系のテーブル・ビューに対する権限付与設定
- 調査分析に使うコマンドの実行確認
- 付録:Amazon Redshift システム系テーブル・ビュー一覧
- まとめ
テスト用グループ・ユーザーの作成
先ず最初に、アクセス確認を行う為のユーザー及びユーザーが所属するグループを作成しておきます。スーパーユーザーでDBにアクセスし、以下コマンドで要素を作成します。
/** グループの作成. */ # CREATE GROUP cm_cluster_research; CREATE GROUP /** ユーザーの作成及びグループへのユーザーの追加. */ # CREATE USER research_user WITH PASSWORD 'abc123DEF'; CREATE USER # ALTER GROUP cm_cluster_research ADD USER research_user; ALTER GROUP
想定する構築状況
今回状況として構築したいのは、以下のようなものを想定しています。以降の手順で、この形に近づけていく作業を行っていきます。
- 対象となるスキーマ内のテーブルに於いては、参照権限(SELECT)のみ許可する必要最低限の形としたい。
- また、各種情報・状況調査の為にシステム系テーブルも見たいものについては見られるようにしておく必要がある。
ユーザー作成の要素に対する権限付与設定
分析や参照に利用する為のテーブルを任意のスキーマに作成します。スキーマ名:cm_research、テーブル名:redshift_testで要素を作成しました。
/** スキーマの作成. */ # CREATE SCHEMA cm_research; CREATE SCHEMA /** テーブルの作成. */ # CREATE TABLE cm_research.redshift_test ( # id CHAR(5) NOT NULL encode lzo, # name VARCHAR(30) NOT NULL encode lzo, # quantity INT NOT NULL encode mostly16, # date DATE NOT NULL encode delta, # PRIMARY KEY(id)) # distkey(id) # sortkey(date,id); CREATE TABLE #
この時点ではグループ及びユーザーの作成、またスキーマ及びテーブルの作成は済んでいますが、両者間の紐付けは特に行っていません。作成したユーザーでログイン後、テーブルにアクセスを試みてみます。全て『権限が無い為』に弾かれています。
/** SELECT文実行. */ => SELECT * FROM cm_research.redshift_test; ERROR: permission denied for schema cm_research /** INSERT文実行. */ => INSERT INTO cm_research.redshift_test VALUES('0001','テスト1',100,'2014/08/20'); ERROR: permission denied for schema cm_research /** UPDATE文実行. */ => UPDATE cm_research.redshift_test SET quantity = 999 WHERE id = '0001'; ERROR: permission denied for schema cm_research /** DELETE文実行. */ => DELETE FROM cm_research.redshift_test; ERROR: permission denied for schema cm_research =>
スーパーユーザーで入り直し、所定のユーザー・もしくはユーザーが所属するグループに対し、必要なテーブルに必要な権限を付与します。このエントリでは、テーブルへのアクセス許可をグループに付与する形で進めますので、権限付与もグループに対して行います。
/** 対象グループに対し利用権限を付与する. */ # GRANT USAGE ON SCHEMA cm_research TO GROUP cm_cluster_research; GRANT # /** 更に、対象テーブルに対して参照権限『のみ』与える. */ # GRANT SELECT ON cm_research.redshift_test TO GROUP cm_cluster_research; GRANT
再度作成したユーザーで入り直し、処理を試みてみます。権限付与したSELECT文だけ実行出来るようになりました。
/** SELECT文実行. */ => SELECT * FROM cm_research.redshift_test; id | name | quantity | date ----+------+----------+------ (0 rows) /** INSERT文実行. */ => INSERT INTO cm_research.redshift_test VALUES('0001','テスト1',100,'2014/08/20'); ERROR: permission denied for relation redshift_test /** UPDATE文実行. */ => UPDATE cm_research.redshift_test SET quantity = 999 WHERE id = '0001'; ERROR: permission denied for relation redshift_test /** DELETE文実行. */ => DELETE FROM cm_research.redshift_test; ERROR: permission denied for relation redshift_test =>
対象テーブルの定義の確認も行えました。
cmawsteamdb=> \d cm_research.redshift_test; Table "cm_research.redshift_test" Column | Type | Modifiers ----------+-----------------------+----------- id | character(5) | not null name | character varying(30) | not null quantity | integer | not null date | date | not null Indexes: "redshift_test_pkey" PRIMARY KEY, btree (id)
システム系のテーブル・ビューに対する権限付与設定
システム系のテーブル・ビューは以下の様な用途・種別で分類されています。
- ログ記録のための STL テーブル
- スナップショットデータの STV テーブル
- システムビュー
- システムカタログテーブル
そして、システムテーブルには『可視性』というものが設定されており、閲覧者ユーザーがどの権限なのかでテーブルの閲覧内容に制限がある様です。
システムテーブルとビューには、データについて 2 つのクラスの可視性 (ユーザーが表示可能、スーパーユーザーが表示可能)があります。 スーパーユーザー特権を持っているユーザーのみが、 スーパーユーザーが表示可能なカテゴリのテーブルのデータを表示できます。 通常のユーザーは、ユーザーが表示可能なテーブルのデータを表示できますが、 表示できるのは自分のアクティビティによって生成された行のみです。 別のユーザーによって生成された行は、通常のユーザーには表示されません。 スーパーユーザーは両方のカテゴリのテーブルのすべての行を表示できます。
それぞれ内容を確認してみます。
アクセス制限:『ユーザー』に指定されているシステム・ビューへの確認
システムカタログテーブル:PG_TABLE_DEFが見えるかどうか確認してみます。上記でスキーマを新規作成してるので一度パラメータグループに値を追加し、再起動する必要があります。
再起動後作成したユーザーで内容を確認してみたところ、内容は取得出来ました。特に権限付与設定をせずとも問題無さそうです。
=> SELECT DISTINCT schemaname, tablename FROM pg_table_def WHERE schemaname = 'cm_research'; schemaname | tablename -------------+-------------------- cm_research | redshift_test cm_research | redshift_test_pkey (2 rows)
御覧の様にテーブル構造も情報を取得出来ています。
=> SELECT * FROM pg_table_def WHERE schemaname = 'cm_research'; schemaname | tablename | column | type | encoding | distkey | sortkey | notnull -------------+--------------------+----------+-----------------------+----------+---------+---------+--------- cm_research | redshift_test | id | character(5) | lzo | t | 2 | t cm_research | redshift_test | name | character varying(30) | lzo | f | 0 | t cm_research | redshift_test | quantity | integer | mostly16 | f | 0 | t cm_research | redshift_test | date | date | delta | f | 1 | t cm_research | redshift_test_pkey | id | character(5) | lzo | t | 2 | f (5 rows)
その他システム系のテーブル・ビューについても内容は取得出来ました。
=> SELECT COUNT(*) FROM STL_SAVE; count ------- 258 (1 row) => SELECT COUNT(*) FROM SVL_QLOG; count ------- 13 (1 row)
アクセス制限:『全てのユーザー』に指定されているシステム・ビューへの確認
ドキュメント上、『すべてのユーザー』と記載のあるものについても内容は確認出来る模様。『ユーザー』『全てのユーザー』については、"閲覧可能だが自らのユーザーに該当するもののみ"という仕様があるので、ここで引っ掛かって居るのはその条件を満たした内容のようですね。
=> SELECT COUNT(*) FROM STL_DDLTEXT; count ------- 0 (1 row) => SELECT COUNT(*) FROM SVL_COMPILE; count ------- 155 (1 row)
アクセス制限:『スーパーユーザー』に指定されているシステム・ビューへの確認
まずは現時点でそのままアクセスしてみます。『権限が無い』と怒られますね。
=> SELECT COUNT(*) FROM STL_CONNECTION_LOG; ERROR: permission denied for relation stl_connection_log => SELECT COUNT(*) FROM SVV_DISKUSAGE; ERROR: permission denied for relation svv_diskusage =>
スーパーユーザーでログインし直し、作成ユーザー(のグループ)に対して権限付与設定を試みて見ます...出来ました!
# GRANT SELECT ON pg_catalog.stl_connection_log TO GROUP cm_cluster_research; GRANT # GRANT SELECT ON pg_catalog.svv_diskusage TO GROUP cm_cluster_research; GRANT
作成ユーザーでログインし直してみると、これらのテーブルでも権限を付与すればアクセス出来る事が分かりました。
=> SELECT COUNT(*) FROM STL_CONNECTION_LOG; count ------- 945 (1 row) => SELECT COUNT(*) FROM SVV_DISKUSAGE; count ------- 27595 (1 row)
調査分析に使うコマンドの実行確認
クエリの実行計画を表示するEXPLAINコマンドはどうでしょうか。上記で作成したテーブルは何もデータを入れてないので結果らしい結果は出ませんが、実行は可能でした。参照権限があれば対象テーブル(が入っている)クエリの実行計画の取得は可能そうです。
=> EXPLAIN SELECT * FROM cm_research.redshift_test; QUERY PLAN ------------------------------------------------------------------------------ XN Seq Scan on redshift_test (cost=0.00..5.60 rows=560 width=90) ----- Tables missing statistics: redshift_test ----- ----- Update statistics by running the ANALYZE command on these tables ----- (3 rows)
若干ズレますが、VACUUMやANALYZEはどうでしょうか。これはその要素のオーナー(作成者)で無ければ駄目な様です。
=> VACUUM cm_research.redshift_test; ERROR: skipping "redshift_test" --- only table or database owner can vacuum it => ANALYZE cm_research.redshift_test; ERROR: skipping "redshift_test" --- only table or database owner can analyze it
付録:Amazon Redshift システム系テーブル・ビュー一覧
以下に、Amazon Redshiftで提供されているシステム系のテーブル・ビューに関する情報をまとめます。アクセス権限情報の一覧付きです。
ログ記録のためのSTLテーブル一覧
テーブル名 | 説明 | 参照可能ユーザー |
---|---|---|
STL_AGGR | 集計を実行するステップのクエリについて分析 | 全てのユーザー |
STL_ALERT_EVENT_LOG | パフォーマンスの問題を示している可能性のある条件がクエリオプティマイザによって特定された場合にアラートを記録 | ユーザー |
STL_BCAST | データをブロードキャストするクエリステップが実行されている間のネットワークアクティビティに関する情報を記録 | ユーザー |
STL_COMMIT_STATS | コミットのさまざまなステージのタイミングやコミットされるブロックの数など、コミットのパフォーマンスに関連するメトリックスを提供 | スーパーユーザー |
STL_CONNECTION_LOG | 認証の試みと、接続および切断をログに記録 | スーパーユーザー |
STL_DDLTEXT | システムで実行された以下の DDL ステートメントを取得 ・CREATE SCHEMA、TABLE、VIEW ・DROP SCHEMA、TABLE、VIEW ・ALTER SCHEMA、TABLE | 全てのユーザー |
STL_DIST | データを配布するクエリステップが実行されている間のネットワークアクティビティに関する情報を記録 | 全てのユーザー |
STL_DELETE | 削除を実行するステップをクエリについて分析 | 全てのユーザー |
STL_ERROR | クエリの実行中に発生するすべてのエラーを記録 | 全てのユーザー |
STL_EXPLAIN | 実行するために送信されたクエリの EXPLAIN プランを表示 | 全てのユーザー |
STL_FILE_SCAN | COPY コマンドによってデータをロードするときに Amazon Redshift が読み込んだファイルを返す | 全てのユーザー |
STL_HASH | ハッシュを実行するステップをクエリについて分析 | 全てのユーザー |
STL_HASHJOIN | ハッシュ結合を実行するステップをクエリについて分析 | 全てのユーザー |
STL_INSERT | 挿入を実行するステップをクエリについて分析 | 全てのユーザー |
STL_LIMIT | SELECT クエリ内で LIMIT 句が使用されるときに発生する実行ステップを分析 | 全てのユーザー |
STL_LOAD_COMMITS | データのロードを追跡またはトラブルシューティングするための情報を返す | 全てのユーザー |
STL_LOAD_ERRORS | すべての Amazon Redshift ロードエラーのレコードを表示 | 全てのユーザー |
STL_LOADERROR_DETAIL | COPY コマンドを使用したテーブルのロード中に発生したデータ解析エラーのログを表示 | 全てのユーザー |
STL_MERGE | マージを実行するステップをクエリについて分析 | 全てのユーザー |
STL_MERGEJOIN | マージ結合を実行するステップをクエリについて分析 | 全てのユーザー |
STL_NESTLOOP | ネステッドループ結合を実行するステップをクエリについて分析 | 全てのユーザー |
STL_PARSE | 文字列をロード用のバイナリ値に解析するクエリステップを分析 | 全てのユーザー |
STL_PLAN_INFO | 行のセットに関するクエリの EXPLAIN 出力を確認 | 全てのユーザー |
STL_PROJECT | 式を評価するために使用されるクエリステップの行が含まれる | 全てのユーザー |
STL_QUERY | データベースクエリに関する実行情報を返す | 全てのユーザー |
STL_QUERYTEXT | SQL コマンドのクエリテキストを取得 | 全てのユーザー |
STL_REPLACEMENTS | 無効な UTF-8 文字が COPY コマンドの ACCEPTINVCHARS オプションによって置き換えられたときのログを表示 | 全てのユーザー |
STL_RETURN | クエリに含まれるリターンステップの詳細を格納 | ユーザー |
STL_SAVE | クエリに含まれる保存ステップの詳細を格納 | ユーザー |
STL_S3CLIENT | 転送時間などのパフォーマンスメトリックスを記録 | 全てのユーザー |
STL_S3CLIENT_ERROR | スライスで Amazon S3 からファイルをロードするときに発生したエラーを記録 | 全てのユーザー |
STL_SCAN | テーブルをスキャンするステップをクエリについて分析 | 全てのユーザー |
STL_SESSIONS | ユーザーセッション履歴に関する情報を返す | 全てのユーザー |
STL_SORT | ORDER BY 処理などを使用する、ソートを実行するステップのクエリを表示 | 全てのユーザー |
STL_SSHCLIENT_ERROR | SSH クライアントに対して表示されるすべてのエラーを記録 | 全てのユーザー |
STL_STREAM_SEGS | ストリームと並行セグメントの間の関係をリスト表示 | 全てのユーザー |
STL_TR_CONFLICT | データベーステーブルのロック競合を認識し、解決するための情報を表示 | 全てのユーザー |
STL_UNDONE | 元に戻されたトランザクションに関する情報を表示 | 全てのユーザー |
STL_UNIQUE | SELECT リストで DISTINCT 関数が使用されているとき、あるいは UNION または INTERSECT クエリから重複が除去されるときに発生する実行ステップを分析 | 全てのユーザー |
STL_UNLOAD_LOG | アンロード処理の詳細を記録 | 全てのユーザー |
STL_USERLOG | データベースユーザーに対する次の変更の詳細を記録 ・ユーザーの作成 ・ユーザーの削除 ・ユーザーの変更(名前の変更) ・ユーザーの変更(プロパティの変更) | スーパーユーザー |
STL_UTILITYTEXT | データベースに対して実行された SELECT 以外の SQL コマンドを取得/システムで実行された SQL ステートメントのうち、次のサブセットを取得可能 ・ABORT、BEGIN、COMMIT、END、ROLLBACK ・CANCEL ・COMMENT ・CREATE、ALTER、DROP DATABASE ・CREATE、ALTER、DROP USER ・EXPLAIN ・GRANT、REVOKE ・LOCK ・RESET ・SET ・SHOW ・TRUNCATE | 全てのユーザー |
STL_VACUUM | バキュームされたテーブルの行およびブロックに関する統計を表示 | スーパーユーザー |
STL_WARNING | Amazon Redshift での予期しない出来事のうち、エラーを引き起こすほど深刻ではないもののログを表示 | 全てのユーザー |
STL_WINDOW | ウィンドウ関数を実行するクエリステップを分析 | 全てのユーザー |
STL_WLM_ERROR | すべての WLM 関連のエラーを発生時に記録 | 全てのユーザー |
STL_WLM_QUERY | WLM が扱うサービスクラス内で実行が試みられたクエリごとに、レコードが 1 件作成 | 全てのユーザー |
スナップショットデータの STV テーブル一覧
テーブル名 | 説明 | 参照可 | STV_ACTIVE_CURSORS | 現在開いているカーソルの詳細を表示 ユーザーから表示可能。 ユーザーは、自身が開いたカーソルのみを表示可能。 スーパーユーザーはすべてのカーソルを表示可能。 | 全てのユーザー | STV_BLOCKLIST | データベース内の各スライス、テーブル、または列で使用される 1 MB ディスクブロックの数が表示 | スーパーユーザー | STV_CURSOR_CONFIGURATION | カーソル設定の制約を表示 | スーパーユーザー | STV_EXEC_STATE | Amazon Redshift でアクティブに実行されているクエリおよびクエリ手順についての情報を取得 | ユーザー | STV_INFLIGHT | データベースで現在どのクエリが実行されているかを調べる | ユーザー | STV_LOAD_STATE | 実行中の COPY ステートメントの現在の状態についての情報を取得 | ユーザー | STV_LOCKS | データベース内のテーブルに対する現時点での更新をすべて表示 | スーパーユーザー | STV_PARTITIONS | Amazon Redshift のディスク速度の性能とディスクの利用状況を調べる | スーパーユーザー | STV_RECENTS | 現在アクティブなクエリや、最近データベースに対して実行されたクエリに関する情報を取得 | ユーザー | STV_SLICES | スライスからノードへの現在のマッピングを見る | ユーザー | STV_SESSIONS | Amazon Redshift のアクティブなユーザーセッションに関する情報を見る | ユーザー | STV_TBL_PERM | STV_TBL_PERM テーブルには、現在のセッション用にユーザーが作成した一時テーブルを含め、Amazon Redshift の永続テーブルに関する情報が表示 | スーパーユーザー | STV_TBL_TRANS | 現在メモリ内にある一時データベーステーブルに関する情報を取得 | スーパーユーザー | STV_WLM_CLASSIFICATION_CONFIG | WLM の現在の分類ルール | スーパーユーザー | STV_WLM_QUERY_QUEUE_STATE | サービスクラスのクエリキューの現在の状態を記録 | ユーザー | STV_WLM_QUERY_STATE | WLM に追跡されているクエリの現在の状態 | ユーザー | STV_WLM_QUERY_TASK_STATE | サービスクラスクエリタスクの現在の状態を表示 | ユーザー | STV_WLM_SERVICE_CLASS_CONFIG | WLM のサービスクラス設定を記録 | スーパーユーザー | STV_WLM_SERVICE_CLASS_STATE | サービスクラスの現在の状態を表示 | スーパーユーザー |
---|
システムビュー一覧
テーブル名 | 説明 | 参照可 | SVL_COMPILE | クエリの各クエリセグメントのコンパイル時間と位置を記録 | 全てのユーザー | SVV_DISKUSAGE | STV_TBL_PERM テーブルと STV_BLOCKLIST テーブルを結合して、SVV_DISKUSAGE システムビューを作成。データベースのテーブルに対するデータ割り当てに関する情報が含まれる | スーパーユーザー | SVL_QLOG | データベースに対して実行されたすべてのクエリのログが含まれる | ユーザー | SVV_QUERY_INFLIGHT | データベースで現在実行されているクエリを確認 | ユーザー | SVL_QUERY_REPORT | Amazon Redshift の STL システムテーブルのいくつかを UNION(結合)したものから SVL_QUERY_REPORT ビューを作成し、実行されたクエリステップについての情報を提供 | ユーザー | SVV_QUERY_STATE | 現在実行されているクエリの実行についての情報を表示。STV_EXEC_STATE テーブルのデータのサブセットが含まれる | ユーザー | SVL_QUERY_SUMMARY | クエリの実行についての全般的な情報を確認。SVL_QUERY_REPORT ビューからのデータのサブセットが含まれる。SVL_QUERY_SUMMARY の情報はすべてのノードからの情報の集計であることに注意 | ユーザー | SVL_STATEMENTTEXT | システムで実行されたすべての SQL コマンドの完全な記録を取得 | ユーザー | SVV_VACUUM_PROGRESS | 現在進行中のバキューム処理が終了するまでにかかる時間の予測を返す | スーパーユーザー | SVV_VACUUM_SUMMARY | STL_VACUUM テーブル、STL_QUERY テーブル、STV_TBL_PERM テーブルを結合し、システムがログ記録したバキューム処理についての情報を要約 | スーパーユーザー | SVL_VACUUM_PERCENTAGE | バキューム処理の実行後にテーブルに割り当てられるデータブロックのパーセントを示す | スーパーユーザー |
---|
システムカタログテーブル一覧
テーブル名 | 説明 | 参照可 | PG_TABLE_DEF | テーブルに関してユーザーに表示される情報のみを返す | "Amazon Redshift ユーザーは、標準の PostgreSQL カタログテーブルにアクセスできます"→ユーザー? |
---|
まとめ
以上、調査用に用意しておくAmazon Redshiftユーザーの環境の整え方に関するまとめでした。これらの内容を整理すると、以下のポイントに基づいて権限が限定されたユーザーを用意する(または用意して頂く)事で想定する情報は用意出来そうです。自らの管理する環境でもそうですし、お客様環境を調査する際に御用意頂くユーザーについてもこのラインに基づいたユーザーを作成頂く事で安全な調査が行えそうですね。
- 1.調査対象となるテーブルを予め特定しておく必要がある(必要最低限のテーブルに対するアクセス権限を付与させるため)
- 2.とりあえずはテーブルに対する参照権限(SELECT)だけあれば何とかなりそう(データベースやテーブルに余計な影響を与えないため)
- 3.システム系のテーブルやビューに対しても、アクセス範囲は絞られるが閲覧は可能(1,2の設定後に所定ユーザーでアクセスした内容であれば確認出来そう)
- 4.クエリの実行計画(EXPLAIN)についても、関連するテーブルへの(参照)権限があれば取得は可能
- 5.スーパーユーザーが対象となっているテーブルやビューはデフォルトでは参照不可。しかし参照が必要であればGRANT文で通常運用テーブルと同様に権限付与は可能
こちらからは以上です。