mysql5.7 の 注意点 (< 5.7.11)

RDS 上で mysql 5.7 を使うときに覚えておかなければならないことは一つで、

default_password_lifetime
この値が、5.7.10 以下の時、360 になっています。

SELECT @@default_password_lifetime;

つまり360日で期限切れになりログインできなくなります。RDS 作成時のマスターパスワードであっても同じです。

Your password has expired. To log in you must change it using a client that supports expired passwords.

万が一、期限が切れてしまった場合は、
RDSのマスターパスワードをリセットし、mysqlにログイン。

ALTER USER user_name PASSWORD EXPIRE NEVER;

これで password_lifetime = 0 となり、ログインできます。

5.7.11以降のバージョンは、default_password_lifetime = 0 になっているので、問題はありません。

CloudFront lambda@Edge で、Basic認証を設定する

S3+CloudFrontなど、サーバーレスでBasic認証をかける方法を何年も検討していたのですが、CloudFrontにLambdaを割り当てられるようになり、試したところ実装することがで来ました。

まだPreview版ですが、フォームから申請することで、数日で許可が得られます。

イベントの種類

まず仕組みとしては、以下4つのイベントに、機能が絞られたLambda@Edgeを割り当てることがで来ます。

Viewer リクエス

リクエスト時に呼ばれるイベント

Viewer レスポンス

レスポンス時に呼ばれるイベント

Origin リクエス

オリジナルデータにリクエストが到達した時に呼ばれるイベント

Origin レスポンス

オリジナルデータからのレスポンス時に呼ばれるイベント

リクエストとレスポンスの違い

レスポンスの場合
  • レスポンスヘッダーの参照
  • レスポンスヘッダーの書き換え
  • レスポンスを返す

こちらはあまり使うことを検討していないので、もしかしたら他の機能もあるかもしれません。

リクエストの場合
  • リクエストヘッダーの参照
  • Origin へのリクエストヘッダーの書き換え
  • Origin の切り替え
  • Origin にアクセスせず、その場でレスポンスを返す

status が callback に渡した連想配列に含まれているかどうかで、Originへアクセスするかどうかの挙動が変わるようです。



今回は Viewer リクエストを使います。
Basic 認証の仕様に合わせてヘッダーを返すことで、Basic認証を実装することがで来ました。

exports.handler = (event, context, callback) => {
    
    const Allows = {
        "users": "users",
    };
    
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const authorization = headers.authorization || headers.Authorization;

    if (authorization) {
        
        const enc = authorization[0].split(" ")[1];
        const userPassword = new Buffer(enc, 'base64').toString();
        
        for (var key in Allows) {
            var val = Allows[key];
            if (`${key}:${val}` === userPassword) {
                callback(null, request);
                return
            }
        }
    }

    const response = {
        status: '401',
        statusDescription: 'Authorization Required',
        httpVersion: request.httpVersion,
        headers: {
          "WWW-Authenticate": ['Basic realm="Enter username and password."'],
          "Content-Type": ["text/plain; charset=utf-8"],
        },
        body: "401 Authorization Required",
    };

    callback(null, response);
};

event のサンプル

※ event に入ってくるデータは、以下のように小文字でくることもあれば、大文字始まりで受け取る場合もあるので、どちらにも対応しなければならないようです。

{
  "host":["dummy.dayo"],
  "authorization":["Basic dXNlcnM6dXNlcnM="],
  "cache-control":["no-cache"],
  "user-agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"],
  "accept":["*/*"],
  "accept-encoding":["gzip, deflate, sdch, br"],
  "accept-language":["ja,en;q=0.8,en-US;q=0.6"]
}


ログがでないと言うことと、Lambda@Edgeを割り当てたときだけでなく、コードを書き換えたあとも、数分待ち時間があることで、確認が大変でした。

ElasticBeanstalk+CloudFrontのときにも、このBasic認証の設定が活躍するのでうれしいです。

unching-star.hatenablog.jp

SES でメール送信時にリジェクトされる

Net::SMTPFatalError: 554 Message rejected: Email address is not verified. The following identities failed the check in region US-EAST-1

ActionMailer で送信した例だが、このようにメール送信がデフォルト状態だと出来ない。

Your Amazon SES account has "sandbox" access in region US East (N. Virginia). With sandbox access you can only send email to the Amazon SES mailbox simulator and to email addresses or domains that you have verified. To be moved out of the sandbox, please request a sending limit increase. Learn more.
Can't find your existing account settings? Your account may be set up in a different AWS region. Try switching regions in the upper right corner of the console.

SESはデフォルトの状態だと、sandboxモードになっており、テスト用の特定アカウントか、登録したメールアドレス、送信元と同じメールアドレスにのみ、送信できるようになっている。

サポートへ問い合わせることで、送信制限と緩和と同時に、sandboxモードが解除され、どのメールへも送れるようになる。

Lambda@Edge を利用し、Cloudfrontに設定ようとしたとき、エラーが表示される

There was an error creating the trigger: Completing this action would cause the maximum number of distributions with Lambda function associations per owner to be exceeded (maximum allowed is 0).

Lambda@Edge は現在プレビュー版となっており、利用する場合は事前に申請の必要があります。
申請は下記のページより

https://pages.awscloud.com/lambda-at-edge-preview.html

AWS SSM で、EC2に任意のコマンドを実行する

ssm は、ssh で接続することなく、 必要な role があれば、特定の EC2 上へコマンドを送ることが出来ます。
Amazon Linux に対しても、実行できます。

EC2の自動セットアップを行いながらも、ssh キーの登録をしたくないようなときに役立ちます。

実行するリモートサーバー側に ssm-agent をインストールする。

cd /tmp
curl https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm
yum install -y amazon-ssm-agent.rpm

実行するリモートサーバー側に role を設定する。

AmazonEC2RoleForSSM

コマンドを送る元に、role を設定する。

AmazonSSMFullAccess

実行方法

こんな感じ

def command(instance, commands):
  ssm = boto3.client('ssm')
  r = ssm.send_command(
    InstanceIds = [instance.instance_id],
    DocumentName = "AWS-RunShellScript",
    Parameters = {
      "commands": commands
    }
  )
  command_id = r['Command']['CommandId']

  while True:
    time.sleep(0.2)
    res = ssm.list_command_invocations(CommandId=command_id)

    invocations = res['CommandInvocations']
    if len(invocations) <= 0: continue

    status = invocations[0]['Status']
    if status == 'Success': return True
    if status == 'Failed': return False

Rails5 では、production 時、config.autoload_paths が機能しない

こちらに変更点が書かれていますが、

A Guide for Upgrading Ruby on Rails — Ruby on Rails Guides

Autoloadを有効にする

$ vi config/environments/production.rb

config.enable_dependency_loading = true

起動時にロードする

config.eager_load_paths += %(hoge)

どちらかの対応で読まれるようになります。