[Git] 運用ルールの決定〜導入

検討事項

  • Gitアカウント取得は自社か、先方か
  • ブランチ管理モデルは、Git flowか、Github flowか
    • Git flow: 全員が全員ブランチを切り全員がマージできる状態
    • Github flow: develop masterへのマージはコード管理者へのプルリクで行う
    • 後者の方がコード品質は保てるが実装期間が短い場合これは該当しない。
  • 有識者・管理者の選定
  • 本番サーバに上がっているソースとgit masterに上がっているファイルの比較/保守

ブランチ管理(例)

  • リポジトリの作成
  • ブランチと役割を明確化
    • 例: master, develop, feature, release, hotfixで以下のように運用。
    • masterはマージ後テスト済みのリリース可能な状態のブランチ。直接このブランチで作業しない。
    • developは開発ブランチ。feature/release/hotfixブランチを切り、終わったらdevelopへマージ。直接このブランチで作業しない。
    • featureは追加機能開発ブランチ。
    • releaseはリリース用ブランチ。developブランチから切ってmasterブランチへマージ。
    • hotfixは本番障害時など早急に対応が必要な場合にmasterブランチから切られる。
  • ポータルのWiki等で周知し、ブランチ管理を管理者の元徹底化。

Gitクライアントの選定

  • Git CLI
  • SourceTree
  • GitHub Desktop

参考サイト

maintenanceサーバの構築

環境

環境 Ver.
OS 4.9.32-15.41.amzn1.x86_64
Apache 2.4

▼以下は既に適宜設定/構築されているものとする。

  • EC2起動/基本設定
  • 静的メンテナンスファイルとCSS/JSは “/var/www/html” 配下に配置。
  • “_Health_Check.html”を配置。
  • サーバーの基本設定Apacheの基本設定等が設定済み。
  • ELB HealthCheckも適宜設定済み。
$ cd /var/www/html
$ tree
.
├── _Health_Check.html
├── maintenance.html
└── resources

コンテンツの権限/所有者の変更

$ chown -R apache:apache /var/www/html
$ cd /var/www/
$ find html -type f -exec chmod 0644 {} \;
$ find resources -type d -exec chmod 0755 {} \;

503リダイレクト設定

/etc/httpd/conf.d/maintenance.conf

ErrorDocument 503 /maintenance.html
Alias /maintenance.html /var/www/html/maintenance.html
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} !^/resources/.*$
  RewriteCond %{REQUEST_URI} !^/maintenance.html$
  RewriteCond %{REQUEST_URI} !^/_Health_Check.html$
  RewriteRule ^.*$ /maintenance.html [R=503,L]
</IfModule>

サーバーへ反映する。

$ service httpd graceful

Apache基本設定

更新途中。

環境

  • Apache2.2, 2.4
  • AWS ELB

モジュールの確認

$ /usr/sbin/httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

DSO(Dynamic Shared Object)

実行時にモジュールを組み込める。
“httpd.conf” ファイルで “LoadModule” ディレクティブを使い、モジュールを指定する。

KeepAlive

ELBヘルスチェックの設定

ルート「/」へのチェックは、毎回トップへアクセスし、動的処理が入るため、負荷が高い。
ライトにする為、”_health_check.html”等適当にファイルを用意し、ヘルスチェック先を変更する。

アクセスログに正常にスタンプされることを確認。

"GET /_health_check.html HTTP/1.1" 200

ELBのタイムアウト時間/ApacheのKeepAliveを調整

ELBのデフォルトタイムアウト時間は、”60秒”である。
ELBは、コネクション生成コスト削減の為、常設コネクション(セッション維持)を確立を生成し、60秒毎(デフォルト)に再生成している。
Apache2.4系では、”mod_reqtimeout”がデフォルトで有効になっており、デフォルト値は”header=20-40,MinRate=500 body=20,MinRate=500″である。
TCPコネクション接続後、”20-40秒”のうちにHTTPヘッダーの応答がないコネクションは、破棄を行う。
デフォルト値ではbodyは20秒、headerは20秒以内に受信できないときはタイムアウトとみなし、データ送信中は500Bytes受信するごとに1秒、タイムアウトまでの時間を延長し、最大30秒まで延長することが可能。

ELBで常設コネクション(セッション維持)を行っているのに、Apache側でタイムアウトすると、408エラーが起こってしまう。セッションが切れてしまう為、切断されたセッションを繋ぎ直す余計な処理も走ることになる。

ELBのタイムアウト設定を変更し、Apache側のタイムアウトは変更しない場合

“KeepAliveTimeout”を設定している環境であれば、”KeepAliveTimeout”>”ELBアイドルタイムアウト”とし、そうでなければ、”ELBアイドルタイムアウト”を”5秒-50秒”に設定するのがよい(Apache2.2、2.4系では、”KeepAliveTimeout”のデフォルト値が”5秒”であり、5秒後に接続を遮断しコネクション再接続のコスト削減とサーバ側リソースとの調整を行っている為、ELBの”アイドルタイムアウト”を”5秒”まで短くしても問題ない。)。

ELBのタイムアウト設定を変更せず、Apache側のタイムアウトを変更する場合

“KeepAliveTimeout”を設定している環境であれば、”KeepAliveTimeout”の値 > “ELBアイドルタイムアウト”の値 とする。
AWSのドキュメントでは、ApacheのTimeout値は120秒を推奨値としている。
例えば、ELBのアイドルタイムアウト値を”60秒”のままにする場合、以下のように設定する。

  • Apacheタイムアウト時間: 120sec
  • keepalive: 90sec

▼設定例
/path/to/httpd.conf

<VirtualHost *:80>
  ServerName   www.example.com
  DocumentRoot /var/www/html/
  # Enable TCP keepalive
  Timeout 120
  KeepAlive On
  KeepAliveTimeout 90
  MaxKeepAliveRequests 100
  LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" combined
</VirtualHost>

ELB配下のApacheアクセスログにClientIPを表示する(Apache2.2系)

ELB配下のApacheアクセスログは、デフォルトだとClientIPではなくELBのIPが表示されてしまう。

10.20.0.80 - - [05/Sep/2017:16:45:08 +0900] "GET /_health_check.html HTTP/1.1" 200 227 "-" "ELB-HealthChecker/2.0"
10.20.1.168 - - [05/Sep/2017:16:45:08 +0900] "GET /_health_check.html HTTP/1.1" 200 227 "-" "ELB-HealthChecker/2.0"
$ yum --enablerepo=epel install mod_extract_forwarded

/etc/httpd/conf.d/mod_extract_forwarded.conf

LoadModule extract_forwarded_module modules/mod_extract_forwarded.so
MEForder refuse,accept
MEFrefuse all
MEFaccept all

Apacheの再起動を行う。

$ service httpd graceful

ELB配下のApacheアクセスログにClientIPを表示する(Apache2.4系)

“mod_remoteip”モジュールが読み込まれていることを確認する。
/etc/httpd/conf.modules.d/00-base.conf

LoadModule remoteip_module modules/mod_remoteip.so
$ apachectl -M | grep remoteip
 remoteip_module (shared)

/path/to/httpd-vhosts.conf

<VirtualHost *:80>
    ServerName xxx.net
    # IP check through ELB
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 10.20.0.80/32
    RemoteIPTrustedProxy 10.20.1.168/32
    DocumentRoot /var/www/vhosts/xxx/htdocs/yyy
    <Directory "/var/www/vhosts/xxx/htdocs/yyy">
        Require all granted
    </Directory>
</VirtualHost>

LogFormatを変更する。

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    #LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined # 追加
    #LogFormat "%h %l %u %t \"%r\" %>s %b" common
    LogFormat "%a %l %u %t \"%r\" %>s %b" common # 追加

access.logへ、ClientIPがスタンプされるようになる。

61.xxx.x.xxx - - [05/Sep/2017:17:16:01 +0900] "GET / HTTP/1.1" 200 65387 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"

Apacheの再起動を行う。

$ service httpd graceful

アクセス制限

全てのアクセスを許可

2.4系

<Directory "/admin">
  Require all granted
</Directory>

2.2系

<Directory "/admin">
  Order allow,deny
  Allow from all
</Directory>

全てのアクセスを拒否

2.4系

<Directory "/admin">
  Require all denied
</Directory>

2.2系

<Directory "/admin">
  Order allow,deny
  Deny from all
</Directory>

特定のIPのみ許可

2.4系

<Directory "/admin">
  Require ip xxx.xxx.xxx.xxx
</Directory>

2.2系

<Directory "/admin">
  Order deny,allow
  Deny from all
  Allow from xxx.xxx.xxx.xxx
</Directory>

IPによるアクセス等、設定したServerName以外でのアクセスには “403 Forbidden” を返す。

セキュリティの向上

“Trace method” を無効にする。
XSSの脆弱性がある場合に、APサーバー側でTrace methodが有効になっていると、”クロスサイトトレーシング”という脆弱性が発生する可能性があり、暗号化されていないBasic認証のID/パスワード/Cookieが漏洩する可能性がある。

/etc/httpd/conf/httpd.conf

TraceEnable off

反映を確認する。
“405 Method Not Allowed” と出力されていることを確認する。

$ curl -I https://{YOUR_DOMAIN}
HTTP/1.1 405 Method Not Allowed
Allow: GET
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/plain
Date: Mon, 25 Sep 2017 04:36:35 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Connection: keep-alive

welcomeページを非表示に。

$ cd /etc/httpd/conf.d/
$ mv welcome.conf welcome.conf.org

[svn] コマンド

# チェックアウト
$ svn co https://svn.xxx/src/trunk

# indexへ追加
$ svn add {FILE_NAME}

# indexから削除
$ svn delete {FILE_NAME}

# ファイルのリネーム
$ svn rename {FILE_NAME}

# コミット
$ svn commit -m "modify text" [--username xxx]
$ svn commit file -m "modify text"

# ブランチ作成
$ svn copy https://svn.xxx/src/trunk https://svn.xxx/src/branches/stable-2.0 -m "Create new branch, stable-2.0"

# タグ作成
$ svn copy https://svn.xxx/src/trunk https://svn.xxx/src/tags/2.0 -m "Create new tag, 2.0"

# ステータス確認
$ svn st
? apps/xxx.log

# 検証切り替え
$ svn info
$ svn switch https://svn.xxx/src/branches/stable-2.0

# 特定のリビジョンまで戻したい場合
$ svn merge -r [現在のリビジョン番号]:[戻したいリビジョン番号] [リポジトリURL]

[Shell Script] DBバックアップ、S3へアップロード

S3バックアップ用IAMユーザーの作成

Management Consoleより、IAMのポリシーを作成し、ユーザーをアタッチする。

S3バックアップ用ポリシー例

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1506579924000",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:ListMultipartUploadParts",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:PutObjectTagging",
                "s3:PutObjectVersionAcl",
                "s3:PutObjectVersionTagging",
                "s3:ReplicateDelete",
                "s3:ReplicateObject",
                "s3:RestoreObject"
            ],
            "Resource": [
                "arn:aws:s3:::{BUCKET_NAME}",
                "arn:aws:s3:::{BUCKET_NAME}/*"
            ]
        }
    ]
}
# AWS CLIからS3 APIへ接続
$ aws configure --profile s3-bk
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: text

# 確認
$ aws s3 ls s3://{BUCKET_NAME}/ --profile s3-bk

MySQL接続用ファイルの作成

mysql接続用のユーザー名/パスワードはスクリプト外のファイルで管理する。
./.access-db.conf

[client]
user     = "{DB_USER_NAME}"
password = "{DB_USER_PASS}"

権限を変更する。

chmod 0600 ./.access-db.conf

シェルスクリプト

変数は外部参照。
if文やエラー処理等は省略している。

#!/bin/bash
#
# Backup Database.
#
# Ex. sh database_backup.sh
#
###############################################

BK_PATH=/backups/databases
PROFILE=s3-bk
DB_NAME=test
DB_HOST=test.ap-northeast-1.rds.amazonaws.com
BUCKET_NAME_BACKUP="s3://{BUCKET_NAME}/"

if [ ! -e ${BK_PATH} ]; then
    mkdir -p ${BK_PATH}
fi

cd /root/scripts/backup_script

echo '~~~~~~~~~~~~ Start Backup ~~~~~~~~~~~~'

# MySQLdump DB server
mysqldump --defaults-extra-file=./.access-db.conf --databases ${DB_NAME} --default-character-set=utf8 --add-drop-database --host=${DB_HOST} > ${BK_PATH}/${DB_NAME}-dump.sql

# GZIP SQL files
# -C で絶対パスによるエラー出力を抑制
GZIP=-9 tar czf ${BK_PATH}/${DB_NAME}-dump-`date +%Y%m%d%H%M`.tar.gz -C / backups/databases/${DB_NAME}-dump.sql

echo '~~~~~~~~~~~~ Remove backup files more than 7 days ~~~~~~~~~~~~'
find ${BK_PATH}/ -name "*.tar.gz" -type f -mtime +7 | xargs rm -fv
rm -fv ${BK_PATH}/${DB_NAME}-dump.sql

# Sync S3
aws s3 sync ${BK_PATH}/ ${BUCKET_NAME_BACKUP} --acl private --profile=${PROFILE}

echo '~~~~~~~~~~~~ Finished Backup ~~~~~~~~~~~~'

exit 0
  • 外部ファイルから、DB(MySQL)接続ユーザーとパスワードは指定する。
  • 最高品質を保つ圧縮の”GZIP=-9″で”tar.gz”を作成。
  • 本日より7日前以上のファイルは削除。

Cronへ仕込み

$ crontab > /root/crontab
$ vim /root/crontab
$ crontab < /root/crontab
$ crontab -l
05 2 * * * /bin/sh /root/scripts/backup_script/contents_backup.sh 1> /dev/null 2> /dev/null
10 2 * * * /bin/sh /root/scripts/backup_script/database_backup.sh 1> /dev/null 2> /dev/null

参考サイト

関連記事