[AWS] AWS Certificate Manager が Tokyo リージョンにやってきた!

AWS Certificate Manager が Tokyo リージョンでも使えるようになりました。
AWS Certificate Manager now available in more regions

以前、SES を使って ACM の承認メール受信する方法を書いてますので、それ参考にしてくださいねー。

S3 で SES 受信するためのバケットポリシーサンプル

{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "GiveSESPermissionToWriteEmail",
"Effect": "Allow",
"Principal": {
"Service": [
"ses.amazonaws.com"
]
},
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::BUCKET-NAME/*",
"Condition": {
"StringEquals": {
"aws:Referer": "ACCOUNT-ID-WITHOUT-HYPHENS"
}
}
}
]
}

[AWS] mailq を監視して CloudWatch のカスタムメトリクスに送信

Web サーバにバックドア仕掛けられて spam 送信の踏み台にされていないかを確認するために mailq の値をカスタムメトリクスに定期的に送信してCloudWatch で検出しておくと、ある日突然 AWS から「Your Amazon EC2 Abuse Report」ってメールが来ることが無くなると思うよ。

#!/bin/sh
# EC2 のインスタンス ID を取得
instanceid=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)

# region を取得
az=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
_length=$(echo $((${#az} - 1)))
region=$(echo ${az} | cut -c 1-${_length})

namespace="System/Linux"

# mailq
mailq=$(mailq | grep 'Total requests' | awk '{print $3}')
aws cloudwatch put-metric-data \
 --region ${region} \
 --namespace ${namespace} \
 --dimensions InstanceId=${instanceid} \
 --unit Count \
 --metric-name "MailQueu" \
 --value "$mailq"

[AWS] Lambda から Lambda を呼ぶ

ようやく AWS Lambda が把握できてきた。
小さい機能単位で Lambda ファンクション作って、それを呼ぶ感じで作っていくとやりやすい。

イベント発生して呼び出される Lambda ファンクション

イベントの情報をもとになんかする Lambda ファンクション

結果を SNS なり、Slack なりに投げる Lambda ファンクション

みたいに Lambda ファンクションから Lambda ファンクションを呼び出して作業させると具合がいい
Lambda から Lambda を呼ぶには

console.log('Loading event');
var aws = require('aws-sdk');

exports.handler = function(event, context) {
    // なんか処理

    var lambda = new aws.Lambda({apiVersion: '2014-11-11'});
    var params = {
        FunctionName: "lambda-function-name",
        InvokeArgs: JSON.stringify({
            "key_1": 'var_1',
            "key_2": 'var_2',
            "key_3": 'var_3'
            }, null, ' ')
        };
    lambda.invokeAsync(params, function(err, data){
        if(err) context.done('error', err.stack);
        else context.done(null, '');
}

Lambda から SNS を呼ぶには

var sns = new aws.SNS({region: 'リージョン'});
var params = {
    TopicArn: 'トピック arn',
    Subject: 'サブジェクト',
    Message: 'メッセージ'
  };
  sns.publish(params, function(err, data) {
    if(err) context.done('error', err.stack);
    else context.done(null, '');
  })

[AWS] Lambda でS3 にファイルをアップロードしたら typetalk チャットに通知するやつ

参考: AWS Lambda でS3 にファイルをアップロードしたらSlackチャットに通知するやつ

元記事では Slack だったけど、typetalk も業務でお世話になってるので、Typetalk 対応もしてみた。
Typetalk API

const TYPETALK_TOKEN = "....";

var req = require('request');

exports.handler = function(event, context) {
    var filename = event.Records[0].s3.object.key;
    typetalk(TYPETALK_TOKEN, "your typetalk toppick id", "Put: "+filename);
};

function typetalk(token, topic_id, message) {
    req.post('https://typetalk.in/api/v1/topics/'+topic_id+'?typetalkToken='+token)
        .form({
            message: message
        })
        .on('response', function (response) {
          response.on('data', function(data) {
            context.done(null, data);
          });
        })
        .on('error', function (err) {
            cotext.done(err, 'Failed post the chat');
        });
}

https://github.com/wokamoto/aws-lambda-samples/tree/master/s3slack

[Nginx] CloudFront を前面に置いたときに css が gzip 転送されないときへの対処

Nginx をオリジンサーバにして CloudFront を設置したときにテキストファイルが gzip 圧縮転送されないときは nginx.conf に以下を追加する。

gzip_proxied any;
gzip_http_version 1.0;

参考: Serving Compressed Files – Amazon CloudFront

網元 AMI で対応するなら、以下の手順で

$ sudo sh -c 'echo "gzip_proxied any;" > /etc/nginx/conf.d/gzip_proxied.conf'
$ sudo service nginx reload

[Nginx] Nginx で S3 をリバースプロキシする

location ~* ^/(get_s3)/(.*) {
set $s3_bucket 'your_s3_bucket_name.s3.amazonaws.com';
set $url_full "/$1/$2";
proxy_http_version 1.1;
proxy_set_header Host $s3_bucket;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers "Set-Cookie";
proxy_buffering off;
proxy_intercept_errors on;
resolver 172.16.0.23 valid=300s;
resolver_timeout 10s;
proxy_pass http://$s3_bucket/$url_full;
}

view raw
gistfile1.nginxconf
hosted with ❤ by GitHub

参考:
http://davidburgosonline.com/dev-ops/2014/configure-nginx-amazon-s3/
https://coderwall.com/p/rlguog/nginx-as-proxy-for-amazon-s3-public-private-files

可用性は落ちちゃうけど、例えば S3 上のテキストファイルを gzip 圧縮転送したいとか、https + spdy で配信したいとかに使おう

Re: Amimotoからstaticpress-s3で静的ホスティング連携

名前もお好きに、とりあえず、wp_update_siteurl.sh とかで。EC2のメタデータを取得して、その情報でデータベースを更新するようにしました。

#!/bin/bash

_id=`curl -s 169.254.169.254/latest/meta-data/instance-id/ | sed -e "s/-/_/"`
_dns=`curl -s 169.254.169.254/latest/meta-data/public-hostname/`
mysql -u root ${_id} <<_EOT_

update wp_options set option_value = 'http://${_dns}' where option_name = 'siteurl';
update wp_options set option_value = 'http://${_dns}' where option_name = 'home';

_EOT_

Amimotoからstaticpress-s3で静的ホスティング連携

武田さん、ありがとうございます。
でも、このままだと不完全で、実は WordPress では wp_options の他にも wp_posts 内に画像ファイルのURLとかを投稿した時の home_url を元に絶対パスで保存してたりするんです。
wp-cli ってツールを使うと、そんな値を一括で置換してくれる search-replace という便利なコマンドが有ります。
網元AMIには、最初から wp-cli 入っているので、wp-cli をインストールしたりする必要は無いです。

てことで、こんな感じで wp_update_siteurl.sh を作ればおっけー

#!/bin/bash
WP_ROOT="/path/to/wordpress"
WP_CLI="/usr/local/bin/wp –path=${WP_ROOT}"
_old_url=`${WP_CLI} eval "echo home_url();"`
_dns=`curl -s 169.254.169.254/latest/meta-data/public-hostname/`
$WP_CLI search-replace ${_old_url} http://${_dns}

view raw
wp_update_siteurl.sh
hosted with ❤ by GitHub

2行目の “/path/to/wordpress” の所は、適宜自分の環境に合わせて変更してください。

[AWS] awscli と jq でインスタンスタイプの変更を気軽に

awscli, jq が利用できることが前提です。
以下のようなシェルスクリプトを組むだけで、特定のインスタンスのインスタンスタイプを変更できます。
(ついでに EIP の付与も)

#!/bin/sh
AWS_PROFILE='YOUR aws-cli PROFILE HERE'
INSTANCE_ID='YOUR INSTANCE ID HERE'
INSTANCE_TYPE='YOUR INSTANCE TYPE HERE'
PUBLIC_IP='YOUR INSTANCE EIP HERE'
while :
do
EC2_STATE=`aws ec2 describe-instances –profile ${AWS_PROFILE} –instance-ids ${INSTANCE_ID} | jq -r '.Reservations [] .Instances [] .State | .Name'`
if [ $EC2_STATE = 'running' ]; then
aws ec2 stop-instances –profile ${AWS_PROFILE} –instance-ids ${INSTANCE_ID}
fi
if [ $EC2_STATE = 'stopped' ]; then
break
fi
echo "${INSTANCE_ID} : ${EC2_STATE}"
sleep 10
done
aws ec2 modify-instance-attribute –profile ${AWS_PROFILE} –instance-id ${INSTANCE_ID} –instance-type ${INSTANCE_TYPE}
aws ec2 start-instances –profile ${AWS_PROFILE} –instance-ids ${INSTANCE_ID}
while :
do
EC2_STATE=`aws ec2 describe-instances –profile ${AWS_PROFILE} –instance-ids ${INSTANCE_ID} | jq -r '.Reservations [] .Instances [] .State | .Name'`
if [ $EC2_STATE = 'running' ]; then
break
fi
echo "${INSTANCE_ID} : ${EC2_STATE}"
sleep 10
done
EC2_EIP=`aws ec2 describe-instances –profile ${AWS_PROFILE} –instance-ids ${INSTANCE_ID} | jq -r '.Reservations [] .Instances [] .PublicIpAddress'`
if [ $EC2_EIP != $PUBLIC_IP ]; then
aws ec2 associate-address –profile ${AWS_PROFILE} –instance-id ${INSTANCE_ID} –public-ip ${PUBLIC_IP}
fi

view raw
gistfile1.sh
hosted with ❤ by GitHub

[AWS] AMI 作る前にやっておきたいこと

#!/bin/sh
rm -rf /tmp/*
rm -f /etc/ssh/ssh_host_*
if [ -d /var/log ]; then
find /var/log -type f -print | xargs -L1 /bin/cp /dev/null
fi
if [ -d /var/spool/mail ]; then
find /var/spool/mail -type f -print | xargs -L1 /bin/cp /dev/null
fi
/bin/cp /dev/null /root/.ssh/authorized_keys
/bin/cp /dev/null /root/.bash_history
if [ -f /root/.mysql_history ]; then
/bin/cp /dev/null /root/.mysql_history
fi
if [ -d /home/ec2-user ]; then
/bin/cp /dev/null /home/ec2-user/.ssh/authorized_keys
/bin/cp /dev/null /home/ec2-user/.bash_history
if [ -f /home/ec2-user/.mysql_history ]; then
/bin/cp /dev/null /home/ec2-user/.mysql_history
fi
fi
history -c
echo "clear!"

view raw
clear.sh
hosted with ❤ by GitHub

  • /var/log 以下のファイルを /dev/null で上書き
  • /var/spool/mail 以下のファイルを(略)
  • /root 以下の .ssh/authorized_keys, .bash_history, .mysql_history を(略)
  • (あれば) /home/ec2-user 以下の .ssh/authorized_keys, .bash_history, .mysql_history を(略)
  • /tmp/*, /etc/ssh/ssh_host_* を削除

をやるので、最低限必要なことはこれで足りるはず
参考: cloudpackブログ: 公開AMIを作成する直前で行っていること

せっかちなあなたには

# curl -L clear.ninjax.cc | bash; history -c 

authorized_keys 消すから、この作業やったら、そのインスタンスにはログインできなくなるよ