技術メモ

プログラミングとか電子工作とか

EC2を使わないAWSでメール送信/受信(転送)(SES + S3 + Lambda)

f:id:ysmn_deus:20200215223446p:plain

Amazon WorkMail使えばええやんって所なんですが、無意味にメアドを増やしたい時なんかは 4.0 USD/Monthはちょい高め。
なので、勉強がてらSES、S3、Lambdaを使ったメール送受信を導入してみることにしました。
とはいえ、SESは本来送信専用なので受信はどこか普段使いのメールに転送する想定になります。

メール受信(転送)のセットアップ

まずはメールの受信から。
基本的にはAWSの公式ドキュメントを参照します。
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-getting-started.html
AWSで痛い目に遭いたくなければ日本語ドキュメントは読まないことです。古事記にもそう書かれている。

Step 1: 初期設定

まずSESの設定とかを始める前にやっておくことが2点あります。

  • AWSのアカウントを作っておく
  • Route53にドメインを登録しておく

基本的にこれらはできてる想定で話を進めます。

Step 2: ドメインの認証

SESでドメインを利用するに当たってドメインの認証が必要になります。
とりあえずSESのコンソールに行きましょう。
https://console.aws.amazon.com/ses/

リージョンは東京がないのでとりあえずバージニア北部(us-east-1)を想定してます。
SESのコンソールを開いたら「Identity Managemen」の「Domains」に行きます。 f:id:ysmn_deus:20200214133008p:plain f:id:ysmn_deus:20200214130405p:plain

Verify a New Domain

なんもないと思うので、左上の「Verify a New Domain」をクリックします。
「Verify a New Domain」というダイアログが出てくると思うので、「Domain」にRoute53に登録したドメインを入力し、「Generate DKIM Setting」にチェックを付けて「Verify This Domain」をクリックします。
DKIMに関しては設定してなくても基本いけると思いますが、送信先によってははじかれたりするので設定しておくのが無難かな、と思います。

「Verify This Domain」をクリックすると、ダイアログの内容が少々変わってなんかでてくると思います。
f:id:ysmn_deus:20200214131648p:plain
Route53を利用しない場合は表示されているレコードをドメインに設定する必要がありますが、AWSに命を捧げている者はAWS様がよしなにしてくれます。
ドメインのレコードをRoute53を利用しない人はここで個別に設定が必要ですが、Route53ユーザーであれば迷わず「Use Route 53」をクリックしましょう。

Use Route 53

次に「Use Route 53」というダイアログが出てきます。
前の段落で設定する筈だった項目をウィザードでやってくれます。
f:id:ysmn_deus:20200214132315p:plain
初めてドメインにレコードを設定する人であれば特に気にせず「Email Receiving Record」の部分もチェック入れて良いと思いますが、もし他にメールアドレスを登録してる人などはMXレコードが上書きされてしまうので要注意です。
全てにチェックを入れて「Create Record Sets」をクリックします。
するとSESのコンソールに戻り、設定していたドメインがpendingになってるのが分かります。
f:id:ysmn_deus:20200214132724p:plain
ここで5分ほど待ちます。待ってる間にRoute53で設定したドメインのレコードに先ほどのウィザードで設定したレコードが追加されているか確認してもいいと思います。

時間がたったらたぶんverifiedになってると思います。
f:id:ysmn_deus:20200214133008p:plain

Step 3: 受信ルールの作成

Step2でドメインの認証を済ませたら、受信設定を作成します。
SESのコンソールの「Email Receiving」の項目から「Rule Sets」をクリックし、「Create a Receipt Rule」をクリックしましょう。
f:id:ysmn_deus:20200214133617p:plain

受信相手の設定

最初に出てくるのは受信対象の設定です。
もし受信するドメインを限定したりする場合はこの辺を設定しましょう。
たぶん設定する人は少ないと思うので、特になにも入力せず「Next Step」をクリックしましょう。
f:id:ysmn_deus:20200214133857p:plain

保存先の設定(Actionの設定)

メールが来たときにそのメールをどうするかの挙動(Action)を設定します。
「Add action」から「S3」を選びます。
f:id:ysmn_deus:20200214134325p:plain
f:id:ysmn_deus:20200214134336p:plain

まずはS3を用意してないと思いますので、「Create S3 bucket」を選択します。(もし既に作成済みなら該当するbucket名を選んでください)
f:id:ysmn_deus:20200214134603p:plain
適当なbucket名を入力します。
f:id:ysmn_deus:20200214140249p:plain
(email-ドメイン名、など分かりやすい名称がいいとは思います。)

prefixなど設定できますがたぶんS3のパフォーマンスを落とすだけなので無視しましょう。
「Next Step」をクリックします。

ルールの詳細設定(名前決めるだけ)

「Rule Details」の項目が出てきます。
基本的に「Rule name」の箇所だけ適当に入力して、「Next Step」で問題無いかと思います。

最終確認

今まで設定してきた項目が一覧で確認できます。
何か間違いがあればここで修正できます。大丈夫であれば右下の「Create Rule」でルールを作成します。
f:id:ysmn_deus:20200214140952p:plain

問題無ければSESのコンソール上で表示されている筈です。
f:id:ysmn_deus:20200214165126p:plain

Step 4: メール送信テスト

まだ設定半ばなのですが、一端ここまでの設定が正しいか確かめてみます。
ドメイン名の前は何でも良いので、「test@設定したドメイン」のように適当なアドレスに向けてメールを送ってみます。
(例えば、example.comというドメインを設定したなら「test@example.com」のような。@の前は何でも良い)

Step 5: 受信したメールを見てみる

設定がうまくいっていれば、先ほどテストで送ったメールがS3に保存されている筈です。
S3のコンソール( https://console.aws.amazon.com/s3/ )から先ほど設定したbucketを見つけて中を見てみましょう。
f:id:ysmn_deus:20200214170821p:plain
bucketの中には - AMAZON_SES_SETUP NOTIFICATION - 謎の英数字の羅列 の2ファイルが存在していると思います。
謎の英数字の羅列が保存されたメールとなります。ダウンロードして中身を確認してみると、メールのソースになっていると思います。
(いわゆる本文だけではなく送信元情報などのデータとしてのメール。)

これでメールの受信が機能している所までは良さそうです。

Step 6: S3にPUTされたらLambdaで転送する様にする

S3にあがるだけではIMAPPOP3形式で受信できないので、どこかのメーラーでやりとりしたいものです。
(例えばGmailThunderbirdなど)
本来設定しているメールアドレスに一時的に転送して、閲覧は普段使いのメーラーでできるようにします。

転送用のLambda関数を作成する

何はともあれLambda関数が必要です。SAM CLIなどでデプロイしてもいいんですがそんなにいじらないし全部ブラウザ上から済ませます。

ローカルにaws-lambda-ses-forwarderをcloneする

まずローカルにGithubで公開されている aws-lambda-ses-forwarder をcloneします。

git clone https://github.com/arithmetric/aws-lambda-ses-forwarder

使い捨てるので適当なディレクトリで大丈夫だと思います。
f:id:ysmn_deus:20200214172950p:plain
必要なのはindex.jsのみです。(なんならコピペでもいいんですが・・・)

コンソールでLambda関数を作成する

ソースが準備できたらLambdaのコンソールに行きます。
https://console.aws.amazon.com/lambda/home
右上の「関数の作成」からLambda関数を作成します。
f:id:ysmn_deus:20200214173333p:plain

「一から作成」で基本的な情報を入力していきます。
関数名は適宜決めていただいて(例えば、「sesForwarder」など)、ランタイムは、現在(2020/02/14)ではNodeのv12が利用可能ですが、念のためv10にしておきました。(GithubのREADME上にはv8 v10と記載があるので、多分v12でも大丈夫だけど)
実行ロールは後で編集するとして、特に触らずに「関数の作成」でLambda関数を作成します。
f:id:ysmn_deus:20200214173938p:plain

とりあえずLambda関数はできました。
f:id:ysmn_deus:20200214174259p:plain

作成した関数をaws-lambda-ses-forwarderに書き換える

先ほどcloneしたaws-lambda-ses-forwarderの中にある「index.js」をアップロードします。
めんどくさい人はエディタで開いてコピーしてからブラウザ上のエディタに貼り付けても良いと思います。
とりあえずzipに固めてアップロードする手法を採ります。「index.js」のみzipに固めます。
f:id:ysmn_deus:20200214174436p:plain

固めたzipをLambdaにアップロードします。
先ほどのコンソールから「関数コード」という項目を探しだし、「コードエントリタイプ」から「zipファイルをアップロード」を選択します。
f:id:ysmn_deus:20200214174611p:plain

「アップロード」という箇所が出てくるので、先ほどのzipをアップロードする。
f:id:ysmn_deus:20200214174744p:plain

「アップロード」の横にzipファイル名が記載されていればアップロードできているので、「保存」をクリックしてアップロードしたzipファイルを関数に適応する。
f:id:ysmn_deus:20200214174934p:plain

Lambdaのコンソール上のエディタにaws-lambda-ses-forwarderが表示されていればOK
f:id:ysmn_deus:20200214175114p:plain

aws-lambda-ses-forwarderの設定を書き換える

これでアップロードは完了しましたが、ちょっとだけ設定を変更します。
30行目のdefaultConfigの値を変更していきます。

var defaultConfig = {
  fromEmail: "noreply@example.com", // ここは設定したドメインの任意のメールアドレス
  subjectPrefix: "[Forwarding]", // 転送するタイトルの頭に何か付けるならここに設定
  emailBucket: "s3-bucket-name", // emailが格納されるS3のbucket名
  emailKeyPrefix: "", // SESの設定でprefixを設定している場合は設定。上記の通りであれば空でOK
  forwardMapping: {
    "info@example.com": [
      "example.john@hoge.com",
      "example.jen@hoge.com"
    ],
    "@example.com": [
      "example.john@hoge.com"
    ]
  }
};

SESは仕様上、転送するメールアドレスの差出人を自分のドメイン以外にすることができません。
つまり、「hogefuga@hoge.com」からメールが来た場合に、「example.john@hoge.com」へメールを転送するのですが、上記の設定では、「example.john@hoge.com」へ届くメールの差出人は「noreply@example.com」に書き換わっています。

f:id:ysmn_deus:20200214182932p:plain
図示するとこんなかんじ

forwardMappingのみ追加で説明しますと、上に記載されているものから順にマッチするか評価され、最初にマッチした宛先に転送されるようです。
つまり上の例では - info@example.comはexample.john@hoge.comとexample.jen@hoge.comに転送される - info2@example.comはexample.john@hoge.comのみに転送される という処理になります。
基本的には1対1か1個のメールアドレスに集約されるように書くのがいいんじゃないでしょうか。

変更した後は右上の「保存」をクリックすることをお忘れ無きよう。

Lambda関数のロールの設定

現状ただのLambda関数ですのでSESはおろかS3にアクセスすらできません。
なので - S3へのアクセス権限 - SESでの送信権限 - ついでにCloudWatchのログ作成権限 を付与します。

コンソール上の下の方にある「実行ロール」という項目を確認します。
f:id:ysmn_deus:20200214184038p:plain

「既存のロール」という項目の下にある「【関数名】-role-(英数字の羅列)ロールを表示」という箇所をクリックします。
するとIAMのコンソールが表示されますので、「インラインポリシーの追加」を押します。
f:id:ysmn_deus:20200214184359p:plain

「ポリシーの作成」というページが表示されますので、編集していきます。
設定する対象がわかりきっている場合はJSONの方が早いです。「JSON」をクリックして下記のように設定しましょう。
f:id:ysmn_deus:20200214184556p:plain

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
         ],
         "Resource": "arn:aws:logs:*:*:*"
      },
      {
         "Effect": "Allow",
         "Action": "ses:SendRawEmail",
         "Resource": "*"
      },
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetObject",
            "s3:PutObject"
         ],
         "Resource": "arn:aws:s3:::S3-BUCKET-NAME/*"
      }
   ]
}

S3-BUCKET-NAMEの箇所はemailが保存されているS3のbucket名に変更して下さい。
厳密に言えばSESのリソースなども対象を絞った方がセキュアだと思いますが、その辺は割愛します。

JSONの編集が完了したら、右下の「ポリシーの確認」をクリックします。

最後に、設定したポリシーがどのようなものか一覧で表示されます。
ポリシー名を付けないといけないので「名前」の箇所を「LambdaSesForwarder」としておきました。
f:id:ysmn_deus:20200214185106p:plain

問題無ければ「ポリシーの作成」をクリックして完了します。
また別のLambdaに別のメールアドレスを設定する可能性などある場合はポリシーを作成しておくと再び作成しなくていいのですが、どうせS3のbucketも変わると思いますのでインラインポリシーで良いと思います。

Lambda関数のタイムアウト時間の変更

大丈夫な気がするんですが、一応aws-lambda-ses-forwarderのREADMEによると「メモリ制限が128MBで10秒がええんとちゃうか?」のような記述があるので、タイムアウト時間だけ10秒に変更しておきます。
(大きな添付ファイルが想定される場合はメモリを512MBにするか、タイムアウトを30秒にするかした方がいいかも、とも書かれているので心配な方は30秒に設定しておいた方がいいかも)

設定を変える場所は先ほど編集していた「実行ロール」の隣にあると思います。「基本設定」という項目を見つけ「編集」をクリックして下さい。
f:id:ysmn_deus:20200214185949p:plain

タイムアウトを10秒に変更して、「保存」をクリックします。
f:id:ysmn_deus:20200214190059p:plain

SESの設定にLambda関数を追加する

ここまできてようやくSESとLambdaを連携させます。
「保存先の設定(Actionの設定)」で編集していたSESのコンソールの「Email Receiving」→「Rule Sets」を編集します。
今までの通りにやっていれば「default-rule-set」が適応されていると思いますので、「View Active Rule Set」をクリックし、設定したRule(たぶん一番上に表示されてるヤツ)をクリックして編集します。
f:id:ysmn_deus:20200214191042p:plain
f:id:ysmn_deus:20200214191143p:plain

Add actionからLambdaを選択します。
f:id:ysmn_deus:20200214191317p:plain

対象の関数は作成した関数名を入力すれば出てくると思います。
それ以外は基本デフォルトで。
f:id:ysmn_deus:20200214191600p:plain

右下の「Save Rule」を押して編集したルールを保存します。
Missing Permissionsと聞かれますので、「Add permissions」で作成したSESにlambdaを起動する権限を付与します。

SESの設定で転送先のメールアドレスを認証しておく(一時的なもの)

おそらくスパム対策だと思いますが、初期状態ではSES+Lambdaでメールを送信する場合は転送先のメールアドレスを前もって認証しておく必要があります。
(後述する AWSのサポートへ連絡 でどのメールアドレスにも送信できるようになります。)
試験的にメールを送信するために、SESのコンソールから転送対象の認証を済ませます。
コンソールの「Identify Management」→「Email Addresses」をクリックし、「Verify a New Email Address」をクリックします。
f:id:ysmn_deus:20200214194422p:plain

Lambda関数のところで転送先を編集したと思うので、そのアドレスを入力します。
(上記の例では「example.john@hoge.com」と「example.jen@hoge.com」の二つ)
f:id:ysmn_deus:20200214194635p:plain

「Verify This Email Address」をクリックすると、前の画面に戻ってpendingになっているのが確認できます。
おそらく「Amazon Web Services – Email Address Verification Request...」というタイトルのメールが届いていると思いますので、記載されているリンクを24時間以内にクリックします。
「検証に成功しました」的な旨のページが出ればOKです。
f:id:ysmn_deus:20200214195036p:plain

コンソール上で先ほど設定したメールアドレスがpendingからverifiedに変わっていれば転送の準備は完了です。
f:id:ysmn_deus:20200214195239p:plain

転送されるか試しにメールを送ってみる

とりあえずメールを送りましょう。宛先は何でも良いと思いますが、Lambda関数の中でマッピングを複雑にした場合は色々試してみると良いと思います。

EX: S3のライフサイクルポリシー

上記のままだとメールが未来永劫たまり続けます。
基本残したままで困る容量ではないですが、SES+Lambdaで究極のコスパを攻めるならS3には極力データは残しておかない方がいいかもしれません。
S3にはライフサイクルポリシーという生成されてからどの期間残しておくかが設定できますので、そちらを設定しておけば極力容量は抑えられるとは思います。
ここでは割愛しますが、需要があればそのうち追記します。

メール送信のセットアップ

と項目を書いたのですが、受信のセットアップが終わっていればほぼ完了しているも同然です。
とはいえまだSMTPの情報などがないのでセットアップしていきましょう。

SMTPの情報を取得する

SESのコンソールから「Email Sending」→「SMTP Settings」をクリックします。
表示されている「Create My SMTP Credentials」をクリックします。
f:id:ysmn_deus:20200214231439p:plain

「Create User for SMTP」というページが出てくるので、とりあえずIAM User Nameはデフォルトで入ってる適当な名称を利用します。

f:id:ysmn_deus:20200214231952p:plain
特に変更しない

右下の「作成」でSMTPのユーザーを作成します。
f:id:ysmn_deus:20200214232107p:plain

書いてあるとおり、認証情報はこのタイミングでしかダウンロードできないので慎重に保存しておきます。
最悪ユーザーを作り直せば良いだけだと思いますが、くれぐれもこの辺の認証情報を公開しないように注意しましょう。
上記の画像に書いてある「ユーザーのSMTPセキュリティ認証情報を表示」でユーザー名とパスワードを表示して設定してもいいですが、ファイルに保存しておいた方が確実かと思いますので、右下の「認証情報のダウンロード」から認証情報を保存しておきましょう。

試験的に送信してみる

先ほどのSMTPの情報で、試しに認証している(上記までの例では、転送先のメールアドレス)にメールを送信してみて下さい。
おそらくSMTPのポートを587に設定して上記の情報を利用すれば送信できると思います。

Sandbox外への払い出し

SESのサービスを利用し始めたときは、認証したメールアドレスにしかメールを送ることができません。
(転送だけしかしない場合はこれでも問題ないでしょう)
なので、認証してないメールアドレスにも送信できるようにAWSに申請する必要があります。

AWSのサポートへ連絡

サポートに連絡するためにコンソール( https://console.aws.amazon.com/ )を開きます。
右上にある「サポート」から「サポートセンター」を開きます。
f:id:ysmn_deus:20200215091101p:plain

「Create case」をクリックし、「Service limit increase」を選択します。
f:id:ysmn_deus:20200215091414p:plain

すると、「Case classification」というボックスが出てくると思いますので、「Limit type」の「SES 送信制限」を選択します。
f:id:ysmn_deus:20200215095237p:plain
その他の入力項目は適宜合わせて貰えば良いと思いますが、今回は普段使いのメールなので「メールの種類」を「その他」、「ウェブサイトのURL」を空欄、残りの項目を「はい」にしました。
最後の3項目は日本語だとなんのこっちゃ・・・という感じですが、原文は

  • For My email sending complies with the AWS Service Terms and AUP, choose the option that applies to your use case.
  • For I only send to recipients who have specifically requested my mail, choose the option that applies to your use case.
  • For I have a process to handle bounces and complaints, choose the option that applies to your use case.

と記載されていますので

  • AWSサービス条件とAUP(ウェブサイトでリンクがありますのでご確認ください)を満たしているか
  • 受け取る意思がある人にのみメールを送信するか(メールのやりとりなので、よっぽど特殊なケースでない限りはあるはず。不特定多数の営業とかには使っちゃダメですね。)
  • 苦情などが来たときにハンドリングする手順があるか(普通のメールなので基本的には考えなくて良いと思います)

といった感じでしょう。アプリケーションなどにも活用を考えている場合はこのへんは慎重に回答してください。

次に、「Requests」の項目を埋めます。
リージョンを自分のSESのリージョンに合わせ、「Limit」を「希望する一日あたりの送信クォータ」に設定し、「New limit value」を「200」に設定します。この200は公式ドキュメントに書いてあります。 基本的にはドキュメント通りに設定すれば問題無いと思います。1日に200通以上も送る(受信ではなく送信)人は通常の人ではないので僕は知りません。
f:id:ysmn_deus:20200215100127p:plain

次に、「Case description」を記入します。
基本的にはありのままを記載すれば良いと思いますが、「Case classification」ではいと答えている項目には言及しておいた方がいいかもしれません。
自分は普通にメールとして使うよ!ということと、苦情対策としてはCloudWatchでSESの送信制限を監視して、ヤバそうだったら利用を停止するよ!ということを書いておきました。

最後に「Contact options」ですが、基本的にはデフォルトのままで良いと思います。「Preferred contact language」はもしかしたら英語の方がレスポンスが早いのかなぁとも思ったんですが、その後でやりとりが発生する可能性を考慮して一応日本語にしておきました。
「submit」を押して起票完了です。
f:id:ysmn_deus:20200215100956p:plain

たぶん1日ぐらいで返信が来ます。(自分は約1日で来ましたが、2~3日たっても気長に待ちましょう。)
「お客様のアカウントを Amazon SES サンドボックスから移動いたしました。」との記載があれば問題無く利用できる状態になっていると思います。

pythonのpip installで「error: Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for Visual Studio"」て言われるの対処法

f:id:ysmn_deus:20200215172000p:plain

結論から言えばhttps://visualstudio.microsoft.com/ja/downloads/からビルドツールを取得してインストールすればOKです。
ぐぐれば同様の記事など見かけますが、Visual Studio 2017など若干バージョンが違ってたりするので、その辺バージョン上でも問題無いのか一応確認しました。

f:id:ysmn_deus:20200215171340p:plain

基本的にインストーラーの指示に従ってれば良いですが、Visual C++のBuild Toolsが欲しいので下記の「C++ Build Tools」にチェックを入れてインストールしました。

f:id:ysmn_deus:20200215171351p:plain

再起動したら問題無くpip installが通ると思います。

Ryzenで組んだPCでDockerをインストールするときに詰まったところ

f:id:ysmn_deus:20200131142114p:plain

どうも、靖宗です
RyzenでPCを組んでセットアップしていたのですが、Docker(Toolbox)をインストールするときに何カ所か詰まりました。

AMDのCPUでHyper-Vを有効化するとVMがうまく起動しない

これなんとかして欲しい所ではありますが、今のところあんまり有効な手立てはないようです。
諦めてHyper-Vを無効化してVMを動かすしか無さそうです。Win10Pro買っちまったよ・・・_(:3 」∠ )_

たぶんHyper-Vを意識的に有効化してない人はなにもしなくていいんでしょうが、自分は無意識のうちにHyper-Vを有効化していたようです。
とりあえずHyper-V関連の機能を無効化します。

Windowsの機能のHyper-Vを切る

この操作が必要かあやしいんですが、自分は一応したので書いときます。
まずコントロールパネルの「プログラム」→「プログラムと機能」の「Windowsの機能の有効化または無効化」→「Hyper-V」のチェックを外す
という操作をしておきます。

f:id:ysmn_deus:20200131140918p:plain f:id:ysmn_deus:20200131141644p:plain f:id:ysmn_deus:20200131141654p:plain

たぶん再起動が求められます。

コマンドで機能を無効化する

上記の操作だけではまだ正しくVMが作成できなかったので、下記の操作を行います。
コマンドプロンプトを管理者モードで起動して

dism /Online /Disable-Feature:Microsoft-Hyper-V

というコマンドを実行します。
一応ここで再起動します。再起動後に下記のコマンドを実行します。

bcdedit /set hypervisorlaunchtype off

これでDockerのVMが正しく起動する環境が整ったと思います。
上記のコマンドに関しては下記のStackOverFlowを参考にしました。

stackoverflow.com

インストールするDockerのバージョンをちょっと古いヤツにする

なにやら新しいDocker Toolboxではうまいこといかないそうなのでちょっと古いバージョンにしておきます。
自分は"v18.06.1-ce"を選択しました。下記のDocker Toolboxのリリースからダウンロードします。

github.com

基本的にウィザードに従ってインストールで問題無いかと思います。
バージョンの選定に関しては下記の記事を参考にさせていただきました。

hepokon365.hatenablog.com

AWS SAMでCognito認証のPOSTが通らなかった

f:id:ysmn_deus:20190318182949p:plain

どうも、靖宗です。
docker-lambdaで開発して、コンソールからLambdaをデプロイするというちょっとアレな運用を直すべくSAM CLIを利用し始めました。
そこまでは良かったものの(逆になんで使って無かったんだ?というぐらい快適だしCloudFormation最高)、Cognitoとの連携をやり始めてCORSでPOSTするAPIがうまくいかず悩んでました。

とは言っても基本的には全てリクエストに情報は載っているもの。
調べて見るとPOSTの手前のOPTIONSリクエストでCognito認証がはじかれてる模様。
axiosでPOSTリクエストを送っている環境下だったので、わざわざOPTIONSのリクエストを描いてヘッダーにトークンを・・・というのはなんだか解決方法として間違ってる気がしたので執拗にウェブをあさっておりましたら該当する情報にたどり着きました。ありがたや。

nibral.hateblo.jp

SAMのテンプレートのAPI Gatewayの箇所にAddDefaultAuthorizerToCorsPreflightという項目を追加しfalseに設定すれば良いとのこと。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
  CognitoUserPoolArn:
    Type: String
    Default: arn:aws:cognito-idp:~~~(該当するARNを入力)
  StageName:
    Type: String
    Default: dev

Globals:
  Function:
    Timeout: 3

Resources:
  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref StageName
      Auth:
        DefaultAuthorizer: CognitoAuthorizer
        AddDefaultAuthorizerToCorsPreflight: false
        Authorizers:
          CognitoAuthorizer:
            UserPoolArn: !Ref CognitoUserPoolArn
      Cors:
        AllowOrigin: "'*'"
        AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
        AllowMethods: "'OPTIONS,POST,GET'"
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ../../built(該当する箇所のパス)
      Handler: (該当ハンドラ)
      Runtime: nodejs10.x
      Events:
        Api:
          Type: Api
          Properties:
            Path: /post
            Method: post
            RestApiId: !Ref ApiGateway

Outputs:
  Region:
    Description: "Region"
    Value: !Ref AWS::Region
  ApiId:
    Description: "API ID"
    Value: !Ref ApiGateway
  ApiUrl:
    Description: "API endpoint URL"
    Value: !Sub 'https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${StageName}/'

これで問題無くAPIが使える筈です。

AmplifyのLambdaでデフォルトでTypeScript使えるようにならんかなぁ・・・(:3 」∠ )

MinecraftサーバーをAWSのEC2(Amazon Linux 2)で立ち上げる

f:id:ysmn_deus:20190904114458p:plain

どうも、靖宗です。
友人との話で度々「マイクラサーバー立てる」と言って無視してきた日々に終止符を打つべくAWSを利用してマイクラサーバーを立てることにしました。
料金的な観点で言えば動かしっぱなしにするなら絶対VPS(かLightsail)の方がいいんですが、EC2に慣れ親しむというのと拡張性(EC2だとインスタンスの性能がすぐ変えられる)という点でEC2をチョイスしました。
なので、これに当てはまらない方はVPSを選びましょう。

EC2でインスタンスを立ち上げる

この辺は記事が腐るほどあると思いますので割愛。
気が向けば別記事にします。
あと、もしかしたらAMIが転がってるかも。

インスタンスの選定

他の記事などで「small以上じゃないと動かない」という報告をいくつか見受けました。
自分は疑り深いので、敢えてt3.microで実行してみました。
Xmx900M Xms512M(最大メモリ900MB、最小メモリ512MB)で実行してみると、起動はするのですが非常にラグ(ブロックを破壊したのに破壊したことにならない)が生じたり、サーバーがクラッシュして落ちたりするところから最小メモリ1024MB程度は確保しておく必要があるのかもしれません。
ただ、この検証は後述するForgeサーバで行っていますので、もしかしたらバニラのサーバーはなんとか動作するかもしれません。

以上より、この記事ではt3.small相当のインスタンス(自分はt3a.smallを利用)することを想定しております。

Minecraft Serverのセットアップ

とりあえずパッケージマネージャーのアップデートと、Javaを入れときます。

sudo yum update -y
sudo yum install java-1.8.0-openjdk.x86_64

次に、Minecraftのサーバー版をダウンロードしてきます。
今回は1.14.4を公式サイトから直接ダウンロードします。

wget https://launcher.mojang.com/v1/objects/3dc3d84a581f14691199cf6831b71ed1296a9fdf/server.jar

たぶんこの辺でディレクトリを作成してその中で作業した方が良いです。
僕は後で後悔しました。

mkdir minecraft_server
mv server.jar minecraft_server/
cd minecraft_server

とりあえず起動してみます。

java -Xmx1024M -Xms1024M -jar server.jar nogui

文句言われて起動しないと思います。
使用ライセンスを許諾するか否かの確認が必要ですので、実行したら作成されるeula.txtを編集します。
eula=falseの箇所をeula=trueにします。

#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
#Fri Aug 11 21:05:32 JST 2017
eula=true

これでサーバーが実行できるようになってる筈です。
先ほどのコマンドで実行します。

java -Xmx1024M -Xms1024M -jar server.jar nogui

これで、EC2のIP(か、ドメインを設定している場合はそのドメイン?)にアクセスすればMinecraftサーバーにアクセスできる筈です。
とりあえずの動作確認ですので、実行したサーバーは終了しておきます。
Ctrl+Cで強制終了するか、コマンド入力できる状態でstopと入力すれば止まります。

Forge Serverにする

MODなどを導入する際にはMinecraft Forgeというものにしておくと便利と聞きます。
実際にどうなのか知りませんが、大体サーバーのセットアップの記事を書いてる人達はForgeを導入しているので一応導入しておきます。
必要最低限構成で動かしたい方はスルーしてください。少々重たくなるかもしれません。
たぶんこいつのせいでt3.microとかが使えないのではないかと思っています。

Forgeのダウンロード

Forgeの公式サイトhttps://files.minecraftforge.net/)からインストーラーをダウンロードします。
参考にしたサイトにはuniversal.jarもダウンロードするよう指示がありましたが、1.14.4ではうまく動作しなかったので不要です。
installer.jarのみダウンロードしてください。

f:id:ysmn_deus:20190904103652p:plain

wgetでダウンロードしたいところですが、広告を読ませるためにリダイレクトする形式になってます。
無料で使えるありがたみをかみしめながら広告を読むぐらいは我慢しましょう。

Forgeインストーラをアップロード

先にForgeのディレクトリを作成しておきます。
通常のサーバーのディレクトリをそのままコピペします。

cd ~
cp -Rp minecraft_server forge_server
cd forge_server

作成したディレクトリにForgeインストーラをアップロードします。
SSHでアクセスしてる場合はSCPかなんかでアップロードしてください。

インストール

インストーラを実行します。

java -jar ./forge-1.14.4-28.0.83-installer.jar nogui --installServer

起動

何はともあれ起動してみます。
参考にしたサイトにはuniversal.jarを起動するよう書かれていましたが、なんか起動しなかった(のと、Webフォーラムで生成された奴を実行しろと書かれていた)ので、生成されたforge-1.14.4-28.0.83.jarを実行します。

java -Xms1024M -Xmx1024M -jar forge-1.14.4-28.0.83.jar nogui

これでしばらくまってサーバーが立ち上がれば問題無いと思います。
念のためMinecraftのクライアントから接続して確かめてみるのも良いと思います。

自動起動+コマンドを用意

メンテナンススクリプトの作成

このサイトを参考にしました。
なぜか大概の方の実行コマンドが最大メモリと最小メモリが同じになっているケースが多いんですが、折角最大と最小を指定出来るので一応分けておきます。
上記の手順に従った方は下記のスクリプトで起動などが可能かと思います。
Forgeサーバーでない方はディレクトリや実行するjarを適宜変更してください。

パーミッション

Minecraftサーバーのみ動かしている方は特に気にしなくてもいい気がしますが一応パーミッションも変更しておきます。

chmod 744 mc_script.sh

実行テスト

スクリプトを作成したらとりあえず手動でスクリプトが実行するか確認します。

sh -x ./mc_script.sh start

Minecraftサーバーの標準入出力はscreenに飛ばされてるので、まずscreenに存在しているか確認します。

screen -ls
There is a screen on:
        2295.minecraft  (Detached)
1 Socket in /var/run/screen/S-ec2-user.

数字とかは適宜変わると思います。

もしサーバー上で直接コマンドを入力したい場合(ホワイトリストの入力とか?)はscreenで接続します。

screen -r minecraft

screenから抜けるときはCtrl+aを押した後にdを押して抜けて下さい。

停止

実行テストが終わったら停止しといてください。

sh -x ./mc_script.sh stop

自動起動の設定

systemdに登録して起動したら実行されるようにしておきます。
/etc/systemd/system/minecraft.serviceを作成します。

sudo vi /etc/systemd/system/minecraft.service

内容は下記の通り

[Unit]
Description=Minecraft Server
After=network.target local-fs.target

[Service]
Type=forking
User=ec2-user
ExecStart=/home/ec2-user/mc_script.sh start
ExecStop=/home/ec2-user/mc_script.sh stop

[Install]
WantedBy=multi-user.target

上記が作成できたら、systemctlコマンドで登録します。

sudo systemctl enable minecraft

これで再起動して接続できれば問題無いかと思います。

動作状況

インスタンスの選定のところで言及しましたが、メモリがまあまあ食ってるみたいです。

free -m
              total        used        free      shared  buff/cache   available
Mem:           1961        1244         443           0         273         566
Swap:             0           0  

余裕を持っての動作でしょうけど、やはり2GBぐらいはメモリを確保しておきたいところです。
なので、VPSMinecraftサーバーを立てる方は、少人数であれば2GB程度は見ておくのが良いのではないでしょうか。

参考

minecraft.server-memo.net

Xiser(エクサー)のステッパーで踏み込む度に音が鳴る対処法(たぶん他の音も直る)

どうも、deus(靖宗)です。
メンタリストDaiGoさんの放送やパレオな男こと鈴木さんのブログをよんでいる人なんかはエクサー社のステッパーを利用している人が多いと思います。
(あとはオリンピック選手?)
ただ、たまに音が鳴るのが気になったので原因調査と対処をしてみました。

対処方法

対処法だけで良いよ!って人が大半だと思いますので先に対処法から書いておきます。
対処1だけであれば別にばらさなくてもいいので、1からやってそれでも直らなければ2もやってみるのをお薦めします。
(ただし、これらをやったからといって確実に直るとは限りませんが)

対処1: シリンダー

必要な物

シリンダーの露出部分の油を拭き取る

本当はパーツクリーナーなどで洗浄の後にグリスを塗布するのが鉄則ではありますが、明らかに分解できないので仕方なく気持ちペーパーで露出部分を拭き取ります。
キッチンペーパーやキムタオルの様な物がベストだと思いますが、ティッシュとかでも別に良いと思います。
たぶん拭かなくてもうまくいきますが、後々のトラブルを避けるために念のため拭き取っておきましょう。

シリンダーの露出部分にグリスを塗布する

シリンダーの露出部分にグリスを塗ります。
全面に広がるように指などで塗り広げて下さい。

f:id:ysmn_deus:20190827102635j:plain
露出している全面にグリスを塗る

運の良い方はコレで異音が直ると思います。

対処2: 接触部分(ボルト周辺、金属同士)

必要な物

パーツクリーナーで綺麗にする

内側のボルトの頭をペンチかウォーターポンププライヤー的な何かで押さえながら、外側のナイロンナットをスパナか何かで(こちらもペンチとかで良いけどできればきちんとした工具を使おう)外します。
たぶん多少緩めればあとは手で行ける筈。

部品を外したら、ボルトが刺さっていた箇所とその辺の部品をパーツクリーナーで洗浄します。

f:id:ysmn_deus:20190827095137j:plain

場合によってはシリンダーと接触してる箇所

f:id:ysmn_deus:20190827095300j:plain

も同様に洗浄しておくといいかも。

あと、可能ならステッパー側の穴もパーツクリーナーや綿棒で洗浄しておく。

f:id:ysmn_deus:20190827100337j:plain

グリスアップする

洗浄したら接触部分にグリスを塗布していきます。いわゆる「グリス」と呼ばれる物だったら何でも良いと思います。
付ける箇所は接触部分全般。

f:id:ysmn_deus:20190827101034j:plain

f:id:ysmn_deus:20190827101250j:plain

f:id:ysmn_deus:20190827101416j:plain

f:id:ysmn_deus:20190827101621j:plain

だいたいこんなもんで良いと思います。
もしシリンダーとの接触部分も洗浄していればそこもグリスアップするといいかも?

補足:シリコンスプレーじゃだめなの?

結論から言えばダメです。
このステッパーのボルトの箇所に入っている樹脂ワッシャーの部分はシリコンスプレーでもいいんですが、基本的に金属と金属の潤滑にシリコンスプレーは不向きです。
特に、力のかかる場所ではシリコンワックスは逆に抵抗感になる恐れがあります。今回で言うボルトに塗布した箇所や穴の内側などはシリコンスプレーは逆効果でしょう。

原因調査

そもそも今までどう対処してたか

買った当初から若干気になっており、今まではボルトの両サイドにシリコンスプレー(潤滑剤)を吹いて済ましていました。
上でダメって言っておきながらですが、ばらすのがめんどかったので・・・
(樹脂ワッシャー部分のこすれだと思っていたというのもありますが)

f:id:ysmn_deus:20190827094418j:plain
これでも多少はマシになることがある

ただ、今回これでは改善しない謎のコツコツ感?みたいなのを感じたのでいっそのことボルト周りを綺麗にして確かめてみます。
今回は右側のみ異音を感じたので右側のみ対処しました。

パーツクリーナーで綺麗にする

内側のボルトの頭をペンチかウォーターポンププライヤー的な何かで押さえながら、外側のナイロンナットをスパナか何かで(こちらもペンチとかで良いけどできればきちんとした工具を使おう)外します。
たぶん多少緩めればあとは手で行ける筈。

部品を外したら、ボルトが刺さっていた箇所とその辺の部品をパーツクリーナーで洗浄します。

f:id:ysmn_deus:20190827095137j:plain

場合によってはシリンダーと接触してる箇所

f:id:ysmn_deus:20190827095300j:plain

も同様に洗浄しておくといいかも。

あと、可能ならステッパー側の穴もパーツクリーナーや綿棒で洗浄しておく。

f:id:ysmn_deus:20190827100337j:plain

現段階で音は鳴るか

潤滑油とか付けてないんで結構なる筈なんですが、意外と大きな音はなりませんでした。

グリスアップする

洗浄したら接触部分にグリスを塗布していきます。いわゆる「グリス」と呼ばれる物だったら何でも良いと思います。
付ける箇所は接触部分全般。

f:id:ysmn_deus:20190827101034j:plain

f:id:ysmn_deus:20190827101250j:plain

f:id:ysmn_deus:20190827101416j:plain

f:id:ysmn_deus:20190827101621j:plain

だいたいこんなもんで良いと思います。
もしシリンダーとの接触部分も洗浄していればそこもグリスアップするといいかも?

でもまだ音が鳴る!

組み付けてみましたがまだ音が鳴る・・・
原理的に接触部分にはグリスで潤滑してるはずなのでそれ以外、という事はシリンダーか!

左右反転してみる

シリンダーは前後逆(180度回転)しても取り付けられるので、左右のシリンダーが逆になるようにセットしてみました。
すると案の定、今度は左のみ音がなる(一瞬の抵抗感?がある)ようになりました。
詰まり犯人はシリンダー・・・

シリンダーの露出部分にグリスを塗布する

本当はパーツクリーナーなどで洗浄の後に塗布するのが鉄則ではありますが、明らかに分解できないので仕方なく気持ちペーパーで露出部分を拭き取って、グリスを塗布しました。

f:id:ysmn_deus:20190827102635j:plain
露出している全面にグリスを塗る

すると、とうとう音が消えた!!!

なんだったのか

よく考えてみると、自分はステッパーを使っていないときは左だけ押し込んで右がマックス露出してる状態で置いてることが多いです。

f:id:ysmn_deus:20190827102433j:plain

なので、露出してる側のグリスが劣化して異音が鳴るようになったのでしょう。

Nuxt.jsが2.9になってからTypeScriptの対応が変わったようです。

f:id:ysmn_deus:20190719124755p:plain

どうも、靖宗です。
一生環境構築してる気がします。フロントもう嫌や・・・
ということでTypeScriptの対応がなにやら変わった?ようなので公式に沿ってセットアップしてみます。

Nuxtプロジェクトのセットアップ

ここに関してはいつも通りです。
よければ以前の記事をどうぞ。

TypeScriptのセットアップ

公式サイトのSetupに沿って進めます。
まずは必要なパッケージのインストールをyarnで行います。

yarn add -D @nuxt/typescript-build @nuxt/types

コンフィグファイルnuxt.config.js編集

コンフィグファイルを編集します。

buildModulesという項目に@nuxt/typescript-buildを追加します。

...
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module',
    '@nuxt/typescript-build'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
...

tsconfig.jsonの追加

tsconfig.jsonを追加します。
一応tscコマンドで追加しますが普通に作成して大丈夫だと思います。

tsc --init

一応ここまでの設定で動作はするようです。

nuxt.configをtsにする

これもうjsのままの方がええんでない?って気もしてきましたが、一応対応します。

必要パッケージのインストール

nuxt.configをtsにする場合はnode環境にもTypeScript対応が求められますので@nuxt/typescript-runtimeが必要になります。
yarnで追加していきますが、-Dではなく普通に依存関係に追加するようです。

yarn add @nuxt/typescript-runtime

package.jsonの編集

yarn devの実行をnuxtからnuxt-tsに変更します。

...
  "scripts": {
    "dev": "nuxt-ts",
    "build": "nuxt-ts build",
    "start": "nuxt-ts start",
    "generate": "nuxt-ts generate",
...

以上でNuxt.jsでTypeScriptを利用できるようになるみたいです。
煩雑なパッケージ関係が整理された感じではありますが、ちょっと手間が増えた感もありますね。
そのうちnuxtのウィザードに追加されそうな気はします。

ついでにLintにも対応する

つまり以前の記事はもう古い。もうしわけないです・・・

パッケージのインストール

これも必要なパッケージがあるのでインストールします。

yarn add -D @nuxtjs/eslint-config-typescript

.eslintrc.jsを編集

.eslintrc.jsに先ほどのパッケージ情報を追加していきます。

...
  extends: [
    '@nuxtjs',
    '@nuxtjs/eslint-config-typescript',
    'prettier',
    'prettier/vue',
    'plugin:prettier/recommended',
    'plugin:nuxt/recommended'
  ],
...

Prettier周りでたまに前後関係が効いてくる場合があるので念のため、Prettierよりは前に追加しました。

package.jsonを編集

package.jsonにlintのコマンドが記載されていますので、それを編集しておきます。といっても.tsを付け加えるだけですが。

...
    "lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .",
...

試しにyarn lintを実行するとnuxt.config.tsがチェックされているのが分かります。

parserの変更

parserがbabel-eslintのままだと色々ESLintに怒られる時があります。なのでparserを@typescript-eslint/parserに変更しておきます。
まずは必要なパッケージをインストールします。

yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin

.eslintrc.jsを編集

parser: 'babel-eslint'

を消去して

  parserOptions: {
    parser: '@typescript-eslint/parser'
  },

を追記します。また、plugins'@typescript-eslint'を追加しておきます。

vueファイルなどにも対応

vueファイルではscriptタグにlang属性を付与することでTypeScriptとしてvueファイルのスクリプトを記載することができます。
ですが、lang="ts"を付けるだけではCannot find moduleとか怒られるのでその辺を対応します。

本当はtsconfig.jsonincludeオプションを利用することで解決できるかと考えていましたが、どうにも解決しませんでしたので

qiita.com

こちらを参考にして、srcディレクトリにshims-vue.d.tsを作成し、tsconfig.jsonfileを追加することで対応しました。
これでたぶんnuxt開発ができる筈!

参考

qiita.com

qiita.com

qiita.com