自己署名証明書の作成と HTTPS 対応

自己署名証明書(オレオレ証明書)を作成して SSL/TLS の暗号化通信を可能にします。

検証環境

  • CentOS 7.3
  • OpenSSL 1.0.1e
  • Nginx 1.12.2

自己署名証明書の作成

※ 今回扱うファイル名が紛らわしいため先に名前を定義します。

  • server.key : 秘密鍵 (CSR 作成, 署名兼用)
  • server.csr : CSR (証明書署名要求)
  • server.crt : 証明書

秘密鍵作成

OpenSSL で鍵長 2048bit の RSA 秘密鍵を作成します。

# openssl genrsa 2048 > ./server.key
Generating RSA private key, 2048 bit long modulus
.......................+++
.........+++
e is 65537 (0x10001)

CSR 作成

作成した秘密鍵を引数に CSR を作成します。
コモンネームや組織名などの入力を求められますが、今回は自己署名証明書のため、入力は全て Enter でデフォルト値を設定してしまいます。

# openssl req -new -key ./server.key > ./server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

証明書作成

CSR に先ほど作成した秘密鍵で署名し、有効期限 10 年間として証明書を作成します。

# openssl x509 -days 3650 -req -signkey ./server.key < ./server.csr > ./server.crt
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd
Getting Private key

リダイレクトで出力した server.crt が証明書ファイルとして使用できます。

Nginx の HTTPS アクセス設定

証明書の配置とアクセス権変更

作成した秘密鍵CSR、証明書のうち、秘密鍵と証明書を Nginx で使用します。
nginx ディレクトリ配下に ssl ディレクトリを作成して格納します。

# mkdir /etc/nginx/ssl/
# cp -p ./server.key /etc/nginx/ssl/
# cp -p ./server.crt /etc/nginx/ssl/

秘密鍵と証明書のアクセス権は root の読み取りのみに限定します。

# chmod 400 /etc/nginx/ssl/server.*
# chmod 700 /etc/nginx/ssl/

設定変更

Nginx の設定ファイルを編集します。
設定の要点は以下3つです。

  • ポート 80 (HTTP) へのアクセスに対しては HTTPS にリダイレクトさせる
  • ポート 443 (HTTPS) へのアクセスは SSL 設定を有効にする
  • location 等の設定は全て SSL の server ディレクティブに記述する
# vi /etc/nginx/nginx.conf

    ...省略...

    server {
        listen      80;
        server_name localhost;

        return 301  https://$host$request_uri;
    }

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl                 on;
        ssl_certificate     /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';

        ...省略...
    }

ssl_protocolsssl_ciphers については Mozilla SSL Configuration Generator で生成される設定を利用するのが一般的なようです。

設定の文法に問題がないことをテストしてリロードします。

# nginx -t /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# systemctl reload nginx

ブラウザからアクセスし、HTTPS の通信ができていること、HTTP が HTTPS にリダイレクトされることを確認します。
証明書情報が正しくないためブラウザからエラーが出ますが、エラーの無視や例外追加でページを閲覧することができます。

参考サイト

GitBucket のデータベース変更

前回に引き続き GitBucket の環境改善です。

組み込みの H2 データベースでは具合が悪いとのことが公式で言及されているため、
GitBucket でサポートしている MySQL に変更します。

GitBucketをPostgreSQLやMySQLで動かす - たけぞう瀕死ブログ

GitBucketは標準では内蔵のH2という組み込みデータベースで動作しますが、4.0からはH2の代わりに外部データベースとしてPostgreSQLMySQLを使うことができるようになっています。H2はデータの保全性に問題がありますので業務等の重要な用途にGitBucketを使われるのであればなるべくPostgreSQLもしくはMySQLを利用することが望ましいです(パフォーマンス面でもメリットがあります)。

基本的にはリンク先の通りの内容で問題なく解決できますが、
DB 側の設定をしていなかったので MySQL の導入から進めていきます。


検証環境

MySQL セットアップ

インストール

# yum install https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
# yum --enablerepo=mysql57-community -y install mysql-community-server

サイズが 200 MB ほどあるので、タイムアウトエラーが出る場合は
yumtimeout の設定を適当に追加します。

# vi /etc/yum.conf
timeout=3600

デフォルトでは一部の文字コードが latin1 になってしまうため、データベースやテーブルを作成する前に設定を追記します。

# vi /etc/my.cnf

[mysqld]
character-set-server = utf8

[client]
default-character-set = utf8

[mysql]
default-character-set = utf8

[mysqldump]
default-character-set = utf8

インストールと文字コード設定が完了したら mysqld を起動します。

# systemctl start mysqld
# systemctl enable mysqld

MySQL 設定変更

MySQL の初回起動後は root ユーザのパスワードが仮設定され、
ログに仮パスワードが出力されます。

# cat /var/log/mysqld.log | grep 'temporary password'
2017-10-20T04:25:29.312034Z 1 [Note] A temporary password is generated for root@localhost: Uo7hApMhqg(k

パスワードとして Uo7hApMhqg(k が設定されていることが分かりましたので、
この情報を元に初回ログインと設定変更をします。

また、パスワードポリシーはデフォルトで MEDIUM に設定されていて、
数字, 小文字, 大文字, 記号 の4種がそれぞれ1つずつ含まれている必要があるようです。

MEDIUM policy adds the conditions that passwords must contain at least 1 numeric character, 1 lowercase character, 1 uppercase character, and 1 special (nonalphanumeric) character.

初回設定をしていきます。

# mysql_secure_installation
Enter password for user root: Uo7hApMhqg(k

New password: (root パスワードを入力)
Re-enter new password: (root パスワードを再入力)

Change the password for root ? ((Press y|Y for Yes, any other key for No) : n
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y

mysql コマンドでログインし、プロンプトに変わったらログイン成功です。

# mysql -u root -p
Enter password: (先ほど設定した root パスワード)

mysql>

データベースとユーザの作成

GitBucket 用のデータベースとユーザを作成し、権限を付与して反映させます。
ここではパスワードを P@ssw0rd として作成しているので、適宜変更してください。

> CREATE DATABASE gitbucket;
Query OK, 1 row affected (0.02 sec)

> CREATE USER 'gitbucket'@'localhost' IDENTIFIED BY 'P@ssw0rd';
Query OK, 0 rows affected (0.02 sec)

> GRANT ALL PRIVILEGES ON gitbucket.* TO 'gitbucket'@'localhost';
Query OK, 0 rows affected (0.01 sec)

> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

H2 データベースからデータを抽出

前回の検証時に組み込みの H2 データベース上にユーザを登録してしまったため、
一旦 H2 からデータをエクスポートします。

最初から MySQL で構築を始める場合、この項目は飛ばしてください。

GitBucket からデータをエクスポート

  1. 管理者でログイン
  2. 右上のユーザメニューから 'System administration' を選択
  3. 左メニューの 'Data export / import' を選択
  4. チェックボックス全てにチェックを入れた状態で Export ボタンを選択
  5. gitbucket-export-xxxxxxxx.sql ファイルをダウンロード

上記の手順でデータが出力されます。

サービス停止

GitBucket のアプリケーションを停止します。

# systemctl stop tomcat

データのインポート

先ほどの .sqlMySQL に直接読み込ませます。

# mysql -u gitbucket -p < gitbucket-export-xxxxxxxx.sql
Enter password: P@ssw0rd

データベース接続設定変更

GitBucket のデータベース接続設定ファイルを編集します。

# vi /usr/share/tomcat/.gitbucket/database.conf

db {
  url = "jdbc:mysql://localhost/gitbucket?useUnicode=true&characterEncoding=utf8"
  user = "gitbucket"
  password = "P@ssw0rd"
}

設定が完了したらもう一度 GitBucket を起動します。

# systemctl start tomcat

ユーザやリポジトリの情報が復旧していれば作業完了です。

参考サイト

GitBucket 構築メモ

ソースコードを Git で管理するため、Git サーバを構築します。
今回は導入が比較的簡単そうな GitBucket を選定しました。

【2017/10/20 追記】
外部データベースを使用する記事を追加しました。
GitBucket のデータベース変更 - さばかん

検証環境

  • CentOS 7.3
  • Git 1.8.3
  • GitBucket 4.18.0
  • Tomcat 7.0.76
  • Nginx 1.12.2

インストール

Git については CentOS に最初からインストールされていたため省略します。

# yum info git
Version     : 1.8.3.1

Tomcat セットアップ

GitBucket のアプリケーションは Tomcat 上で動作させるため、
Tomcat をインストールする必要があります。

インストール後、Tomcat ディレクトリは所有者を tomcat に変更します。

# yum -y install java-1.8.0-openjdk
# yum -y install tomcat
# chown -R tomcat:tomcat /usr/share/tomcat

GitBucket セットアップ

Tomcat アプリケーション用ディレクトリにダウンロードします。

# cd /usr/share/tomcat/webapps
# curl -OL https://github.com/gitbucket/gitbucket/releases/download/4.18.0/gitbucket.war
# chown tomcat:tomcat /usr/share/tomcat/webapps/gitbucket.war

Tomcat サービスの開始後、 ポート 8080 で GitBucket にアクセスができます。

# systemctl start tomcat
# systemctl enable tomcat

Nginx セットアップ

今回はポート 80 から 8080 へのリバースプロキシとして使用します。
リポジトリ情報を作成し、yum でインストールします。

# vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enable=1

# yum -y install nginx

Nginx の http ディレクティブ内に設定を追加します。(抜粋)

client_max_body_size については、リポジトリにプッシュしたときに
サイズ上限エラーが出たため暫定的に 100MB として設定しています。

# vi /etc/nginx/nginx.conf

http {
    client_max_body_size 100m;

    server {
        location /gitbucket {
            proxy_pass http//127.0.0.1:8080;
        }
    } 
}

設定に問題がないことを確認し、サービスを起動します。

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# systemctl start nginx
# systemctl enable nginx

正しく動いていれば、ブラウザから http://127.0.0.1/gitbucket にアクセスして
GitBucket の Web アプリケーションが閲覧できるようになっています。

ログイン

デフォルトの設定では以下の情報でサインインできます。

Username: root
Password: root

参考サイト

MongoDB セットアップ手順

シングル構成の MongoDB セットアップ手順をメモとして残します。

検証環境

インストー

リポジトリ情報の作成

標準リポジトリには含まれていないため、新しく作成します。
上手くインストールできない場合は gpgcheck=0 にして gpgkey=… の行を除いてください。

# vi /etc/yum.repos.d/mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc

パッケージインストー

yum でパッケージをインストールします。

# yum -y install mongodb-org

バージョン 3.4 がインストールされたことを確認します。

# mongo --version
MongoDB shell version v3.4.4
git version: 888390515874a9debd1b6c5d36559ca86b44babd
OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
allocator: tcmalloc
modules: none
build environment:
    distmod: rhel70
    distarch: x86_64
    target_arch: x86_64

サービスの起動と自動起動の設定を有効にします。

# systemctl start mongod
# systemctl enable mongod

設定変更

3.x 系は設定ファイルを YAML で記述します。
ローカルホスト以外からの接続を許可する設定を有効にします。

# vi /etc/mongod.conf

net:
  port: 27017
  bindIp: 0.0.0.0
  http:
    enabled: true

上記の設定の再読み込みをします。

# systemctl restart mongod

ユーザまわりの設定

ユーザ追加

mongo コマンドで対話型シェル起動し、admin ユーザを作成します。

# mongo --host localhost --port 27017
> use admin
> db.createUser(
    {
      user: "admin",
      pwd: "password",
      roles: [ { role: "root", db: "admin" } ]
    }
  )

test-user ユーザを作成します。
role: "readOnly" にすると権限を読み込み限定に設定できます。

> use test-db
> db.createUser(
    {
      user: "test-user",
      pwd: "password",
      roles: [ { role: "readWrite", db: "test-db" } ]
    }
  )

作成したユーザを確認します。

> use admin
> db.system.users.find()

認証の有効化

ユーザ認証機能を有効にします。

# vi /etc/mongod.conf

security:
  authorization: enabled

設定を再読み込みし、ユーザ認証が有効化されたことを確認します。

# systemctl restart mongod
# mongo --host localhost --port 27017
> use admin
> db.system.users.find()

認証を行わない状態でユーザ一覧を出そうとするとエラーが返ってきます。

> db.auth("admin","password")
> db.system.users.find()

作成した admin と test-user が表示されていれば認証成功です。

ユーザの削除

DB 名を指定し、以下の remove() コマンドを実行します。

> use test-db
> db.dropUser("test-user")

データベースの操作

コレクション作成

test-db に test というコレクションを作成します。

> use test-db
> db.auth("test-user","password")
> db.createCollection("test")
> show collections

ドキュメント追加

適当な値を test コレクションに追加します。

> db.test.insert( { "foo" : "bar" } )
> db.test.find( { "foo" : "bar" } )

ドキュメントの件数カウント

コレクションのドキュメント数は count() で件数を表示できます。
find() と同様に括弧内にクエリを書くことで条件を絞ることも可能です。

> db.test.count()

削除系コマンド

ドキュメントを削除します。
括弧内に指定が無いとコレクション内のドキュメントが全件消去されます。

> db.test.remove( { "foo": "bar" } )

コレクションを削除します。

> db.test.drop()

データベース自体を削除します。

> use test-db
> db.dropDatabase()

ダンプとリストア

ダンプ

Bashmongodump コマンドでカレントディレクトリに dump を出力します。

# mongodump --db test-db --collection test --authenticationDatabase test-db --username test-user --password password --out ./dump

# ls ./dump/test-db/
test.bson  test.metadata.json

–db を指定しないと全てのデータベースを対象に BSON からリストアされます。

リストア

復元前に test コレクションを削除します。

> use test-db
> db.auth("test-user","password")
1
> db.test.drop()

mongodump と同様の指定方法で mongorestore します。

# mongorestore --db test-db --collection test --authenticationDatabase test-db --username test-user --password password ./dump/test-db/test.bson

消したコレクション・ドキュメントが復元されていればリストア完了です。

# mongo --host localhost --port 27017
> use test-db
> db.auth("test-user", "password)
> db.test.count()
1

参考サイト

chrony で NTP サーバを構築する

chrony は NTP のクライアント/サーバのミドルウェアです。
時刻を正確にするために導入します。

CentOS 7 からは ntpd に代わって chrony が標準となっています。

検証環境

  • CentOS 7
    • server01 (192.168.33.11)
    • server02 (192.168.33.12)
  • chrony 2.1.1

今回は2台の CentOS を使って検証します。
server01 をサーバ、server02 をクライアントとして用意します。

タイムゾーンの変更

Vagrant で作ったあとに時刻を確認したらイギリス夏時間だったので、
タイムゾーンも日本に設定します。 ※ 現在夜の23時台くらい

# timedatectl set-timezone Asia/Tokyo

# timedatectl status
      Local time: Mon 2017-04-17 23:10:25 JST
  Universal time: Mon 2017-04-17 14:10:25 UTC
        RTC time: Mon 2017-04-17 23:10:25
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: yes
      DST active: n/a

chrony インストールと起動

yum で chrony パッケージをインストールします。

# yum -y install chrony

パッケージ名とは異なり、デーモンの名前は chronyd です。

# systemctl start chronyd
# systemctl status chronyd

サーバ側の設定

server01 のマシンで操作します。

NICT と同期

同期する時刻サーバの設定を追加します。

[root@server01 ~]# vi /etc/chrony.conf

server の部分を NICT の時刻サーバと同期する設定に変更します。
また、後ほど設定する server02 がクライアントとして接続するため、
192.168.0.0 のネットワークも許可します。

server ntp.nict.jp iburst

allow 192.168/16

同期の確認

chronyd を再起動し、同期を確認します。

[root@server01 ~]# systemctl restart chronyd
[root@server01 ~]# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp-a2.nict.go.jp             1   6    77    42   -148us[-2816us] +/- 3731us

左の項目 MS^* が表示されていればサーバと同期が出来ている状態です。

クライアント側の設定

server02 のマシンで操作します。

server01 と同期

今度は NICT ではなく先ほどの server01 をサーバとして同期します。

[root@server02 ~]# vi /etc/chrony.conf
server 192.168.33.11 iburst

allow 192.168/16

同期の確認

chronyd を再起動し、server01 との同期を確認します。

[root@server02 ~]# systemctl restart chronyd
[root@server02 ~]# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 192.168.33.11                 2   6   377    37   +396us[ +480us] +/- 3930us

server01 との同期が確認できました。

参考サイト