今日では、企業や医療機関、自治体などの組織において、情報セキュリティ対策は慎重に取り扱うべき重要な課題です。特に、個人情報を含む可能性のあるデータベースについては、より一層の配慮が求められます。
PostgreSQL は、クライアント認証やデータベースオブジェクトのアクセス制御によって、不正なユーザからデータを保護する仕組みを備えています。しかし、OSファイルレベルでの暗号化には対応しておらず、ファイルやディスクの物理的な盗難への対策としては、追加の暗号化モジュールをインストールする必要があるなど、一定の運用負荷が伴います。
PowerGres Plus では、コミュニティ版 PostgreSQL にはない独自機能として、透過的データ暗号化(TDE)を利用できます。この機能は PowerGres Plus に組み込まれているため、追加インストールの手間が不要であり、PowerGres Administration Tool からのGUI操作にも対応しているため、コンソール画面に不慣れであっても容易に管理ができます。また、データベースに格納するデータはもちろん、バックアップデータやトランザクションログ、一時ファイルまで暗号化できます。 しかも、データは自動的に暗号化、復号されるため、ユーザやアプリケーションが暗号化を意識する必要はありません。
本稿では、このPowerGres Plus の独自機能である透過的データ暗号化を用いて、よりセキュアなデータベース管理の方法をご紹介します。
透過的データ暗号化は、指定したテーブル空間内の全てのユーザデータを暗号化します。暗号化されたテーブルやインデックスに対する操作によって出力されるトランザクションログや一時ファイルも自動的に暗号化されます。したがって、クライアント側は暗号化キーの管理や暗号化 / 復号の処理を意識する必要はありません。また、物理コピーによるバックアップデータも、暗号化されたデータは暗号化されたままとなっています。
また、透過的データ暗号化では、ディスク I/O が発生するときのみ、暗号化/復号が実施されますので、バッファ・キャッシュ内のデータアクセスではオーバーヘッドがありません。
テーブルやインデックス、WAL に格納されるデータの大きさは暗号化しても変わりません。 そのため、追加の見積もりやディスクは不要です。
さらに透過的データ暗号化は、ストリーミングレプリケーションを組み合わせて使うことも可能です。 プライマリサーバで暗号化されたデータと WAL は、暗号化されたままスタンバイサーバに転送され格納されます。
透過的データ暗号化では、二層のキーストアファイルによってデータを保護しています。暗号化されたテーブル空間には、その中の全てのデータを暗号化 / 復号するキーストアファイルがあります。このキーストアファイルはデータベースクラスタに 1 つだけ作成されるマスター暗号化キーによって暗号化されています。マスター暗号化キーは DB 管理者が指定したパスフレーズに基づいて暗号化され、キーストアファイルに保存されます。
PowerGres および PowerGres Plus 向けウェブベースの GUI 管理ツールであるPowerGres Administration Tool では、リモートホスト上のデータベースでも OS にログインすることなく、PowerGres Plusの透過的データ暗号化をウェブブラウザで簡単に管理することができます。透過的データ暗号化の管理を行う上で必要なすべての操作を、わかりやすいGUIで完結できることは、PowerGres Plusの大きな魅力の一つです。
今回の解説では、CLIのコマンドでの手順に加え、こうしたPowerGres Administration Tool での手順も併せてお伝えします。
透過的データ暗号化を使用するには、まずキーストアを作成し、任意のパスフレーズからマスター暗号化キーを設定する必要があります。
キーストアの作成、及びマスター暗号化キーの設定と聞くと難しそうな手順に思えますが、PowerGres Plus ではいずれの手順も、専用のシンプルなコマンド実行による方法と、Administration ToolによるわかりやすいGUIによる方法がサポートされているため、初めてでも簡単に設定できます。
なお、ここで設定する任意のパスフレーズは、今後キーストアをオープンするために使われます。ここで指定したパスフレーズを忘れてしまうと、暗号化されたデータにはアクセスできなくなります。 忘れたパスフレーズを取り戻したり、データを復号する方法はありませんので、決してパスフレーズを忘れないようにしてください。
また、重要なセキュリティのポイントであるマスター暗号化キーはこのパスフレーズによって保護される仕様のため、パスフレーズには短く単純で推測されやすい文字列を指定しないよう注意してください。
それでは実際に透過的データ暗号化を設定してみましょう。
はじめに、CLIでマスター暗号化キーの設定を行います。
まず、postgresql.conf の keystore_location パラメータに、キーストアを格納するディレクトリを設定します。 これにはデータベースクラスタごとに異なる場所を指定する必要があります。 設定後、データベースサーバを再起動してください。
(凡例) keystore_location = '《キーストアを格納するディレクトリ》'
ここではキーストア格納ディレクトリを「/var/lib/pgsql/16/keystore」とします。
(例1:postgresql.confでkeystore_locationを設定) keystore_location = '/var/lib/pgsql/16/keystore'
(例2:OSコマンドラインでデータベースサーバを再起動) $ pg_ctl restart -D /var/lib/pgsql/16/data
次に、下のような SQL 関数を実行してマスター暗号化キーを設定します。 これはデータベースのスーパーユーザで実行する必要があります。
(凡例)
SELECT pgx_set_master_key('《パスフレーズ》');
このpgx_set_master_key関数実行時に「keystore.ks」ファイルがキーストア格納ディレクトリに作成されます。このファイルには、関数実行時に生成されたマスター暗号化キーが、指定のパスフレーズで暗号化したうえで格納されます。なお、セキュリティ対策として、キーストアを格納したディレクトリ、および keystore.ksは、データベースサーバを起動するユーザのみがアクセスできるように保護してください。
それでは、ここでパスフレーズを「passphrase」として、実行例を示します。
(例3:psqlでスーパーユーザとしてpostgresデータベースに接続し実行)
$ psql -d postgres -U postgres
=# SELECT pgx_set_master_key('passphrase');
pgx_set_master_key
--------------------
(1 行)
次に、管理ツールでのマスター暗号化キーの設定を行う手順を紹介します。
まず、「透過的データ暗号化」画面にアクセスするには、メニューの「透過的データ暗号化」をクリックします。
マスターキーが存在しない場合には、マスターキーの作成が開始されます。
従って、サーバ作成後にマスターキーを設定していない状態で、初めて「透過的データ暗号化」画面にアクセスする際には、次のマスターキー作成画面に遷移します。
マスターキーを作成するのに必要な情報を入力し、「作成」ボタンをクリックします。
例として、ここでは以下のように入力します。
キーストアディレクトリ:/var/lib/pgsql/16/keystore パスフレーズ:passphrase
「作成」ボタンをクリックすると、サーバを再起動するかを確認するダイアログが表示されます。
「OK」ボタンをクリックします。
マスターキーの作成が完了すると、完了したことを表すメッセージが表示されます。
マスターキーの作成直後には、キーストアはオープンされます。
以上でキーストアの作成と、マスター暗号化キーの設定の手順は完了です。
暗号化テーブル空間を作成したり暗号化データにアクセスするには、キーストアをオープンしておく必要があります。 キーストアをオープンすると、マスター暗号化キーがデータベースサーバのメモリにロードされ、暗号化と復号に利用できるようになります。ですので、透過的データ暗号化の機能を利用する場合は、基本的にデータベースサーバを起動するたびにキーストアをオープンすることになります。
キーストアをオープンする方法は二通りで、手動のコマンドでオープンを行う方法と、自動オープンキーストアを使用する方法があります。どちらの方法も、CLI・管理ツールのいずれからでも操作可能です。
まずは手動でキーストアをオープンする方法です。
スーパーユーザが次のように SQL 関数を実行します。
SELECT pgx_open_keystore('《パスフレーズ》');
ここではキーストアの作成時に指定したパスフレーズを指定してください。
(例4:psqlでスーパーユーザとしてpostgresデータベースに接続し実行)
$ psql -d postgres -U postgres
=# SELECT pgx_open_keystore('passphrase');
pgx_open_keystore
-------------------
(1 行)
なお、データベースサーバの起動時にリカバリが実行される場合、上記の方法ではデータベースサーバを起動できません。 なぜなら、暗号化された WAL を復号する必要があるためです。 この場合には、pgx_open_keystore 関数を実行する代わりに、pg_ctl startでの起動時に --keystore-passphrase オプションを指定し実行します。 これはパスフレーズ入力を促すプロンプトを表示します。
(例5:pg_ctl startでの起動時に --keystore-passphrase オプションを指定し実行) $ pg_ctl start --keystore-passphrase パスフレーズを入力してください: #パスフレーズ(ここではpassphrase)を入力 サーバーの起動完了を待っています.... (中略) 完了 サーバー起動完了
次に自動オープンキーストアを使用する方法を行っていきます。
自動オープンキーストアを使用すると、パスフレーズを入力することなく、データベースサーバの起動時に自動的にキーストアをオープンできます。なお、自動オープンキーストアは、それが作成されたコンピュータでのみオープンします。
キーストアの自動オープンを有効にするには、次のようにコマンドを実行します。
(凡例) pgx_keystore --enable-auto-open 《キーストアを格納したディレクトリ》/keystore.ks
自動オープンを有効にすると、元のキーストアと同じディレクトリに自動オープン・キーストアファイルが作成されます。自動オープンキーストアのファイル名はkeystore.aksです。
このファイルが存在すると、データベースサーバの起動時に、キーストアをオープンするためのパスフレーズを入力する必要はありません。
このkeystore.aksは、keystore.ks の復号された内容を難読化したコピーですので、セキュリティを意識する必要があります。キーストアを格納したディレクトリ、およびkeystore.ksと同様に、keystore.aksもデータベースサーバを起動するユーザのみがアクセスできるように保護してください。
では実際の例として、先ほどの手順でキーストアを格納したディレクトリ「/var/lib/pgsql/16/keystore」を指定して、自動オープンを有効化してみましょう。
(例6:自動オープンの有効化) $ pgx_keystore --enable-auto-open /var/lib/pgsql/16/keystore/keystore.ks パスフレーズを入力してください: キーストアの自動オープンが有効になりました
キーストアの自動オープンを無効にする場合は、keystore.aks ファイルを削除してください。
(例7:自動オープンの無効化) $ rm /var/lib/pgsql/16/keystore/keystore.aks
次に、管理ツールでキーストアのオープンを行う手順を紹介します。
キーストアのオープンを行うには、メニューの「透過的データ暗号化」をクリックします。
メニューの「透過的データ暗号化」をクリックすると、キーストアがオープンされていない場合には、「キーストアをオープン」画面が表示されます。
キーストアのパスフレーズを入力し、「オープン」ボタンをクリックします。
ここでは先ほど設定したパスフレーズ「passphrase」を入力します。
キーストアのオープンが完了すると、完了したことを表すメッセージが表示されます。
次に、自動オープンキーストアの有効化の手順を行っていきます。
「透過的データ暗号化」を開くと、デフォルトでは以下のように自動オープンキーストアは無効になっています。自動オープンキーストアを有効にするには、「自動オープンキーストアを有効化」ボタンをクリックします。
なお、すでに有効になっている場合には「自動オープンキーストアを無効化」ボタンが表示されます。無効化の際はパスフレーズの入力などはなく、ボタンをクリックするのみで完了します。
「自動オープンキーストアを有効化」ボタンをクリックすると、「自動オープンキーストアを有効化」画面が表示されます。
キーストアのパスフレーズを入力し、「有効化」ボタンをクリックします。
自動オープンキーストアの有効化が完了すると、完了したことを表すメッセージが表示されます。
以上でキーストアのオープンの手順は完了です。
暗号化テーブル空間を作成するには、事前にキーストアがオープンされている必要があります。前章までの手順で事前にキーストアをオープンしてください。
CLIによる手順では、まず暗号化するテーブル空間を作成する前段階として、実行時パラメータに暗号化アルゴリズムを設定します。 暗号化アルゴリズムとして、キー長が 128 または 256 ビットの AES を使用でき、以下のようなSQL文で設定を行います。
SET tablespace_encryption_algorithm = '《暗号化アルゴリズム名》';
有効な値は AES128、AES256、または none(デフォルト)です。 none を指定した場合、もしくは実行時パラメータの設定を省略した場合は、テーブル空間の作成時に暗号化は行われません。なお、スーパーユーザのみがこの設定を変更できます。
たとえば、暗号化アルゴリズムとしてキー長が 128 ビットの AES を用いる場合、以下のように設定します。
(例8―1:以降に作成するテーブル空間の暗号化アルゴリズムをAES128に指定) =# SET tablespace_encryption_algorithm = 'AES128'; SET (例8-2:現在指定されている暗号化アルゴリズムの確認) =# SHOW tablespace_encryption_algorithm; tablespace_encryption_algorithm --------------------------------- AES128 (1 行)
次に、暗号化するテーブル空間を作成します。
例えば、secure_tablespace という名前のテーブル空間を作成するには、次のようにSQLを実行します。ここではテーブル空間を作成するディレクトリとして「/var/lib/pgsql/16/secure_tablespace_dir」を事前に作成しておくこととします。
(例9:暗号化するテーブル空間を作成) =# CREATE TABLESPACE secure_tablespace LOCATION '/var/lib/pgsql/16/secure_tablespace_dir'; CREATE TABLESPACE
特定のテーブル空間のみを暗号化し、同一セッション上でその後に作成するテーブル空間は暗号化をしない設計とする場合などは、暗号化テーブル空間の作成後に、以下のように明示的にnoneを指定するとよいでしょう。
(例10:以降に作成するテーブル空間は暗号化しないように指定) =# SET tablespace_encryption_algorithm = 'none'; SET
注意点として、テーブル空間 pg_default および pg_global を暗号化することはできません。
はじめに「テーブル空間」画面にアクセスします。
メニューの「データベースオブジェクト」内の「テーブル空間」をクリックしてください。
「テーブル空間」画面にアクセスすると、テーブル空間の一覧が表示されます。
暗号化アルゴリズムがnoneと表示されている場合、テーブル空間が暗号化されていない状態を表します。
新しいテーブル空間を作成するには、「新しいテーブル空間」ボタンをクリックします。
「新しいテーブル空間」ボタンをクリックすると、「新しいテーブル空間」画面が表示されます。作成するテーブル空間の属性を入力し、「作成」ボタンをクリックします。
例として、ここでは以下のように設定します。
テーブル空間名:secure_tablespace 場所:/var/lib/pgsql/16/secure_tablespace_dir 暗号化アルゴリズム:AES128 所有者:postgres
テーブル空間の作成が完了すると、完了したことを表すメッセージが表示され、作成したテーブル空間が一覧に追加されます。
作成したテーブル空間では暗号化アルゴリズムとしてAES128が指定され、テーブル空間が暗号化されていることがわかります。
以上でテーブル空間の暗号化手順は完了です。
暗号化テーブル空間に作成されたデータベースやリレーションは、自動的に暗号化されます。
また、暗号化されたデータベース内に作成されたリレーション(テーブルやインデックス)も、自動的に暗号化されます。
なお、暗号化されたデータベースでは、システムカタログも暗号化されるので、ユーザ定義関数のソースコードも保護されます。
暗号化テーブル空間にテーブルやインデックスを作成します。まず、リレーション作成時にTABLESPACE句で暗号化テーブル空間を指定してください。
例えば、暗号化テーブル空間に新規テーブルを作成する場合は、以下のように行います。
(例11:リレーション作成時に暗号化テーブル空間を指定) =# CREATE TABLE my_table (i int, t text) TABLESPACE secure_tablespace; CREATE TABLE
TABLESPACE句を省略したい場合は、事前にdefault_tablespaceに暗号化テーブル空間を指定した状態で新規リレーションを作成してください。
(例12:作成時にはテーブル空間を明示せず、デフォルトテーブル空間を使用) =# SET default_tablespace = 'secure_tablespace'; SET =# CREATE TABLE my_table_2 (i int, t text); CREATE TABLE
一時テーブルを暗号化する場合も同様です。 TABLESPACE句を明示的に指定するか、または temp_tablespaces パラメータに暗号化テーブル空間を列挙し、CREATE TEMPORARY TABLE を実行してください。
暗号化したテーブル空間にデータベースを作成し、データを挿入していきます。
データベースの作成は「データベース」画面から行います。
「データベース」画面にアクセスするには、メニューの「データベースオブジェクト」内の「データベース」をクリックします。
「データベース」画面にアクセスすると、データベースの一覧が表示されます。
新しいデータベースを作成するには、「新しいデータベース」ボタンをクリックします。
「新しいデータベース」ボタンをクリックすると、「新しいデータベース」画面が表示されます。
作成するデータベースの属性を入力し、「作成」ボタンをクリックします。
例として、ここでは以下のように設定します。テーブル空間に指定するsecure_tablespaceは、先ほどの手順で作成した暗号化テーブル空間です。
データベース名:securedb 所有者名:postgres エンコーディング:UTF8 テーブル空間:secure_tablespace
なお、デフォルトではテーブル空間にpg_defaultテーブル空間が指定されています。このpg_defaultテーブル空間をはじめ、テーブル空間に非暗号化テーブル空間が指定された場合、データベースの暗号化は行われないため注意してください。
データベースの作成が完了すると、完了したことを表すメッセージが表示され、作成したデータベースが一覧に追加されます。
securedbデータベースが追加されていることがわかります。
なお、Administration ToolはCLIと同様に「メンテナンス作業」→「SQL問い合わせの実行」からSQLを発行することが可能です。
先ほど紹介したCLI手順のSQLに従って、テーブルの作成を行ってください。
PowerGres Plus 固有のシステムビューpgx_tablespaceは、各テーブル空間が暗号化されているかどうか、および暗号化アルゴリズムについての情報を示します。次のような SQL 文を実行することで、どのテーブル空間が暗号化されているかを知ることができます。
(例13―1:pgx_tablespaceビューの取得)
=# SELECT spcname, spcencalgo FROM pg_tablespace AS ts JOIN pgx_tablespaces AS tsx ON ts.oid = tsx.spctablespace;
(例13―2:pgx_tablespaceビューの出力例)
spcname | spcencalgo
-------------------+------------
pg_default | none
pg_global | none
secure_tablespace | AES128
(3 行)
PowerGres Administration Toolでは、「テーブル空間」画面のテーブル空間一覧から暗号化アルゴリズムを確認することで、どのテーブル空間が暗号化されているかを知ることができます。
次に、暗号化テーブル空間にデータベースを作成し、データを挿入していきます。これらの手順は、透過的データ暗号化を利用しない場合と何も変わりはありません。なお、前述の通りデータベース作成時に暗号化テーブル空間を指定していた場合は、データベース内に挿入されたデータは意識せずとも暗号化されます。
ここからデータが暗号化されていることを直接確認します。以降は、CLI(コマンドライン)で実行してください。
ここでは、先ほど暗号化テーブル空間に作成したテーブルmy_tableにデータを挿入します。
(例14:暗号化テーブルへのデータ挿入) =# INSERT INTO my_table VALUES (123, 'onetwothree'); SELECT * FROM my_table; INSERT 0 1 i | t -----+------------- 123 | onetwothree (1 行)
my_tableのテーブルデータが格納されているファイルを確認してみましょう。
PostgreSQL の組み込み関数である pg_relation_filepath() でテーブルデータが格納されているファイルパスを特定し、ファイルを読み込みます。
(例15:テーブルデータ格納ファイルのパス特定)
=# SELECT pg_relation_filepath('my_table');
pg_relation_filepath
-----------------------------------------
pg_tblspc/24587/PG_16_202307071/5/24588
(1 行)
上で特定したファイルのバイナリデータを確認します。
ここではhexdumpコマンド(ファイルの中身を16進数で表示するコマンド)を用いてファイルの中身を見てみましょう。
(例16:暗号化テーブルのファイルのバイナリデータを確認) $ hexdump -C /var/lib/pgsql/16/secure_tablespace_dir/PG_16_202307071/5/24588 | tail 00001f70 8a 43 65 34 0a b2 f4 0a 3a 56 ab 04 9a f6 de a7 |.Ce4....:V......| 00001f80 2b 12 00 8e 26 cc cd 41 39 2a a8 1c 8d 46 aa bb |+...&..A9*...F..| 00001f90 e8 c1 f9 22 f4 ea 4a 91 ed 21 fb 1d d5 11 2d 15 |..."..J..!....-.| 00001fa0 01 ff d9 05 7d 46 15 0e c1 5d f1 5d d2 a7 d6 f4 |....}F...].]....| 00001fb0 e2 ba e1 77 a0 ce ba 1d bb 71 03 75 42 26 d3 06 |...w.....q.uB&..| 00001fc0 ad 6f 60 8f bd 8f f3 4e e1 48 ca 9f ea e3 28 5f |.o`....N.H....(_| 00001fd0 f6 17 59 45 40 b1 ac 6c 7d ea 86 97 ac f9 71 78 |..YE@..l}.....qx| 00001fe0 f9 cb 09 2c 4b e0 bb c4 59 15 e9 c6 9b 77 5d f6 |...,K...Y....w].| 00001ff0 4a e7 c5 fb dd 28 29 8b c4 75 8c 54 bf a2 27 9a |J....()..u.T..'.| 00002000
上がmy_tableの中身です。カラムtに入力した文字列「onetwothree」は暗号化されており、特定することができません。
以下はmy_tableテーブルと同一のデータを暗号化せずに挿入したテーブルの中身です。
ここではカラムtに入力した文字列「onetwothree」は暗号化されておらず、ファイルを覗くことで確認できてしまいます。
(例17:暗号化していないテーブルのバイナリデータを確認)
$ hexdump -C /var/lib/pgsql/16/data/base/5/32768 | tail
00000000 00 00 00 00 f8 20 5f 01 00 00 00 00 1c 00 d8 1f |..... _.........|
00000010 00 20 04 20 00 00 00 00 d8 9f 50 00 00 00 00 00 |. . ......P.....|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001fd0 00 00 00 00 00 00 00 00 f8 02 00 00 00 00 00 00 |................|
00001fe0 00 00 00 00 00 00 00 00 01 00 02 00 02 09 18 00 |................|
00001ff0 7b 00 00 00 19 6f 6e 65 74 77 6f 74 68 72 65 65 |{....onetwothree|
00002000
以上が実際の透過的データ暗号化の手順と、暗号化されたデータが実際にどのように記録されているかの確認となります。
今回は PowerGres Plus の透過的データ暗号化機能についての解説でした。
透過的データ暗号化は、クライアント側が暗号化 / 復号を意識することなく手軽に使えるメリットがあります。また、オーバーヘッドもほとんどありません。PowerGres Plus を使って、手軽な GUI でセキュアな DB 管理をぜひともお試しください。