セキュリティ
データベースのセキュリティ対策は、データベースが保持する情報の機密性、整合性、可用性を確保し、不正アクセスやデータ損失などのセキュリティインシデントを最小限に抑える必要があります。
データベースのセキュリティで考慮すべきは以下になります。
- (1) アクセス制御
クライアントからデータベースへの接続方法やデータベースのユーザー認証(権限管理やロール管理)のアクセス制御などです。
TCPで接続する場合は、SSL・IP制限・ロール制限など(pg_hba.conf)を設定します。
ロール管理では、GRANT,REVOKEなど最小限必要な権限を設定します。 - (2) データ暗号化
データベース接続時のデータの転送中のデータ暗号ややデータを保存したときにのデータ暗号化などです。
データが不正アクセスされた場合でも最小限のデータ流失になるようにします。 - (3) セキュリティポリシー
データベースには適切なセキュリティポリシーが必要です。
パスワードポリシー、アクセス制御ポリシー、監査ポリシーなどがあります。 - (4) ログ管理
データベースアクセスや変更に関するログを管理する必要があります。
ログを適切に管理することで不正アクセスの検知やセキュリティインシデントを実施できます。
それにより、監査ログとしても使用でき、定期的に監査することも必要です。 - (5) 脆弱性対策
DBMSなどで脆弱性が見つかるとその攻撃を受けてデータ流出する恐れがあります。
そのため、セキュリティ関連のアップデートは適時適用してゼロデイ攻撃などの対策が必要です。 - (6) 物理マシンの管理
クラウドで利用している場合には対象ではありませんが、物理マシンにDBMSをインストールしている場合にはその管理が必要です。
サーバルームやデータセンターに設置している場合にはそこへのアクセス制限やUSB接続の無効かやディスクの暗号化など物理マシンが盗難されてもデータを流出しない仕組みづくりが必要です。 - (7) 災害対応
クラウドやデータセンターに物理マシンが設置されていても設置しているリージョンで地震などの災害が発生するとデータベースの継続利用が困難になったり、データ消失が起こる場合があります。
ディザスタリカバリとして、地理的に離れたリージョンの物理マシンにレプリケーションやバックアップを検討します。
データベースの継続利用する場合には自動で切り替わる構成も検討します。
インテグリティ
インテグリティとは、データの整合性や信頼性を確保することです。
セキュリティの一環であり、データが予期しない状態で保持されないことを目的とします。
データベースのインテグリティでは次の方法があります。
- (1) データベース設計
データベース設計で正規化などの手法を用いてデータを効果的に構造化し、データ冗長性を避けることが重要です。
正規化が正しく行われていれば、データの不整合は起こりずらくなります。 - (2) 制約(Constraints)
主キー制約や外部キー制約が適正に行われているかを確認します。
適正に設定することで、データの整合性が維持されて、データの不足や不整合が起こりずらくなります。 - (3) トランザクション制御
トランザクション制御を適正使用しているかを確認します。
トランザクションについては、トランザクションとロックを参照してください。
トランザクション制御が適正に行われていれば、データの不整合は起こりずらくなります。 -
(4) ログ管理
セキュリティのログ管理と同じく、データベースアクセスや変更に関するログを管理します。
ログ管理されていることで、人的ミス・外部攻撃・プログラムバグなどデータが意図しない理由で改竄・削除されたりしていないか追跡できます。
PostgreSQLでのセキュリティ対応
PostgreSQLでのセキュリティ対応について記述します。
「pg_hba.conf」で設定することが可能で、初期設定ではローカルからの接続のみが可能になっています。
これであれば、OSにログインできない限りはアクセスできませんが、環境によってはネットワーク経由でのアクセスが必要になったりします。
その場合、ROLEにアクセス可能なデータベースなどを適正設定し、接続タイプを「hostssl」の設定をすることで、セキュアな接続になりデータ盗聴の対策にもなります。
SSL証明書なども確認できます。
以下が、「pg_hba.conf」の中身で最初(Local、host)が接続タイプになります。
次(postgres,all)がデータベースで次(user,all)がユーザになります。
その次(空白、127.0.0.1)がアクセス可能なIPアドレスで、最後が認証方式(trustは許可)です。
[pg_hba.conf]
# "local" is for Unix domain socket connections only
Local postgres user trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
また、データベースのデータでパスワードなどは暗号化して参照させたくない運用が考えられます。
その場合、contrib/pgcryptoなどの関数を使用することで暗号化したデータを保存することができます。
PostgreSQLで考えられるセキュリティに次のことが考えられます。
1. クライアント認証
2. 通信経路暗号化
3. データ暗号化
4. ログ
【1. クライアント認証】
クライアントからPostgresに通信するときに誰もがアクセスできてしまうと不正な人物がアクセスされ情報漏えいやデータ破損などの恐れがあります。
クライアント毎に認証を設定することでその対策が行えます。
データベースクラスタ(/var/lib/pgsql/9.6/data)内のpg_hba.confがクライアント認証の設定ファイルです。
設定方法は、TYPE、DATABASE、USER、ADDRESS、METHODを区切って記載します。
各設定方法の詳細を次に記載いたします。
[TYPE]
local
→Unixドメインのソケット通信
host
→平分またはSSLでの通信
hostssl
→SSLオンリー通信
hostnossl
→平分オンリー通信
[DATABASE]
all
→全てのデータベース
sameuser
→接続ユーザと同じ名前のデータベース
samerole
→接続ロールと同じ名前のデータベース
replication
→レプリケーション専用
データベース名
→指定したデータベース
[USER]
all
→全てのユーザ
ロール名またはグループ名
→指定したロールまたはグループ名(+またはカンマで区切って複数設定可能)
[ADDRESS]
IPv4またはIPv6アドレス
→接続元のIPアドレスを指定します。(prefix長での範囲指定可能)
[METHOD]
trust
→無条件で許可
reject
→無条件で拒否
md5
→パスワード認証(md5ハッシュで比較)
password
→パスワード認証(平文)
cert
→SSL証明書にて認証
認証方式
→idnent,ldap、radius、sspi、gss、pam、peerなどの外部認証
192.168.0.0/24の全てのネットワークからSSLのみ接続を許可する場合は次の様に記載します。
ssl all all 192.168.0.0/24 trust
【2. 通信経路暗号化】
クライアントからPostgresにはTCPで通信しますが、標準の設定では通信は平文のためデータが傍受されてしまうと情報漏えいが発生いたします。
PostgreSQLにはSSLを利用して暗号化した通信を行うことで対策になります。
※SSLで通信する場合、クライアント・サーバのOSに事前にOpenSSLが必要になります。
インストール跡もPostgresの設定で、SSLのサポートを有効にする必要があります。
また、SSLを利用する場合、SSL証明証が必要になります。
SSL証明書は次のファイルに保存します。
サーバ証明書
データベースクラスタ(/var/lib/pgsql/9.6/data)/server.crt
サーバ秘密鍵
データベースクラスタ(/var/lib/pgsql/9.6/data)/server.key
SSL証明書を利用する場合、Postgresの設定ファイルを次のように修正します。
[postgresql.conf]
⇒ssl = on
[pg_hba.conf]
hostssl all all 0.0.0.0/0 md5
証明書の作成方法は以下になります。
1. データベースクラスタに移動
# cd /var/lib/pgsql/9.6/data
2.OpenSSLでRSAの秘密鍵を作成
# openssl genrsa 2048 > server.key
※2048はビット数
3.OpenSSLでCSRを作成
# openssl req -new -key server.key > server.csr
4.OpenSSLで証明書を作成
# openssl x509 -days 36500 -req -signkey server.key < server.csr >
server.crt
※36500は有効期限(この場合100年)
5.作成したファイルの所有権・グループを変更
# chown postgres:postgres server.*
6.server.keyのアクセス権限変更
# chmod 600 server.key
[3. データ暗号化]
データベース内のデータを暗号化するにはcontribモジュールの1つであるpgcryptoを利用することで対応可能です。
詳細はこちらでご確認ください。
※conntribモジュールがインストールされている前提で記載いたします。
次のコマンドを実行します。(DB名は利用者のデータベース名)
#psql -f /usr/pgsql-9.6/share/extension/pgcrypto--1.3.sql [DB名]
postgres=# CREATE EXTENSION pgcrypto;
postgres=# select digest('test','MD5')
postgres-# ;
digest
------------------------------------
\x098f6bcd4621d373cade4e832627b4f6
ハッシュ関数一覧を次に記載します。
digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea
hmac(data text, key text, type text) returns bytea
hmac(data bytea, key text, type text) returns bytea
crypt(password text, salt text) returns text
gen_salt(type text [, iter_count integer ]) returns text
pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea
pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns
bytea
pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text
pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns
bytea
pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea
pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns
bytea
pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]])
returns text
pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text
]]) returns bytea
データの暗号化とは違うのですが、「データチェックサム」をPostgreSQLで利用可能です。
利用するとPostgreSQLのデータブロックで破損した場合、検出します。
データベースクラスタ作成時のコマンドであるinitdbにオプションを付けるとデータチェックサムが有効になります。
チェックサムはデータベースクラスタ全体ではなく、データをブロックに書き出す時に行います。
オプションは「-k」または、「--data-checksums」です。
※後から設定を変更することはできないので注意が必要です。
※データベースクラスタ全体を行いたい場合、OS側で行う必要があります。
※pg_controldataで確認することができます。