2012年12月13日

AWSでそこそこセキュアにPostgreSQLインスタンスを立ち上げる

(4/5追記)アクセス管理関連の脆弱性が発見されています。
バージョン9.2.3、9.1.8、9.0.12、8.4.16およびそれより前のバージョンをお使いの場合はアップグレードしてください。特にクラウド環境で利用する際にはご注意ください。



PostgreSQL Advent Calendar 2012(全部俺)のDay 13です。

クラウドが大流行中です。(個人的に)

いろいろ試したり、ちょっとデータを突っ込んで分析したり、といった用途に使う場合には、クラウド上に自分専用のPostgreSQLが動いていると何かと便利です。

PaaSサービスを使うのも良いのですが、IaaS上に自分でPostgreSQLをインストールした方が自由度は高くなりますので、今回はAmazon EC2上にPostgreSQLをインストールして、自分専用のサーバとして使う設定をしてみます。

なお、インターネット上をデータが流れる関係上、多少、セキュリティに配慮した設定を行おうと思います。(とは言っても、ポート番号を変えてSSL接続を行うだけですが・・)

前提として、インターネット上のサーバの任意のポートに対してTCP接続を張れることが必要です。ファイヤーウォールなどでネットワーク接続が制限されている場合にはこの方法は使えません。

■Amazon EC2でインスタンスを立ち上げる


まず、Amazon EC2でインスタンスを立ち上げます。

EC2のセットアップから説明していると非常に長くなるため詳細は省きますが、今回は以下の設定で立ち上げます。

リージョンは「APAC -Tokyo」として、「Amazon Linux AMI 2012.09」を起動します。アーキテクチャはとりあえず32ビットとします。
  • Instance Type : T1 Micro
  • Availability Zone : No Preference
  • Key Pair : Create a new Key Pair (または既存のものがあればそれを選ぶ)
セキュリティグループでは、SSHの接続と、PostgreSQLの接続のみを受け付ける設定を行います。PostgreSQLのポート番号は、デフォルトの「5432」ではなく、ここでは「16543」を使います。
  • Security Group : Create a new Security Group
  • Group Name : test-pgsql
  • Group Description : test-pgsql
    • Create a new rule : SSH
    • Source : 0.0.0.0/0 (または制限できるのであれば指定する)
    • Create a new rule : Custom TCP rule
    • Port range : 16543
    • Source : 0.0.0.0/0 (または制限できるのであれば指定する)
インスタンスを起動したら、ec2-userでログインします。
login as: ec2-user
Authenticating with public key "imported-openssh-key"

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2012.09-release-notes/
There are 4 security update(s) out of 33 total update(s) available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-152-167-242 ~]$ 
ログインしたら、まず yum update を行います。
[ec2-user@ip-10-152-167-242 ~]$ sudo su
[root@ip-10-152-167-242 ec2-user]# yum update
Loaded plugins: priorities, security, update-motd, upgrade-helper
Setting up Update Process
Resolving Dependencies
(...snip...)
  ruby-libs.i686 0:1.8.7.371-1.20.amzn1     tzdata.noarch 0:2012f-1.15.amzn1
  tzdata-java.noarch 0:2012f-1.15.amzn1     yum.noarch 0:3.2.29-30.24.amzn1

Complete!
[root@ip-10-152-167-242 ec2-user]#
次に、PostgreSQLをインストールする際に依存するパッケージをインストールします。今回は、libxsltとuuidが必要になりますので、これらをyumでインストールします。
[root@ip-10-152-167-242 ~]# yum install libxslt.i686 uuid.i686
Loaded plugins: priorities, security, update-motd, upgrade-helper
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package libxslt.i686 0:1.1.26-2.7.amzn1 will be installed
---> Package uuid.i686 0:1.6.2-11.16.amzn1 will be installed
(...snip...)
Installed:
  libxslt.i686 0:1.1.26-2.7.amzn1
  uuid.i686 0:1.6.2-11.16.amzn1

Complete!
[root@ip-10-152-167-242 ~]# 

■PostgreSQLをインストールする


次にPostgreSQLのRPMをインストールします。

Amazon Linux AMIはRed Hat Enterprise Linux 6系のようですので、RHEL6用のPostgreSQL 9.2のRPMパッケージをダウンロードします。

ダウンロード用のスクリプト dl.sh をGistに置きましたので、これを実行してPostgreSQLのRPMをダウンロードします。

https://gist.github.com/4273726
[root@ip-10-152-167-242 ~]# sh dl.sh
--2012-11-24 09:15:20--  http://yum.postgresql.org/9.2/redhat/rhel-6.3-i386/postgresql92-9.2.1-1PGDG.rhel6.i686.rpm
Resolving yum.postgresql.org... 98.129.198.114
Connecting to yum.postgresql.org|98.129.198.114|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 959964 (937K) [application/x-redhat-package-manager]
Saving to: “postgresql92-9.2.1-1PGDG.rhel6.i686.rpm”

100%[======================================>] 959,964      634K/s   in 1.5s

2012-11-24 09:15:22 (634 KB/s) - “postgresql92-9.2.1-1PGDG.rhel6.i686.rpm” saved [959964/959964]

(...snip...)

2012-11-24 09:15:48 (702 KB/s) - “postgresql92-test-9.2.1-1PGDG.rhel6.i686.rpm” saved [1275524/1275524]

[root@ip-10-152-167-242 ~]# ls *.rpm
postgresql92-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-contrib-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-debuginfo-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-devel-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-docs-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-libs-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-plperl-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-plpython-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-pltcl-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-server-9.2.1-1PGDG.rhel6.i686.rpm
postgresql92-test-9.2.1-1PGDG.rhel6.i686.rpm
[root@ip-10-152-167-242 ~]#
このうち、以下の5つのRPMをインストールします。
  • postgresql92-9.2.1-1PGDG.rhel6.i686.rpm
  • postgresql92-contrib-9.2.1-1PGDG.rhel6.i686.rpm
  • postgresql92-devel-9.2.1-1PGDG.rhel6.i686.rpm
  • postgresql92-libs-9.2.1-1PGDG.rhel6.i686.rpm
  • postgresql92-server-9.2.1-1PGDG.rhel6.i686.rpm
[root@ip-10-152-167-242 ~]# rpm -ivh postgresql92-9.2.1-1PGDG.rhel6.i686.rpm postgresql92-contrib-9.2.1-1PGDG.rhel6.i686.rpm postgresql92-devel-9.2.1-1PGDG.rhel6.i686.rpm postgresql92-libs-9.2.1-1PGDG.rhel6.i686.rpm postgresql92-server-9.2.1-1PGDG.rhel6.i686.rpm
warning: postgresql92-9.2.1-1PGDG.rhel6.i686.rpm: Header V4 DSA/SHA1 Signature, key ID 442df0f8: NOKEY
Preparing...                ########################################### [100%]
   1:postgresql92-libs      ########################################### [ 20%]
   2:postgresql92           ########################################### [ 40%]
   3:postgresql92-contrib   ########################################### [ 60%]
   4:postgresql92-devel     ########################################### [ 80%]
   5:postgresql92-server    ########################################### [100%]
[root@ip-10-152-167-242 ~]#

■データベースクラスタを初期化する


PostgreSQLのインストールが終わったら、データベースクラスタを初期化します。おなじみのinitdbコマンドの出番です。
[root@ip-10-152-167-242 ~]# su - postgres
-bash-4.1$ pwd
/var/lib/pgsql
-bash-4.1$ ls -F
9.2/
-bash-4.1$ /usr/pgsql-9.2/bin/initdb -D /var/lib/pgsql/9.2/data --no-locale -E UTF-8
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "C".
The default text search configuration will be set to "english".

fixing permissions on existing directory /var/lib/pgsql/9.2/data ... ok
(...snip...)

Success. You can now start the database server using:

    /usr/pgsql-9.2/bin/postgres -D /var/lib/pgsql/9.2/data
or
    /usr/pgsql-9.2/bin/pg_ctl -D /var/lib/pgsql/9.2/data -l logfile start

-bash-4.1$

■サーバの鍵と証明書を作成する


次にSSL接続用のサーバの鍵とサーバ証明書を作成します。
-bash-4.1$ openssl genrsa -out server.key 1024
Generating RSA private key, 1024 bit long modulus
.........................................++++++
....++++++
e is 65537 (0x10001)
-bash-4.1$ openssl req -new -key server.key -x509 -days 365 -out server.crt
(...snip...)
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Minato-ku
Organization Name (eg, company) [Default Company Ltd]:Uptime Technologies, LLC
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:ec2-54-248-9-93.ap-northeast-1.compute.amazonaws.com
Email Address []:nobody@uptime.jp
-bash-4.1$ ls -F
9.2/  server.crt  server.key
-bash-4.1$
サーバの公開鍵と証明書を作成したら、データベースクラスタのディレクトリに移動させます。
-bash-4.1$ chmod 600 server.*
-bash-4.1$ mv server.* 9.2/data/
-bash-4.1$ cd 9.2/data/
-bash-4.1$ ls -F
base/        pg_ident.conf  pg_serial/     pg_tblspc/    postgresql.conf
global/      pg_log/        pg_snapshots/  pg_twophase/  postmaster.opts
pg_clog/     pg_multixact/  pg_stat_tmp/   PG_VERSION    server.crt
pg_hba.conf  pg_notify/     pg_subtrans/   pg_xlog/      server.key
-bash-4.1$

■PostgreSQLにSSLの設定行い、サービスを起動する


postgresql.confファイルの中で以下の設定を有効にします。
listen_addresses = '*'
port = 16543
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
上記以外の設定(log_line_prefixなど)も必要に応じて行います。

次に、インターネットからの接続に対して、すべてSSL接続を要求するようにpg_hba.confの最後の行に以下を追加します。
hostssl all             all             0.0.0.0/0               password
そして、サービスを起動するスクリプトで設定するポート番号を変更するために、/etc/sysconfig/pgsql/postgresql-9.2 に以下を記述します。
PGPORT=16543
最後に、サーバ起動時に自動的に起動されるようにサービススクリプトを設定して、PostgreSQLサービスを起動します。
[root@ip-10-152-167-242 ~]# /sbin/chkconfig postgresql-9.2 on
[root@ip-10-152-167-242 ~]# /sbin/chkconfig --list postgresql-9.2
postgresql-9.2  0:off   1:off   2:on    3:on    4:on    5:on    6:off
[root@ip-10-152-167-242 ~]# /etc/rc.d/init.d/postgresql-9.2 start
Starting postgresql-9.2 service:                           [  OK  ]
[root@ip-10-152-167-242 ~]#

■ユーザを作成し、パスワードを設定する


PostgreSQLを起動したら、ユーザの作成を行います。

ここでは、データベース作成権限のある一般ユーザとして snaga というユーザを作成しています。--pwpromptオプションも指定して、パスワードの設定も行います。
[root@ip-10-152-167-242 ~]# su - postgres
-bash-4.1$ createuser -p 16543 --createdb --encrypted --pwprompt snaga
Enter password for new role:
Enter it again:
-bash-4.1$
ユーザの作成が完了したら、サーバ側のセットアップは完了です。

■pgAdminIIIから接続する


それでは、手元のクライアントからインターネットを経由して、PostgreSQLサーバに接続してみます。

とは言え、特に変わった設定は不要で、接続先のホストにEC2のホスト名を指定して、Portに先ほどの16543を指定するだけです。


接続に成功すれば、赤い「×」アイコンが消えて、サーバの情報を取得できるようになります。ここで、右側のペインに表示されている「暗号」の項目が「SSL暗号化」となっていれば、SSL接続できていることになります。


なお、サーバ設定のダイアログでSSLを「無効」とすると接続できなくなります。「必ずSSL接続がされている」ことを確認するためにも、この確認もしておくと良いでしょう。

■まとめ


今回はAmazonのEC2上でPostgreSQLを立ち上げて、安全に接続する方法を解説してきました。

自分でいろいろと試すためにも、クラウド上で自由にPostgreSQLを利用できると非常に便利です。ぜひ、クラウドの利便性とセキュリティをバランスさせながら、うまく使ってみていただければと思います。

ではでは。

0 件のコメント:

コメントを投稿