アクセスログをシンプルにDB出力する

サーバー構成

AWSのELBに複数台EC2がぶら下がっており、そのEC2上でApache+PHP環境のアプリケーションが動作している

アクセスログ用テーブルの作成

sql
CREATE TABLE `access_logs` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `request_time` DATETIME NOT NULL COMMENT 'リクエスト日時',
    `session_id` VARCHAR(30) NOT NULL COMMENT 'セッションID',
    `request_method` VARCHAR(10) NOT NULL COMMENT 'リクエスト方式',
    `request_uri` VARCHAR(2083) NOT NULL COMMENT 'リクエストURI',
    `action_name` VARCHAR(50) NOT NULL COMMENT 'アクション名',
    `controller_name` VARCHAR(50) NOT NULL COMMENT 'コントローラ名',
    `x_forwarded_for` VARCHAR(255) NULL DEFAULT NULL COMMENT 'リクエスト元IP',
    `server_addr` VARCHAR(10) NULL DEFAULT NULL COMMENT 'サーバーIP',
    `user_agent` VARCHAR(255) NULL DEFAULT NULL COMMENT 'ユーザーエージェント',
    `request_query` TEXT NULL COMMENT 'リクエストクエリ',
    `request_data` TEXT NULL COMMENT 'リクエストデータ',
    `referer` VARCHAR(255) NULL DEFAULT NULL COMMENT 'リファラー',
    PRIMARY KEY (`id`)
)
COMMENT='アクセスログ'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

Model

Bakeで
https://book.cakephp.org/3.0/ja/bake/usage.html

AppController

beforeFilter

リクエスト内容を簡潔に取りたいのでbeforeFilterだけにしています。
結果まで取るのでしたらafterFilterも併用するといいかもしれません。

AppControllerクラスbeforeFilterメソッド
use CakeChronosChronos;

public function beforeFilter(Event $event) {
    try{
        // リクエストクエリとデータを文字列に変換&password等は出力しない
        $requestQuery = $this->unsetSecret($this->request->query);
        $requestData = $this->unsetSecret($this->request->data);

        $accessLogParameters = [
            'request_time' => (Chronos::createFromTimestamp(time()))->toDateTimeString(),
            'session_id' => $this->request->session()->id(),
            'request_method' => $this->request->env('REQUEST_METHOD'),
            'request_uri' => $this->request->env('REQUEST_URI'),
            'action_name' => $this->request->action,
            'controller_name' => $this->name,
            'x_forwarded_for' => $this->request->env('HTTP_X_FORWARDED_FOR'),
            'server_addr' => $this->request->env('SERVER_ADDR'),
            'user_agent' => $this->request->env('HTTP_USER_AGENT'),
            'request_query' => json_encode($requestQuery),
            'request_data' => json_encode($requestData),
            'referer' => $this->request->env('HTTP_REFERER')
            ];

        $accessLogModel = TableRegistry::get('AccessLogs');
        $accessLogEntity = $accessLogModel->newEntity($accessLogParameters);
        $accessLogModel->save($accessLogEntity);
    }
    catch (Throwable $throwable){
    }
}

アクセスログに残すべきでない情報の消去

パスワード等取っておいてはいけない情報を消します。

AppController内privateメソッド
/**
 * パスワード等のログ出力してはいけない項目をマスクする。
 * @param Array $params
 * @return Array
 */
private function unsetSecret($params){

    // unset対象の文字列
    $keywords = [
        'password',
    ];

    // unset処理
    $paramKeys = array_keys($params);
    foreach($keywords as $maskKeyword){
        $masks = preg_grep("/{$maskKeyword}/i", $paramKeys);
        foreach($masks as $mask){
            $params[$mask] = "***";
        }
    }
    return $params;
}

参考

AWS ELBが付与するHTTPヘッダ
http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/x-forwarded-headers.html

続きを読む

Amazon Linux + Apache でLet’s encrypt

Let’s encryptの設定

参考サイト

http://webfood.info/letsencrypt-renewal-failure/

Let’s encrypt とは?

「安全な接続を世界中に広めよう」という素晴らしい考えを持ったプロジェクト。
非営利団体の ISRG (Internet Security Research Group) によって運営されており、いろいろな大手企業がこの活動をサポートしている。利用料はもちろん無料。

なにがすごいんじゃ

Let’s encrypt では、「certbot」というクライアントソフトを使うことで、
自動的にSSL証明書の更新を行うことが出来るようになっている。
独自ドメインさえあればコマンド操作のみでSSL証明書がゲット出来るのである。

Amazon Linux に入れてみよう

Amazon Linuxはcertbotにまだ対応できていないため、単純にyumインストールができない(2017/11/16現在)
その為wgetでソースを落として直接インストールする必要がある。

$ wget https://dl.eff.org/certbot-auto
--2017-11-16 12:49:31--  https://dl.eff.org/certbot-auto
dl.eff.org (dl.eff.org) をDNSに問いあわせています... 151.101.32.201, 2a04:4e42:8::201
dl.eff.org (dl.eff.org)|151.101.32.201|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 57312 (56K) [application/octet-stream]
`certbot-auto' に保存中

certbot-auto            100%[==============================>]  55.97K  --.-KB/s    in 0.02s   

2017-11-16 12:49:31 (2.39 MB/s) - `certbot-auto' へ保存完了 [57312/57312]

$ chmod a+x certbot-auto

ここまでは公式サイトに乗っている手順通り。
後1コマンド!・・・というところでこんな表示が出てしまう。

$ ./certbot-auto
Requesting to rerun ./certbot-auto with root privileges...
FATAL: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!
Alternatively, you can install OS dependencies yourself and run this script
again with --no-bootstrap.

要約すると、
「Amazon Linuxでのcertbotはまだ実験段階だよ。もし君がその実験のお手伝いをしたいならバックアップを必ず取ってさっきのコマンドに–debugオプションを付けて実行してね!」
と書いてある。優しい。

というわけでバックアップをとって自己責任で実行してみる。

$ ./certbot-auto --debug
Requesting to rerun ./certbot-auto with root privileges...
Bootstrapping dependencies for Amazon... (you can skip this with --no-bootstrap)
yum は /usr/bin/yum です
読み込んだプラグイン:priorities, update-motd, upgrade-helper
パッケージ 1:openssl-1.0.2k-8.105.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ ca-certificates-2015.2.6-65.0.1.16.amzn1.noarch はインストール済みか最新バージョンです
パッケージ python27-2.7.12-2.121.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ python27-devel-2.7.12-2.121.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ python27-virtualenv-15.1.0-1.14.amzn1.noarch はインストール済みか最新バージョンです
パッケージ python27-pip-9.0.1-1.24.amzn1.noarch はインストール済みか最新バージョンです
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ augeas-libs.x86_64 0:1.0.0-5.7.amzn1 を インストール

~省略~

依存性を解決しました

===============================================================================================
 Package                   アーキテクチャー
                                        バージョン                    リポジトリー        容量
===============================================================================================
インストール中:
 augeas-libs               x86_64       1.0.0-5.7.amzn1               amzn-main          345 k
 gcc                       noarch       4.8.5-1.22.amzn1              amzn-main          4.1 k

~省略~

トランザクションの要約
===============================================================================================
インストール  6 パッケージ (+17 個の依存関係のパッケージ)

総ダウンロード容量: 32 M
インストール容量: 61 M
Is this ok [y/d/N]: 

お、なんとかなりそう。
というわけで実行しましょう。ちゃんと完了しました!と表示されるはずです。

これでインストールが完了です。ここからが本番です。

証明書を取得する

以下のコマンドを入力し、証明書を入手します。

./certbot-auto certonly --webroot -w [ドキュメントルート] -d [ドメイン]

–webrootオプションをつけることで、Webサーバを停止することなく実行できます。

以下のメッセージが表示されていれば成功です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/[ドメイン名]/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/[ドメイン名]/privkey.pem
   Your cert will expire on 2018-02-14. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

皆さん寄付をご検討ください。

このメッセージが表示されていれば、以下のパスに証明書ファイルが生成されています。
見に行きましょう。

$ cd /etc/letsencrypt/live/[ドメイン名]/
$ ls
cert.pem  chain.pem  fullchain.pem  privkey.pem  README

こいつらが生成されていればOK
Apacheにmod_SSLをインストールするのをお忘れなく

$ yum install -y mod24_ssl

ssl.confを修正

$ vi /etc/httpd/conf.d/ssl.conf 
以下を記述
SSLCertificateFile /etc/letsencrypt/live/[ドメイン名]/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/[ドメイン名]/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/[ドメイン名]/chain.pem

んでApaheを再起動すれば完了!

service httpd restart

問題なければここでおわり!
本当はhttpのアクセスをhttpsに流したりとかあるんだろうけど、それはまた別のお話。
お疲れ様でした。

…Apacheが起動しない人へ

最後に何故かApacheが起動しなくなりました・・エラーメッセージは以下

Starting httpd: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:443

443ポートがすでに使われているとのこと。しかしポートが使われている形跡はない・・・
悩みに調べて30分後

「もしやhttpd自身が443ポートを2回バインドしようとしているのでは・・・?」
とおもいhttpd.confを見てみると、ありました

Listen 443

こいつ。ssl.confの中にも書いてあるんですね。
httpd.confの方をコメントアウトしてhttpd再起動!

上手く行った!!!
よかったよかった。

誰かの助けになればいいなと思います。

続きを読む

AWS linux PHP apache mysql wordpress 環境構築

Step1
EC2インスタンス作成

1.png

Step2
TaraTerm使って、linuxサーバ接続する

2.jpg

Step3
yum 更新
$ sudo yum -y update

4.jpg
5.jpg

Step4
Apache2.4インストール

//バージョン確認
$ sudo yum list available | grep httpd

8.jpg

//httpd24インストールする
$ sudo yum -y install httpd24

6.jpg
7.jpg

//結果確認
$ sudo yum list installed | grep httpd24

9.jpg

Step5
PHP7.0インストールする

//バージョン確認
$ sudo yum list available | grep php70
//インストールする
$ sudo yum -y install php70 php70-mbstring php70-pdo
//結果確認
$ sudo yum list installed | grep php70

10.jpg
11.jpg
12.jpg

Step6
mysqlインストールする

//mysql バージョン確認
//mysql インストールする
//結果確認
$ sudo yum list available | grep mysql57
$ sudo yum install mysql
$ sudo yum list installed | grep mysql

20.jpg21.jpg
22.jpg

Step7
apache配置

etc/httpd/con/httpd.confを編集し、以下の2行を追加
(編集する前はhttpd.confバックアップする)
AddType application/x-httpd-php .html .htm .php .phtml
AddType application/x-httpd-php-source .html .htm .phps

・httpd.confバックアップする
$ sudo cp httpd.conf httpd.conf.bak

23.jpg

・httpd.conf編集する
$ vim httpd.conf

24.jpg

・AddTypeのところで下記二行追加
AddType application/x-httpd-php .html .htm .php .phtml
AddType application/x-httpd-php-source .html .htm .phps

25.jpg

・httpd restart
$ sudo service httpd restart

26.jpg

・確認する
var/www/htmlの下でindex.php を作成、下記のコードを追加
<?php
phpinfo();
?>
ブローザにIP入力、下記の画面出ます

28.jpg

Step8
mysql配置

・mysql起動する時、エラー発生しました。
改正:$ sudo yum install mysql57-server

29.jpg

・mysql 起動する
$ service mysqld start

30.jpg

・mysql 登録する

31.jpg

・ユーザ追加
ユーザ名:mysql
パスワード:mysql
mysql> CREATE USER ‘mysql’@’localhost’ IDENTIFIED BY ‘mysql’;

32.jpg
33.jpg

Step9
wordpess配置

・下記のurlから日本語wordpessダウンロードする
https://ja.wordpress.org/install/

var/www/html下に
$ wget https://ja.wordpress.org/wordpress-4.8.3-ja.zip

36.jpg

・解凍する

37.jpg

38.jpg

・エラー発生した
39.jpg

・原因:PHPにmysqlサポート追加されない。

・改正:
$ sudo yum -y install php70-mysqlnd
/etc/php.ini に extension=msql.so 追加

40.jpg
41.jpg

・設定画面が出ます
43.jpg

Step10
wordpess設定

・rootユーザにdatabaseを追加
mysql> create database wordpress;

・rootユーザパスワード修正
mysql>update mysql.user set authentication_string=password(‘root’) where user=’root’;

45.jpg

・wordpessに情報記入
46.jpg

47.jpg

wp-config.php作成
$ cd var/www/html/wordpress

48.jpg

・情報記入
49.jpg
50.jpg
51.jpg

ここまで、以上になります。

追記:
FTP使いたくない場合下記参照

・wp-config.php に書きます
define(‘FS_METHOD’, ‘direct’);
・wordpressフォルダすべてのファイル書き可能に変更
sudo chmod 777 * -R

続きを読む

EC2(Amazon Linux)とRDS(MySQL)でLAMP環境を構築するまで

備忘録程度に簡単にメモ

EC2でLAMP環境を構築するまでにやったこと

AWSでやったこと

  • AWSのアカウントを作った
  • 無料枠の範囲内でとりあえずEC2とRDSを立てる
    理由はなくなんとなくAmazon LinuxとMySQLの構成で作成。
    RDSを作成する時は無料枠のオプションを表示することが出来るので、そのチェックを入れておくと料金が発生する設定にしてしまうことを防ぐことができる。
  • 請求アラームの作成
    0ドルを超えるとメールで発報するよう設定(通常料金でも1,000円に収まる範囲だと思うが無料枠でいろいろしたいので)
  • Elastic IPの取得
    IPアドレスを取得し、EC2に関連付ける(無料枠内で起動しているEC2に関連付けされている間は無料らしい)
  • EC2のセキュリティグループにアクセスする際のIPからのSSH接続を許可
    ここで一緒に任意のIPからのHTTP/HTTPSも許可しとくといい

たぶんざっくりこんなもん
リージョンはオレゴン(リージョン次第で無料かどうか変わるのかはわからない)

SSH接続の設定

EC2を作成したときにpemをDLしているはずなので、それを使ってSSH接続してみる

pemの権限設定を変更する

$ chmod 400 [pemのパス]

SSH接続してみる

$ ssh -i [pemのパス] ec2-user@[パブリックドメイン]

パブリックドメインはec2から始まるインスタンスごとに勝手に設定されているもの
こんなの(ec2-11-111-111-1.us-east-2.compute.amazonaws.com)

これでつながるはず。繋がらなかったらインバウンドで許可したIPアドレスに間違いがないか、
ユーザ名(デフォはec2-user)を別に設定していないかなどを確認

ここまでできればあとはサーバ側の設定とDNSさえどうにかすればWebサーバとして利用できる

SSHConfigをいじって接続しやすくする(おまけ)

$ vi ~/.ssh/config 

以下のような感じで追記

#AWSサーバ
Host [sshコマンドで使う名前]
        HostName [パブリックドメイン]
        User ec2-user
        IdentityFile [pemのパス]

これで以下みたいに簡単に接続できる

$ ssh [sshコマンドで使う名前]

サーバ側の設定(とりあえずPHPとMySQLが使える状態に持っていく)

とりあえずソフトウェアパッケージを更新

$ sudo yum update -y

Apahe、PHP、MySQLをインストール

$ sudo yum install -y httpd24 php70 mysql56-server php70-mysqlnd

Apache起動とサーバ起動時に自動的に立ち上がるよう設定

$ sudo service httpd start
$ sudo chkconfig httpd on
chkconfig --list httpd
httpd           0:off   1:off   2:on    3:on    4:on    5:on    6:off

EC2のインバウンド設定でHTTPを任意のIPに対して許可していれば、ブラウザにIPアドレスを入力すると
Apacheのテストページが見れるはず

Apacheのドキュメントルートを編集できるようにする

デフォルトではApacheは/var/www/htmlをドキュメントルートにしている。
/var/wwwディレクトリはrootが所有者なので、apacheユーザに変更する
SSH時のユーザはec2-userなので、apacheユーザグループにec2-userを追加する。

$ sudo usermod -a -G apache ec2-user

再接続する

$ exit
$ groups
ec2-user wheel apache
$ sudo chown -R ec2-user:apache /var/www

グループ編集許可を与える

$ sudo chmod 2775 /var/www
$ find /var/www -type d -exec sudo chmod 2775 {} ;
$ find /var/www -type f -exec sudo chmod 0664 {} ;

PHPファイルの動作を確認する

さっきの設定がうまく行っていれば、ec2-userはルートディレクトリにファイルを作成する事ができるはず

$ echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

[IPアドレス]/phpinfo.php にアクセスしてPHPの情報が表示されるはず
公開すべき情報ではないので、忘れずに削除しとく

$ rm /var/www/html/phpinfo.php

EC2とRDSを疎通させる

とりあえずMySQLポートを開放

EC2のインバウンドにMYSQLの接続を任意の場所から許可するよう設定

mysqlコマンドでRDSのMySQLへ接続してみる

RDSのインスタンスのセキュリティグループで、EC2インスタンスのセキュリティグループからのMYSQL接続を許可するよう設定

mysql –h [RDSインスタンスのエンドポイント] -P 3306 –u [ユーザ名] –p
Enter password: [パスワード]

基本的にユーザ名とパスワードはAWSのユーザ名パスワードになっているはず(何も設定していなければ)

ここまでできればApache、PHP、MySQLのセットアップはざっくりと完了。
セキュリティ的な話をすると弱い部分はたくさんあるので、実際の公開時には補強の必要があるが、
最低限は上記で完了。
後は静的HTML置くなり、Codeigniterでも入れて本格的なWebアプリ公開するなりする。

続きを読む

Amazon EC2 (Amazon Linux)に PHP 7 + Laravel 5.5 + MySQL をインストールする手順 (201711版)

参考資料

https://qiita.com/zz22394/items/2d684d980f35106d3c65

Amazon EC2 (Amazon Linux)に PHP 5.6 + Laravel 5.3 + Apache 2.4をインストールする手順 (sedでphp.iniのdate.timezoneをAsia/Tokyoに変更するワンライナー)
https://qiita.com/na0AaooQ/items/e9b782be01ce6946d7e8

Goal

Amazon EC2 (Amazon Linux)に PHP 7 + Laravel 5.5 + Apache 2.4 + MySQL をインストールする手順 (201711版)

手順

PHP 7

sudo yum -y install php70 php70-mbstring php70-pdo

Git

sudo yum install git

Composer

sudo curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chown root:root /usr/local/bin/composer
ll /usr/local/bin/composer

MySQL

EC2にMySQLインストールと設定確認

sudo yum install  mysql56 mysql56-server
sudo service mysqld start
sudo /usr/libexec/mysql56/mysql_secure_installation
CREATE USER your_user IDENTIFIED BY 'your_password';

drop database your_database;
create database your_database character set utf8;
show create database your_database;
GRANT ALL PRIVILEGES ON your_database.* TO your_user@localhost IDENTIFIED BY 'your_password';
flush privileges;

select Host, User, Password  from mysql.user;

mysql -u your_user -p

PHP – MySQL Library install

yum list available | grep php70
sudo yum install php70-mysqlnd
yum list installed | grep php70

続きを読む

AWSサービスの概要を一覧化するスクレイピング

背景

AWSにはサービスが多種多様にあり、なかなか全体感が一覧できません。
初学者には「全体的にどんなサービスがあるの?」というのが俯瞰的に見ることができないのか「サービスのカテゴリとサービス名と、その概要を一覧化してくれ」なんてことがあろうかと思います。
対してうるせぇググれよさっと各サービスの概要説明を一覧にして差し上げるのがクラウド時代のエンジニアの所作と思われます。知らんけど。

やってみる

cheerio-httpcliでクローリング&スクレイピングしてみました。
最初はHeadless Chromeで始めたのですが、どうやらSPAはなさそうでcheerio-httpcliでよいだろうと書き直しました。

コードは以下に配置しています。
https://github.com/morimop/aws-services-list

  • 重複あっても気にしない
  • 一応言語切り替えができるかもしれない雰囲気は出してみる

うまくいかなかったところ

サービスごとにレイアウトが統一されていないので、ここを取ってくればいい、という単純な判定はできませんでした。

index.js
            const pElements = [].filter.call(
              $('main').find('p'),
              (pn)=>{
                if($(pn).find('a').length == 0){
                  return true;
                };
                return ($(pn).find('a').text() != $(pn).text());
              });

この箇所はEMRのページのせいです。このページだけHadoopやらSparkやらのリンクが冒頭に付いているので、これを除外しています。

index.js
          return $('p').parent().text().trim();

mainが見つからなかったページはとりあえず何か取ってくる、という雑仕様です。
AWS Marketplaceのページが相当おかしな感じになります。

結果

出力は./tmp/以下にJSONで出力していますので、JSON to CSVしたりするとEXCELで見られると思われます。
sample-services.PNG
圧巻。

詳細を以下に貼り付けます。長いので前半のちょっとだけを転載します。

“category” “services__name” “services__href” “services__abstruct”
“コンピューティング” “Amazon EC2” https://aws.amazon.com/jp/ec2/?nc2=h_m1 “Amazon Elastic Compute Cloud (Amazon EC2) は、安全でサイズ変更可能なコンピューティング性能をクラウド内で提供するウェブサービスです。ウェブスケールのクラウドコンピューティングを開発者が簡単に利用できるよう設計されています。 Amazon EC2 のシンプルなウェブサービスインターフェイスによって、手間をかけず、必要な機能を取得および設定できます。お客様のコンピュートリソースに対して、高機能なコントロールが提供され、Amazon の実績あるインフラストラクチャ上で実行できます。Amazon EC2 では、わずか数分間で新規サーバーインスタンスを取得して起動できるようになります。これにより、コンピューティング要件の変化に合わせて、すばやく容量をスケールアップおよびスケールダウンできます。実際に使用した分のみ料金が発生するため、Amazon EC2 はコンピューティングの経済性も変革します。Amazon EC2 を利用すれば、耐障害性に優れたアプリケーションの構築が可能になり、よくある障害のシナリオとは無縁になります。”
“” “Amazon EC2 Container Registry” https://aws.amazon.com/jp/ecr/?nc2=h_m1 “Amazon EC2 Container Registry (ECR) は、完全マネージド型の Docker コンテナレジストリです。このレジストリを使うと、開発者は Docker コンテナイメージを簡単に保存、管理、デプロイできます。Amazon ECR は Amazon EC2 Container Service (ECS) に統合されているため、開発から本番までのワークフローを簡略化できます。Amazon ECR を使用すると、自前のコンテナリポジトリの運用や、基盤となるインフラストラクチャのスケーリングの検討は不要になります。Amazon ECR は非常に可用性が高くスケーラブルなアーキテクチャでイメージをホストするため、コンテナをアプリケーションに確実にデプロイすることが可能です。AWS Identity and Access Management (IAM) に統合すると、各リポジトリをリソースレベルで制御できます。Amazon ECR に前払い料金などの義務はありません。リポジトリに保存したデータ量とインターネットに送信されたデータ量に対してのみ料金が発生します。 AWS 無料利用枠の一環として、Amazon EC2 Container Registry を無料でお試しいただけます。Amazon ECR では、新しいお客様に、月 500 MB 分のストレージを 1 年間にわたって提供いたします。”
“” “Amazon EC2 Container Service” https://aws.amazon.com/jp/ecs/?nc2=h_m1 “Amazon EC2 Container Service (ECS) は、非常にスケーラブルかつ高性能なコンテナ管理サービスで、Docker コンテナに対応しており、Amazon EC2 インスタンスのマネージド型クラスターでアプリケーションを簡単に実行できます。Amazon ECS を使用すると、自社でクラスター管理インフラストラクチャのインストール、運用、スケールを行う必要がなくなります。簡単な API 呼び出しを使用して、Docker 対応アプリケーションの起動と終了、クラスターの完了状態のクエリ、多くの使い慣れた機能 (セキュリティグループ、Elastic Load Balancing、EBS ボリューム、IAM ロールなど) へのアクセスを実行できます。Amazon ECS を使用することで、リソースニーズと可用性要件に基づいて、クラスター全体のコンテナの配置をスケジューリングできます。ビジネスまたはアプリケーション固有の要件を満たすために、独自のスケジューラーまたはサードパーティ製のスケジューラーを統合することもできます。 Amazon EC2 Container Service に追加料金は発生しません。アプリケーションを保存および実行するために作成した AWS リソース(EC2 インスタンス、EBS ボリュームなど)に対してのみ料金が発生します。”
“” “Amazon Lightsail” https://amazonlightsail.com “Everything you need to jumpstart your project on AWS—compute, storage, and networking—for a low, predictable price. Launch a virtual private server with just a few clicks.”
“” “Amazon VPC” https://aws.amazon.com/jp/vpc/?nc2=h_m1 “Amazon Virtual Private Cloud (Amazon VPC) により、アマゾン ウェブ サービス (AWS) クラウドの論理的に分離したセクションをプロビジョニングできます。これにより、AWS リソースをユーザー定義の仮想ネットワークで起動できます。ユーザーの IP アドレス範囲の選択、サブネットの作成、ルートテーブルとネットワークゲートウェイの構成など、仮想ネットワーク環境を完全にコントロールできます。VPC では、リソースやアプリケーションに安全かつ簡単にアクセスできるよう、IPv4 と IPv6 を両方とも使用できます。 Amazon Virtual Private Cloud のネットワーク設定は容易にカスタマイズすることができます。例えば、インターネットとのアクセスが可能なウェブサーバーのパブリック サブネットを作成し、データベースやアプリケーションサーバーなどのバックエンドシステムをインターネットとのアクセスを許可していないプライベート サブネットに配置できます。セキュリティグループやネットワークアクセスコントロールリストなどの複数のセキュリティレイヤーを活用し、各サブネットの Amazon EC2 インスタンスへのアクセスをコントロールすることができます。”
“” “AWS Batch” https://aws.amazon.com/jp/batch/?nc2=h_m1 “AWS Batch を使用することにより、開発者、科学者、およびエンジニアは、数十万件のバッチコンピューティングジョブを AWS で簡単かつ効率的に実行できます。AWS Batch では、送信されたバッチジョブのボリュームと特別なリソース要件に応じて、コンピューティングリソース (CPU やメモリ最適化インスタンス) の最適な数量とタイプを動的にプロビジョニングできます。AWS Batch を使うと、ジョブを実行するためのバッチコンピューティングソフトウェアやサーバークラスターをインストールしたり、管理したりする必要がなくなります。これにより、結果の分析と問題解決に集中できます。AWS Batch では、Amazon EC2 やスポットインスタンスなどの AWS コンピューティングサービスと機能を最大限に活用して、バッチコンピューティングワークロードを計画、スケジュール作成、実行します。 AWS Batch に対する追加料金はありません。バッチジョブを保存したり実行したりするために作成した AWS リソース (EC2 インスタンスなど) に対してのみ料金が発生します。”
“” “AWS Elastic Beanstalk” https://aws.amazon.com/jp/elasticbeanstalk/?nc2=h_m1 “簡単に開始でき、不足を感じることなく利用 AWS Elastic Beanstalk は、Java、.NET、PHP、Node.js、Python、Ruby、Go および Docker を使用して開発されたウェブアプリケーションやサービスを、Apache、Nginx、Passenger、IIS などの使い慣れたサーバーでデプロイおよびスケーリングするための、使いやすいサービスです。”
“” “AWS Lambda” https://aws.amazon.com/jp/lambda/?nc2=h_m1 “AWS Lambda を使用すれば、サーバーのプロビジョニングや管理なしでコードを実行できます。課金は実際に使用したコンピューティング時間に対してのみ発生し、コードが実行されていないときには料金も発生しません。Lambda を使用すれば、実質どのようなタイプのアプリケーションやバックエンドサービスでも管理を必要とせずに実行できます。コードさえアップロードすれば、高可用性を実現しながらコードを実行およびスケーリングするために必要なことは、すべて Lambda により行われます。コードは、他の AWS サービスから自動的にトリガーするよう設定することも、ウェブやモバイルアプリケーションから直接呼び出すよう設定することもできます。 AWS Lambda とは(日本語字幕)”
“” “Auto Scaling” https://aws.amazon.com/jp/autoscaling/?nc2=h_m1 “Auto Scaling により、アプリケーションの可用性を維持できると同時に、お客様が定義する条件に応じて Amazon EC2 のキャパシティーを動的および自動的に縮小あるいは拡張できます。Auto Scaling を EC2 インスタンスのフリート管理に使用することによって、フリートの状態と可用性を維持し、必要な数の Amazon EC2 インスタンスを確実に実行できます。また、Auto Scaling を EC2 インスタンスの動的スケーリングに使用することによって、需要が急激に上昇したときには Amazon EC2 インスタンスの数を自動的に増やしてパフォーマンスを維持し、需要が落ち着いた状態にあるときには能力を縮小してコストを削減できます。Auto Scaling は需要のパターンが一定のアプリケーションにも、使用量が時間、日、週で変動するアプリケーションにも適しています。Auto Scaling を Amazon EC2 で使用する以外に、Application Auto Scaling を使用して、Amazon ECS、Amazon EC2 スポットフリート、Amazon EMR クラスター、AppStream 2.0 フリート、Amazon DynamoDB といった AWS のその他のサービスのリソースを自動的にスケールできます。 12 か月間の AWS 無料利用枠と、24 時間年中無休のカスタマーサービスやサポートフォーラムなどの AWS の基本的なサポート機能を利用できます。”
“” “Elastic Load Balancing” https://aws.amazon.com/jp/elasticloadbalancing/?nc2=h_m1 “Elastic Load Balancing は、アプリケーションへのトラフィックを複数のターゲット (Amazon EC2 インスタンス、コンテナ、IP アドレスなど) に自動的に分散します。Elastic Load Balancing は、変動するアプリケーショントラフィックの負荷を、1 つのアベイラビリティーゾーンまたは複数のアベイラビリティーゾーンで処理できます。Elastic Load Balancing では、3 種類のロードバランサーが用意されています。これらはすべて、アプリケーションの耐障害性を高めるのに必要な高い可用性、自動スケーリング、堅牢なセキュリティを特徴としています。 Application Load Balancer”
“ストレージ” “Amazon Simple Storage Service (S3)” https://aws.amazon.com/jp/s3/?nc2=h_m1 “今日の企業に求められるのは、大規模なデータを簡単かつ安全に収集、保存、分析する能力です。Amazon S3 は、ウェブサイトやモバイルアプリケーション、社内アプリケーション、IoT センサーやデバイスからのデータなど、どこからの、どのような量のデータでも保存と取得が可能なオブジェクトストレージです。これは 99.999999999% の耐久性を提供し、すべての業界のマーケットリーダーによって使用される何百万ものアプリケーションのデータを保管できるように設計されています。S3 では最も厳格なセキュリティ要件を満たす包括的なセキュリティおよびコンプライアンス機能が提供されます。お客様は柔軟にデータを管理して、コスト最適化、アクセス制御、コンプライアンスに対応できるようになります。S3 は、インプレースクエリ機能を備えた唯一のクラウドストレージソリューションであり、S3 の保管データに強力な分析を直接実行できます。また、Amazon S3 は、ISV ソリューションやシステムインテグレータのパートナーによる最大のエコシステムを備えた、最も強力なサポートが提供されているストレージプラットフォームです。 “

続きを読む

Let’s Encryptを使ってEC2にSSL証明書の発行から自動更新まで行う

はじめに

AWSでSSLを簡単に実現するにはAWS Certificate Manager(以下ACM)を使えばすぐ出来るけど、Elastic Load Barancer(以下ELB)を挟まなければいけなかった。特にELBのリスナーをいじっていなければELBを挟むと以下のような形でアクセスされる。

ユーザー → (http or https) → ELB → (http) → EC2

上記でアクセスされるというのはELBのリスナーが以下のようになっているから。
スクリーンショット 2017-11-02 19.23.20.png

ACMはELBでしか使えないので、結局EC2にアクセスする際はhttpでアクセスすることになる。

この時、サーバーサイドの言語を使ってhttpかhttpsを判別している時にhttpsでアクセスしてきてもELBからhttpで呼ばれるためmixed contentになったり不具合があったので、結局EC2にもSSLを適用させることにした。

色々調べてみたら、Let’s Encryptというのが便利そうだった。
なおLet’s Encryptを簡単に導入できるCertbotというクライアントがあったので、その方法で進めていきます

なおAmazon Linuxではまだ実験段階とのことで、途中以下のようにメッセージが出た。

FATAL: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!
Alternatively, you can install OS dependencies yourself and run this script
again with --no-bootstrap.

環境

  • Amazon Linux
  • Apache 2.4.7

前提として、EC2インスタンスの作成は出来ている状態で進めていきます。

以下で行う作業は全てssh後にrootユーザーとなっていることが前提で進めていきます。

1. certbotのインストール

// rootユーザーになる
$ sudo -i

// curlでインストール
$ curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto

// 700権限を付与
$ chmod 700 /usr/bin/certbot-auto

 

2. SSL証明書を作成する

// 生成するコマンド
$ certbot-auto certonly --webroot -w /var/www/html -d hoge.com --email hoge@hoge.com -n --agree-tos --debug

お使いの環境で上記コマンドの変更が必要な部分は以下です。
以下のオプションの後に値を半角スペースで入力する

オプション 概要
-w ドキュメントルートの指定 /var/www/html
-d 対象ドメイン hoge.com
–email 登録用メールアドレス hoge@hoge.com
-n 対話の入力をスキップ
–agree-tos 利用規約に同意する
–debug AWSではこれがないとエラーになる

-wで指定している/var/www/htmlはApacheのデフォルトのドキュメントルートです。httpd -Sとかで確認して設定してください。

最後についてる--debugはAmazon Linuxはまだ実験段階であるためこのオプションをつけなければエラーとなってしまうので、つける必要があります。

上記コマンドを入力して成功すると、以下のようなメッセージが出力される

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/hoge.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/hoge.com/privkey.pem
   Your cert will expire on 2018-01-31. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so

いつまで有効化というのも教えてくれるし、親切仕様…

3. 設定ファイルに証明書のパスを指定

mod_sslをインストールします。

// mod_sslをインストール
$ yum install mod24_ssl

// 作成されたssl.confをviで開く
vi /etc/httpd/conf.d/ssl.conf

ssl.conf

/etc/httpd/conf.d/ssl.confファイルの以下の部分を書き換えていきます。

  • SSLCertificateFile
  • SSLCertificateKeyFile
  • SSLCertificateChainFile

自分の環境下では102行目にSSLCertificateFileに関する記述がありました。

// 102行目にcert.pemファイルまでのパスを記述
102 SSLCertificateFile /etc/letsencrypt/live/hoge.com/cert.pem

// 110行目にprivkey.pemまでのパスを記述
110 SSLCertificateKeyFile /etc/letsencrypt/live/hoge.com/privkey.pem

// 119行目のコメントアウトを外しchain.pemまでのパスを記述
119 SSLCertificateChainFile /etc/letsencrypt/live/hoge.com/chain.pem

変更したらesc:wpで保存して終了し、service httpd restartでApacheを再起動します。

4. SSL証明書をcronを使って自動更新する

Let’s Encryptで発行した証明書は3ヶ月しか有効期限がないので、自動で更新するようにしておく必要があるかと思います。

/usr/bin/certbot-auto renew --post-hook "sudo service httpd restart"のコマンドを実行し、証明書の更新が出来るのか確認する。

証明書を発行した際に、renewコマンドで更新が出来ると書いてあったので、renewコマンドで更新を行う。--post-hookオプションで更新が行われた際に実行するコマンドを指定出来る。

cronに登録する前にcronが使用出来るか確認。
/etc/rc.d/init.d/crond statuscrond (pid 2641) is running...となっていれば大丈夫。

cronファイルを作成

vi /etc/cron.d/letsencryptでファイルを作成して、ファイルに以下を記述する。

0 1 * * * root /usr/bin/certbot-auto renew --post-hook "service httpd restart"

以上で毎日1時にcronが実行されSSL証明書の確認・更新が行われるようになります。

以上で設定は終わりなので、設定したドメインにhttpsをつけてアクセスしてみてください。

httpsでアクセス出来なかったら

もしhttps://設定したドメイン で見れない場合は、「EC2」→ 「セキュリティーグループ」でインスタンスに適用しているグループの「インバウンド」の編集から以下を追加してあげればOKです。

スクリーンショット 2017-11-02 18.54.39.png

続きを読む

nginxのアクセスログからAmazon Athenaを利用してリファラー別にリクエスト数を集計する

初投稿です。
今までQiitaにはだいぶお世話になっており、自分もすこしは貢献したいなと思ったので最近Athena使った時のこと書こうと思います。

apacheやfluentdを使ったAthenaでのアクセスログ解析はネットにたくさん落ちていたのだが、nginxのログをAthenaで解析する情報が少なかったので、同じように困っている人がいたら参考にしてください。

前置き

前職では、アクセスログを解析するDWHがあったのでアクセスログの集計は簡単にできたのだが、現在のシステムはそんな素晴らしいものはなく、今までバッチファイルで集計していた。ただ、特定の条件のアクセスを過去データまで集計したい場合にバッチだとつらくなったのでAmazon Athenaを利用して集計してみることにした。

システム環境

Webサーバはnginxを利用しており、アクセスログの形式は一般的なものを使用。具体的な形式は以下のとおり。

XXX.XXX.XXX.XXX - - [21/Oct/2017:03:08:31 +0900] "GET /js/service.js?cv1=&cv2=&cv3=&cv4= HTTP/1.1" 200 39 "https://clientA.co.jp" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36" "YYY.YYY.YYY.YYY"

やりたいこと

システムへのアクセスがリファラー別(ドメイン別)にどれくらいあるのかを調査したい

手順

アクセスログをS3に置く

各サーバのアクセスログをローカルにダウンロードしてきて、S3に置く。
今回は、月別で集計がしたかったので、バケット名はaraiguma47-bucketとし、その配下に日時のディレクトリを切ってアクセスログを置いた。この際、アクセスログは圧縮したままでOKとのこと!

araiguma47-bucket/athena/201705/XXX-access.log-20170501.web01.gz
araiguma47-bucket/athena/201705/XXX-access.log-20170501.web02.gz
araiguma47-bucket/athena/201705/XXX-access.log-20170502.web01.gz
....
araiguma47-bucket/athena/201705/XXX-access.log-20170531.web02.gz

Athenaの設定

テーブルの追加

Amazon Athenaのサービスへアクセスし、左カラムのTABLESのAdd Tableをクリック。

  • Step1: Name&Location

Dabase名やTable名、S3の位置を設定する

Create new database: access_log
Table Name : log_201705
Location of Input Data Set : s3://araiguma47-bucket/athena/201705/

とし、Nextをクリック

  • Step2: Data Format

アクセスログの形式を指定する。
今回はApache Web Logsを選択し、Regexには、

^(S+) S+ S+ [([^[]+)] "(w+) (S+) (S+)" (d+) (d+) "([^"]+)" "([^"]+)".*

を設定し、Nextをクリック
※ Regexの最後に改行が入らないように注意してください。

  • Step3: Columns
    データのそれぞれのカラムに名前をつける。その際、データのtypeも指定する。
    複数カラムがある場合、一つづつ設定が大変なのと、同じ処理を何度もしなければいけないため、今回はBulk add columnsを使用する。Bulk add columnsをクリックしたら、以下を記載する。
ip                STRING,
time_local        STRING,
method            STRING,
uri               STRING,
protocol          STRING,
status            int,
bytes_sent        int,
referer           STRING,
user_agent        STRING

追加ができたら、Nextをクリック

  • Step4: Partitions
    パーティションを設定することによって、検索範囲を絞れたりするらしいが、今回は設定なしでいくこととした。

  • 完了したら、Create tableをクリックしtableを作成。Query successful.とでていればOK。作成されたtableの右の…をクリックし、preview tablesでデータが入っていることを確認。

いざQueryを実行!

Databaseを選択し、Queryを書いてみる。
今回使用したQueryは以下の通り。Athenaが思ったより早かったので、Queryの速度の最適化は行ってません。

SELECT
        count(referer LIKE '%www.clientA.co.jp%' OR null) AS clientA,
        count(referer LIKE '%www.clientB.co.jp%' OR null) AS clientB,
....
        count(referer LIKE '%www.clientC%' OR null) AS clientZ,
        count() AS total
FROM access_log."log_201705"
WHERE uri LIKE '/js/service.js%';

無事結果が取得できたらOKです。

結果

バッチファイルで数時間かかっていた処理が数分で返ってくるようになったので、さまざまな集計がこれでできるようになりました。さすがAmazonと言えるくらい、満足いく結果です。

Athenaの料金

Amazon AthenaはQueryによりスキャンしたデータ量によって課金されます。金額はそのクエリでスキャンされたデータ1TBごとに$5となっており、利用する前は金額が高くならないか慎重にQueryを投げてました。しかし、日に数百万,数千万件ほどのアクセスログくらいなら、圧縮したまま検索がかければ、日に1GB、月でも数10GBにしかならないため、バッチなどで何度もQueryを投げるような処理をしなければ、かなり料金は安いです。

実際、試行錯誤中、Athenaを使うためにQueryを何度も投げましたが、結果$1すらいってませんでした。ログの数年分をAthenaにいれて、スキャン範囲を大きくしたり、バッチなどで何度もQueryをなげたりしなければ、アクセスログくらいならほとんど金額を気にしないで利用できそうです。

一応注意としては、どんなにスキャン範囲がすくなくとも、10MB未満のクエリは10MBと計算されるらしいですが、個人で使えるくらい料金は安かったです。

課題

今回は月ごとにテーブルを作り集計したため、日時による検索が不要のため、日時のtypeをstgingとして読み込みました。ただ、アクセスログを数年分一つのテーブルに入れて一気に集計するなどしたい場合は、日時のtypeをtimestampやdateにする必要があるので、そこらへんを改善したいです。

また、partitionsを設定すれば金額を安くしたり、検索時間を短縮することも可能らしいので、時間があったらそこらへんの設定も追加したいです。

fluentdとか使って、アクセスログをS3に自動で転送したり、形式変えてAthenaでパースしやすくすれば、よりよくなるんだろうがそれはそのうち。。

参考にした、参考になるサイト

続きを読む

CentOS6.7(AWS)LAMP環境構築からPHPMyAdminまで

AWSの無料枠で使えるCensOSへLAMP環境を構築します。
ついでにSQLの使い勝手向上のため、PHPMyAdminを導入し、GUIでSQLを管理できるところまで残しておこうと思います。

LAMP環境

L-Linux

LinuxはCentOSを利用。
今回の環境では、AmazonWebServiceのEC2にて
AMIをCentOS Linux 6 x86_64 HVM EBS 1602-74e73035-3435-48d6-88e0-89cc02ad83ee-ami-21e6d54b.3 (ami-05cf2265)
として利用する。

A-Apache

WebサーバはApacheを利用する。
CentOSのyumを利用してパッケージをインストール。

#yum -y install httpd

Webサーバの起動

#service httpd start

起動時自動的にサービスが立ち上がるように設定

#chkconfig httpd on

Webサーバへの接続確認
クライアントからブラウザで接続を確認する。
※このWebサーバはデフォルトでファイアーウォールが効いており、接続できないはず。

ファイアーウォールの設定を確認

#/sbin/iptables -L --line-numbers

Httpの通信が許可されているかどうか確認する。
許可されていないと思うので、80番ポートと443番ポートに対して許可を与える。
※途中にはいっている数字「5」と「6」はファイアーウォールの行番号

#/sbin/iptables -I INPUT 5 -m tcp --dport 80 -j ACCEPT
#/sbin/iptables -I INPUT 6 -m tcp --dport 443 -j ACCEPT

nmapによりポートが開いたか確認する。
※デフォルトではインストールされていないので、インストールする

#yum -y install nmap

nmapの実行

nmap -p 1-1023 localhost

下記のように表示される。
image.png

再度クライアントからブラウザで接続確認を行い、下図のように表示されていれば正常にインストールが終了。
image.png

M-MySQL

MySQLのインストール

#yum -y install mysql-server

MySQLの起動

#service mysqld start

自動起動の設定

#chkconfig mysqld on

※実行の確認はPHPMyAdminを実装した後に行う。

P-PHP

PHPのインストール

#yum -y install php

つづいてPHPからMySQLを操作するためのモジュールをインストールする。

#yum -y install php-mysql

実行前にhttpdを再起動する。

#service httpd restart

インストール後の実行確認のため、PHPファイルを作成し確認する。
index.phpのファイルを作成し、確認

#vi /var/www/html/index.php
index.php
<?php
    phpinfo();
?>

これでPHPのインストールまで終了。

PHPMyAdminのインストール

GUIでMySQLを管理できるようにPHPMyAdminをインストールする。

phpMyAdminは標準リポジトリでは提供されていないため、
Fedoraプロジェクトの提供するRHEL用にビルドされたスペシャルパッケージを配布するEPELを追加する。

#yum -y install epel-release

EPELのインストール後リポジトリを利用してphphMyAdminをインストールする。

#yum --enablerepo=epel install -y  phpMyAdmin

ブラウザからWebサーバへ接続したURL/phpMyAdmin/とすると表示できるようになった。
しかし、初期設定ではローカルホストからの接続しか許していないため、外部からの接続を許可する必要がある。

外部クライアントからの接続設定

#vi /etc/httpd/conf.d/phpMyAdmin.conf

下図中のDeny from Allが全ての接続を拒否しているため、コメントアウトする。
設定ファイルのコメントアウトは#なので、先頭に#を追加する。
image.png

設定の保存後、反映させるためにApacheを再起動する。

#service httpd restart    

ここでphpMyAdminに接続する。

URL/phpMyAdmin

MySQLへのログイン

初期設定では、MySQLのrootへパスワードが設定されていないため、はじかれてしまう。
コマンドでMySQLのrootユーザへパスワードの付与が必要になる。
image.png

MySQLへログインし、rootへパスワードを設定する
※初期はrootのパスワードが無いため、このままログインできる

#mysql -u root

mysqlのユーザへパスワード追加

mysql>set password 'root'@'localhost' = password('パスワード');

ここで設定したパスワードを元にphpMyAdminへログインする。

image.png

無事に設定されていれば、下図のように表示される

image.png
以上。

次はphpMyAdminを用いてデータベースの設定とユーザの追加をやります。

続きを読む