20201125のAWSに関する記事は30件です。

ELBのhealth checkが永久にunhealthに・・・

久しぶりに記事を投稿させて頂きます!やっとポートフォリオの作成が一段落して、転職活動中なのですが、一段落したので書かせていただきます。今回の内容は検索しても中々原因を見つけられず、たまたま原因を発見したので、初学者の方で同じように詰まっている方向けに簡単にアウトプット致します!

内容

今回railsで作成したポートフォリオをEC2上にnginxとともに立てました。それから、acmを利用するためにelbを導入したのですが、elbを立ててEC2上のnginxを再起動してもelbのhelth checkがunhealthに・・・。nginxのlistenポートやその他設定を何度確認するも分からず・・・。

原因

nginx側でhttp2を認識していないことが原因でした。これだけで半日使ってしまいました・・・

解決

elbの作成時にターゲットグループのprotcol versionを1に落として作成したところ解決しました!あと、試してはないのですが、こちらの記事でnginxをhttp2でlistenするようにした方がベターかもしれません!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

すでに作ったLaravelプロジェクトにLaradockいれてEC2でデプロイする

背景

Laravelでプロジェクトつくって、EC2にデプロイする手順は下記の通りかと思っています。(間違っていたらすいません)
1.Laradockをいれる。
2.プロジェクトをLaradock配下でcomposerで作成する。
3.作成したプロジェクトをコーディングしていく。
4.githubにあげる。
5.EC2/VPCでgit cloneしてLaradock起動する。

最初にLaradockで作っていくのが良い例かと思いますが、
初心者であった自分はdockerはポートフォリオ作成と並行して勉強していたので、あとからdockerをプロジェクトに入れることが必要になりました。。。
Laradockを最初から使わずに制作していた自分みたいな人にむけて、他の人の参考にでもなればと思い、メモとして残しておきたいと思います。

参考にしたサイト

大いに参考にさせていただいたサイトは次のものです。
既存のLaravelプロジェクトにLaradockを導入する方法は下記のとおりです。

A : https://qiita.com/segur/items/600eaef70fef896f2d0d
このあとにLaradockのsubmoduleが読み込まれないところで詰まった点については下記のサイトを参考にしました。
B : https://karoten512.hatenablog.com/entry/2017/11/09/013845

手順

メモなので、ざっと書きます。
手順は下記の13の手順です。
①すでにローカル環境でLaravevlプロジェクトを作成する。
② 参考サイトAを参考にルートプロジェクト下にLaradockを入れる。(git submoduleする)
③ githubにLardockを入れたプロジェクトごとpushする。(git push(
④ AWS/EC2を起動する。その時使ったインスタンスは,t2.smallです。理由はcomposer installするときにt2.microだと固まってしまうからです。(EC2/VPCの作成)
⑤ インスタンス内で参考サイトBをgit clone --recursive{git repository url}をする。
⑥ git cloneしたプロジェクト配下にlaradockがあるので、そのなかにcd(cd プロジェクト/laradock)
⑦ docker-composeでイメージ立ち上げる。(docker-compose up -d nginx mysql)
⑧ ルート権限にする。(sudo su)
⑨ docker-compose exec workspace bashで作業ディレクトリに入る
⑩ rootで/home/ubuntu/プロジェクト名/laradock に移動して、composer install
⑪ php artisan key:generateする。
⑫ EC2のグローバルIPにブラウザでアクセスする。
⑬ 作ったアプリが確認できます。

終わりに

次からはDockerイメージ作成してからプロジェクト作成します。。。
以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS 上でマルチアカウントで複数サービスをホストする場合のアーキテクチャパターン (1)

はじめに

AWS 上でマルチアカウントで複数サービスをホストする場合のアーキテクチャパターンを紹介します。
書いてみると改めて長くなってしまったので、この記事はシングルアカウントでのパターン紹介です。

シングルアカウントの場合

まず、マルチアカウントの前に、シングルアカウント(AWSのアカウントIDが1つ。その上に複数サービスをホスト)の場合のパターンを考えてみます。

ALBをフロントにして、ALBのルーティングでサービスを分けるパターン

構成図だとこんな感じです。
ALBのルーティング機能で、パスごとにリクエストを分けています。
この構成図だとシンプルにパスでルーティングを変えていますが、HTTP Header に応じて、ルーティング先を変えるといったことも可能です。

ルーティング先は、EC2でもコンテナでもLambdaでも、ALBのターゲットグループが対応しているリソースであれば、柔軟に変更可能です。

image.png

もしかすると、ALB + Lambda で「あれ?」と思われた方もいるかもしれません。
ALB + Lambda より、API Gateway + Lambda のパターンの方が多いからですかね? それもやってみましょう。

API Gateway(HTTP API)をフロントにするパターン

API Gatewayには、HTTP API と REST API の2種類あり、どちらも考えてみます。(正確にいうと、WebSocketにもAPI Gatewayは対応しています)

パスごとにリソースを作成する方法

HTTP APIは、API Gateway のバックエンドに、内部ALB、CloudMap、内部NLBを指定できるため(REST APIは、NLBのみ)
パスごとに、リソースを分けるパターンです。

image.png

App2はコンテナで実装しているので、ELBを利用せず Service Discovery(Cloud Map)を利用する図になっていますが、App1と同様にELBでも問題ありません。
ELBは App2専用のELBを作ってもいいですが、そうすると、最初の図のようにELBをApp1とApp2で共有したなくなってくることがあります。それが次の構成図です。

ALBは共有するパターン

API Gatewayにて、path1とpath2向けのトラフィックは、共有のALBに渡します。
ALBでリクエストの中身を見て、path1ならApp1、path2ならApp2にトラフィックをルーティングするようにします。

image.png

こうすると、最初のALBをフロントに置くパターンと同じでは?API Gatewayというコンポーネントが増えるだけなのではと思われるかも知れませんが、
API Gateway にはスロットリング、キャッシュ、認証機能(Cognito Userpool, OIDC連携、Lambdaを使ったカスタム認証)などALBにはない機能があるので、それらの機能が必要で、App側に極力実装せずに、API Gateway側にオフロードしたい場合には有効なアーキテクチャです。

API Gateway(REST API)をフロントにするパターン

こちらも少し考えてみます。REST APIは、HTTP APIと違い現時点では、 内部用NLBとしか連携できないという制約があります。

パスごとにリソースを作成する方法

このようにリソースごとにNLBを作成する必要があります。
(一応、App1とApp2でNLBで待受するportを変えると1つのNLBを共有することは可能ですが、ここでは分かりやすさを優先し、NLBを個別に作成しています)

image.png

これを見ると、HTTP APIのほうが良さそうに見えますが、HTTP API は現時点で、AWS WAF に対応していなかったりなどいくつか制約があります。
REST APIのみで使える機能が必須の場合は、HTTP APIは使えません。

(余談)REST API でバックエンドに ALB を使いたい場合

イメージとしては、以下のとおりですが、REST API と 内部ALBの連携機能はサポートしていないため、現時点ではできません。

image.png

じゃあ、どうするかというと、API Gateway --- Public な通信 ---- 外部用ALB な構成にすることで可能です。
こんな感じです。構成図をわかりやすくするために、app1/app2(path1/path2)だけにして、API GatewayもVPC外に出しました。

image.png

こうすることによって、REST API を使って ALBを利用することが可能です。
注意するポイントとしては、前述の通り、 API Gateway -- ALB の通信はパブリック通信になります。
(パブリック接続といっても、ISP網などに出ることはなく、Public IPを使っているだけで AWS内で完結する通信になります)

クライアントがインターネットからAPI Gatewayへアクセスするアプリケーションの場合、
API Gateway -- ALBの通信が Public であること自体を気にすることはそれほど多くないのでは思います。

しかし、API Gatewayを private にしたり、VPC内で全ての通信を閉じるという要件があった場合は、
API Gateway -- ALBの通信が Public であること自体が難しい場合もあります。

API GatewayとALB間がPublicになることが許容済みであった場合

仮に、REST API でバックエンドに ALB を使いたくて、API GatewayとALB間がPublicになることが許容済みであった場合でも、
次の注意ポイントとしては、ALBへの直接アクセスを禁止にする必要があります。
ALBはPublicにあるので、ALBへ直接アクセスできてしまえば、API Gatewayで認証やスロットリングをオフロードしてもなんの意味もなくなってしまいます。
つまり、なんらかの方法でALBへのアクセスはAPI Gatewayからのみ許可するようにしてあげる必要があります。

じゃあ、どうするか。

ALBへのアクセス制御の方法

ALBへのアクセス制御の方法はいくつかありますが、以下の3つが多いような気がします

  • Security GroupによるソースIPアドレス制限
  • AWS WAFによる制限、(ソースIPアドレス、HTTP Headerの制限など)
  • ALBのruleによる制限(ソースIPアドレス、HTTP Headerの制限など)

今回のように API Gateway(REST API) -- pubic ALB の場合は、
ALBから見ると送信元IPアドレスは、アクセス元(クライアント)のIPアドレスではなく、API GatewayのIPアドレスになります。
API GatewayのIPアドレス帯は公開されていない(多分。もし、公開されていた場合でも、変更があった場合に追随するのが大変な)ため、ソースIPアドレスでALBへのアクセス制限を行うのは現実的ではないです。つまり、Security Group による制限は適切ではなさそうです。

その代わりに何をすればいいのかというと、
API Gatewayには 指定したHTTP Headerを付けて、バックエンドに渡すという機能があります。
(もっといいドキュメントがあったはずなので、見つかり次第差し替え予定)
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-method-settings-execution-console.html

これを使うことにで、API Gatewayは 特定の HTTP Header を付けて ALB へリクエストを送ることができるので、
ALBの前段に置いたAWS WAFで HTTP Headerの値をチェックして、問題なければ、ALBに処理させるというのが可能です。

AWS WAF を使わなくても ALB のRuleで、特定のHTTP headerがあるという条件をつけるという方法もあるのですが、

  • 「特定のHTTP headerがある + /path1」 なら App1へ
  • 「特定のHTTP headerがある + /path2」 なら App2へ

という具合に、それぞれのルーティングに「特定のHTTP headerがある」という条件を1つ1つ記載しないといけないので、
純粋にめんどくさいのと、ついつい付け忘れが発生しがちなのと、後述しますが、万が一、HTTP header自体を変更しないといけない自体が発生した場合は、
全ての Rule を変更しないといけない点がオペレーションの観点から煩わしいかもしれません。

なので、個人的には、AWS WAFの料金が許容できるなら、HTTP Headerのチェックは AWS WAFに任せるのが楽かなと思います。

HTTP Headerの注意点

API Gateway で予め決めた HTTP Headerを付加して、ALBへのアクセス制限に用いるのは有効です。
(この方法は、CloudFront + ALB の構成で、ALBへの直接アクセスを防ぎたい場合にもよく使われる方法です)
ただ、これも同様に注意点が必要です。HTTP Headerによるアクセス制限は、合言葉と同じなので、なんらかの方法で第三者にバレてしまうと、ALBに直接アクセスされてしまうため、どういうHTTP Headerにどのような値を入れるのかといった管理は厳密に行う必要があります。
そして、万が一バレてしまった場合を想定して、合言葉(HTTP Header)を変更するオペレーションの練習もしておく必要があります。

以上で余談が長くなってしまいましたが、 REST API で バックエンドに ALB を利用する方法です。

まとめ

(長くなってしまったので、マルチアカウントのパターンは2つ目の記事で書こうと思います)書きました
この記事では、シングルアカウントを前提として、複数のサービスをホストするパターンをざっくり書いてみました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6.0×RDS(MySQL8.0)×Nginx×Unicorn】AWSへのデプロイ手順まとめ

3度目のデプロイなのにほとんどやり方がわかっておらずまた勉強し直したので、その備忘録として投稿します。もう何番煎じか分かりませんが、筆者がハマってしまったエラーとその対策についても細かく書きました。また、なぜインストールするのかについてもまとめました。

環境

  • Ruby 2.7.1
  • Rails 6.0.3.4
  • MySQL 8.0
  • Node.js 10.21.0
  • Unicorn 5.7.0
  • Nginx 1.12.2

前提

EC2とRDSは環境によって差異が少ないため作成手順を省略し、以下を前提とします。

  • AWSでEC2インスタンス作成済み
  • EC2インスタンスへElastic IPを関連付け済み
  • RDSのインスタンス及びデータベース作成済み

EC2へログイン

何度もEC2にログインすることになるので、まずはログインを下記コマンドで行えるように設定します。

ローカル
$ ssh アプリ名_key_rsa

通常の方法でEC2にログイン(鍵はDesktopにあるとします)

ローカル
$ cd ~
$ ssh -i ~/Desktop/my-key.pem ec2-user@***.**.***.** # インスタンスを作成した際に作った公開鍵を指定し、@以下はElastic IPを入力します。

はじめてログインする場合は以下のように聞かれます。
Are you sure you want to continue connecting (yes/no)?
# yesを入力しEnter

ユーザを作成している記事が多いですが、自分しかログインすることを想定していないため作成しません。

ローカルで秘密鍵と公開鍵を作成します。

ローカル
$ cd ~/.ssh
$ ssh-keygen -t rsa

# 以下のメッセージが表示されるので、「アプリ名_key_rsa」と入力
Enter file in which to save the key ():アプリ名_key_rsa

# 何もせずにそのままエンター
Enter passphrase (empty for no passphrase):

# 何もせずにそのままエンター
Enter same passphrase again:

鍵が作成されたことを確認

.ssh(ローカル)
$ ls
# アプリ名_key_rsaとアプリ名_key_rsa.pubが表示されるはずです

設定ファイルを作成

.ssh(ローカル)
vi config

#以下を追記

Host アプリ名_key_rsa
  Hostname Elastic IP #自分のWebサーバーのもの
  Port 22
  User ec2-user
  IdentityFile ~/.ssh/アプリ名_key_rsa #先程作成した秘密鍵

公開鍵の中身をコピー

.ssh(ローカル)
$ cat アプリ名_key_rsa.pub

ssh-rsa AAA***************.local #コピーする

サーバーへ公開鍵の設置
EC2では公開鍵は~/.ssh/authorized_keysに置かれる。

/(サーバー環境)
$ mkdir .ssh
$ chmod 700 .ssh
$ cd .ssh
$ vi authorized_keys

#開いたファイルに先ほどコピーした鍵の中身を上書き
ssh-rsa ~~~~~ .local

:wq で保存&編集完了

.ssh(サーバー環境)
$ chmod 600 authorized_keys
$ exit

ログインできるか確認

ローカル
$ ssh アプリ名_key_rsa

EC2へログインできたら完了です。この先はこのコマンドでEC2へログインします。

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

yum(パッケージマネージャ)をアップデート

/(サーバー環境)
sudo yum update

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

/(サーバー環境)
$ sudo yum install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel ImageMagick ImageMagick-devel epel-release

MySQL8.0のインストール

EC2にデフォルトでインストールされているMaria-DBを削除

/(サーバー環境)
$ sudo yum remove mariadb-libs

yumにMySQL8.0のリポジトリ追加

/(サーバー環境)
$ sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

インストール

/(サーバー環境)
$ sudo yum install --enablerepo=mysql80-community mysql-community-server

さらにmysql-develをインストール

/(サーバー環境)
$ sudo yum install mysql-devel

(注意)

mysql-develをインストールしておかないとbundle install時にmysql2のインストールで失敗します。

bundle_install時のエラー文
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.

インストールされたMySQLのバージョンを確認

/(サーバー環境)
$ yum list installed | grep mysql

# 以下のように表示されたら成功(バージョンは時期により異なるかもしれません)
mysql-community-client.x86_64      8.0.22-1.el7                      @mysql80-community
mysql-community-client-plugins.x86_64
                                   8.0.22-1.el7                      @mysql80-community
mysql-community-common.x86_64      8.0.22-1.el7                      @mysql80-community
mysql-community-devel.x86_64       8.0.22-1.el7                      @mysql80-community
mysql-community-libs.x86_64        8.0.22-1.el7                      @mysql80-community
mysql-community-server.x86_64      8.0.22-1.el7                      @mysql80-community
mysql80-community-release.noarch   el7-3                             installed  

ログファイル作成

/(サーバー環境)
$ sudo touch /var/log/mysqld.log

Node.js v10インストール

筆者の場合、ローカル環境のNode.jsのバージョンが10.21.0だったのでこれをEC2にインストールする。

Node.js, npm, libuvをインストール

下のコマンドより、これらがインストールされる。この内、npmとlibuvが必要となる。これらがないとこの先railsコマンドを打とうとすると下のようなエラーになる。

/var/www/rails/アプリ名(サーバー環境)
Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)

補足するとNode.jsが必要ないというのは、このコマンドでインストールされるNode.jsが古いバージョンなためです。では、インストールします。

/(サーバー環境)
$ sudo amazon-linux-extras install epel
/(サーバー環境)
$ sudo yum install nodejs npm --enablerepo=epel

ここでインストールされたnode.jsは6.17だったので、10.21.0にバージョンを変更する。

nvm(パッケージマネージャ)をclone

/(サーバー環境)
$ git clone https://github.com/creationix/nvm.git ~/.nvm

パスを通す

/(サーバー環境)
$ source ~/.nvm/nvm.sh

(注意)

一度EC2からログアウトするとnvmコマンドが使えなくなるので、もう一度パスを通します。

インストール可能なNode.js一覧を表示し、自分のインストールしたいバージョンがあるか確認

/(サーバー環境)
$ nvm ls-remote

インストール

/(サーバー環境)
$ nvm install 10.21.0

使用するバージョンを指定

/(サーバー環境)
$ nvm use v10.21.0

バージョンの確認

/(サーバー環境)
$ nvm use v10.21.0

(注意)
ここで、古いバージョンのNode.jsのままデプロイをすると、下のようなエラーが起こるので、ローカルでインストールしたバージョンと同じものをインストールするのが無難。

エラーログ
ActionView::Template::Error (Autoprefixer doesn’t support Node v6.17.1. Update it

yarnのインストール

Rails6.0から標準となっているwebpackの実行環境を構築するため、yarnをインストールします。ちなみにwebpackが動くためにはyarnとnode.jsが必要になります。

yarnのインストール

/(サーバー環境)
curl -o- -L https://yarnpkg.com/install.sh | bash

パスを通す

/(サーバー環境)
source ~/.bashrc

インストールできたか確認

/(サーバー環境)
yarn -v

(注意)

yarnを入れ忘れるとしたのよなエラーになりハマります

エラーログ
ActionView::Template::Error (Webpacker can't find application in /var/www/rails/live_share/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
   unless you are using the `webpack -w` or the webpack-dev-server.
2. webpack has not yet re-run to reflect updates.
3. You have misconfigured Webpacker's config/webpacker.yml file.
4. Your webpack configuration is not creating a manifest.
Your manifest contains:

rbenvのインストール

/(サーバー環境)
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

ruby-buildのインストール

/(サーバー環境)
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv rehash

Rubyのインストール

rubyのインストールはきちんとローカルで使っているバージョンをインストールする。(ローカルで.ruby-versionというファイルを確認)

/(サーバー環境)
$ rbenv install -v 2.7.1
$ rbenv global 2.7.1
$ rbenv rehash
$ ruby -v

RDSへの接続確認

念の為RDSへ接続できるか確認しておきます。

/(サーバー環境)
$ mysql -h エンドポイント -P 3306 -u root -p

# 下のように表示されれば成功
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1037
Server version: 8.0.20 Source distribution

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

エンドポイントはAWSへログインし、RDS→データベース→接続とセキュリティに記載があります。
スクリーンショット 2020-11-24 19.28.50.png

接続できない場合はRDSのセキュリティーグループを確認

GitHubとの連携

ホームディレクトリに.gitconfigを作成し、編集する。

/(サーバー環境)
$ cd ~
$ vi .gitconfig

# .gitconfigの中身編集
[user]
  name = your_name #gitに登録した自分の名前
  email = hoge@hoge.com #gitの登録メールアドレス

[alias] #好きなようにカスタマイズします。
  br = branch
  co = checkout
  st = status

[color] #色付け
  ui = true

[url "github:"] #pull、pushのための設定
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:

esc + :wqで保存して終了

gitとの接続に必要な鍵の生成

EC2サーバーにログインする際にローカルで行った作業をEC2サーバー上で行います。

公開鍵と秘密鍵の作成

/(サーバー環境)
$ cd ~
$ chmod 700 .ssh
$ cd .ssh
$ ssh-keygen -t rsa

以下のメッセージが表示されるので、「aws_git_rsa」と入力
Enter file in which to save the key ():aws_git_rsa

何もせずにそのままエンター
Enter passphrase (empty for no passphrase):

何もせずにそのままエンター
Enter same passphrase again:

鍵が生成されていることを確認

.ssh(サーバー環境)
$ ls
aws_git_rsa aws_git_rsa_pub

設定ファイルを編集

.ssh(サーバー環境)
$ vi config

# 以下のように編集
Host github github.com
  Hostname github.com
  User git
  IdentityFile ~/.ssh/aws_git_rsa

esc + :wqで保存して終了

作成した公開鍵をgithubに登録

公開鍵をコピー

.ssh(サーバー環境)
$ cat aws_git_rsa.pub

ssh-rsa AAAAB3NzaC1yc*************compute.internal #コピーする

githubのページで右上のアイコン→Setting→SSH and GPG keys→new SSH keyをクリック

スクリーンショット 2020-11-24 5.56.19.png

Githubに公開鍵を登録します。
title: 何の鍵なのか分かるように名前をつける
key: 先程コピーした公開鍵の貼り付け

スクリーンショット 2020-11-24 6.02.31.png

gitへ接続可能か確認

.ssh
# ターミナルへ戻り設定ファイルの権限を変更
$ chmod 600 config

$ ssh -T git@github.com

# 接続してしたのような反応が返ってきたら成功
Hi shun0211! You've successfully authenticated, but GitHub does not provide shell access.

アプリのclone

いよいよアプリをcloneしますが、その前に2点確認を行います。

アプリをcloneする前に①

アセットコンパイルの設定を変更

config/environments/production.rb
 config.assets.compile = true

これをしないとアセットコンパイルが行われず、デプロイ後にアクセスしても下のようなエラーがでます。

エラーログ
ActionView::Template::Error (The asset "application.css" is not present in the asset pipeline.):

アプリをcloneする前に②

cssなどで背景画像を挿入している場合、下のように記述している場合が多いと思いますが、アセットパイプラインを使用した場合、画像の名前が変わるためアクセスできなくなってしまうため、Railsのヘルパーメソッドを使う必要がります。

sassファイル
.class{
  background-image: url(/assets/thumbnail.png)
}

背景画像を指定している場合は以下のように修正する。

sassファイル
.class{
  background-image: image-url(/assets/thumbnail.png)
}

いよいよclone

準備が整ったのでサーバーにcloneします。
アプリを配置するディレクトリを作成

/(サーバー環境)
$ sudo mkdir var/www
$ sudo mkdir var/www/rails
$ sudo chown ec2-user var
$ cd var/
$ sudo chown -R ec2-user www
$ cd /var/www/rails

githubのリポジトリに行き、clone用のパスをコピー
スクリーンショット 2020-11-24 20.36.20.png

実際にcloneします。

/var/www/rails(サーバー環境)
$ git clone git@github.com:~~~~~~
$ cd アプリ名
$ bundle install

問題なくbundle installできれば成功です。ここでエラーが出ることが多いですが、ググればたくさん記事がヒットするのであきらめず試行錯誤すれば必ず解決するはずです。

本番環境でmaster.keyファイルを作成

master.keyはセキュリティ上の問題からデフォルトでgitの管理対象から外れているので、本番環境にはありません。そのため、自分で作成します。

/var/www/rails/アプリ名(サーバー環境)
vim config/master.key

# ローカルにあるmaster.keyの中身をコピペ
************************************

esc + :wqで保存して終了

Unicornの設定

まずはインストール

/var/www/rails/アプリ名(サーバー環境)
vim Gemfile

# Gemfile編集
group :production, :staging do
    gem 'unicorn'
end

esc + :wqで保存して終了

/var/www/rails/アプリ名(サーバー環境)
$ bundle install

設定ファイルを作成

/var/www/rails/アプリ名(サーバー環境)
$ vi config/unicorn.conf.rb

# 以下のように設定ファイルを編集
# set lets
  $worker  = 2
  $timeout = 30
  $app_dir = "/var/www/rails/<アプリ名>" #自分のアプリケーション名
  $listen  = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
  $pid     = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
  $std_log = File.expand_path 'log/unicorn.log', $app_dir
  # set config
  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid
  # loading booster
  preload_app true
  # before starting processes
  before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        Process.kill "QUIT", File.read(old_pid).to_i
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
  end
  # after finishing processes
  after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  end

esc + :wqで保存して終了

Nginxの設定

Nginxのインストール

/(サーバー環境)
$ sudo amazon-linux-extras install nginx1.12 -y

Nginxの自動起動設定

/(サーバー環境)
$ sudo systemctl start nginx # Nginx起動
$ sudo systemctl enable nginx # 自動起動の設定
$ systemctl status nginx # 起動確認

設定ファイルの作成

/(サーバー環境)
$ cd /etc/nginx/conf.d/
$ sudo vi アプリ名.conf

# 以下のように設定ファイルを編集
# log directory
error_log  /var/www/rails/<アプリ名>/log/nginx.error.log; #自分のアプリケーション名に変更
access_log /var/www/rails/<アプリ名>/log/nginx.access.log; #自分のアプリケーション名に変更

upstream unicorn_server {
    server unix:/var/www/rails/<アプリ名>/tmp/sockets/.unicorn.sock fail_timeout=0; #自分のアプリケーション名に変更
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name ~~~.~~~.~~~.~~~; #アプリのElastic IPに変更

    keepalive_timeout 5;

    # Location of our static files
    root /var/www/rails/<アプリ名>/public; #自分のアプリケーション名に変更

    location ~ ^/assets/ {
        root /var/www/rails/<アプリ名>/public; #自分のアプリケーション名に変更
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/rails/<アプリ名>/public; #自分のアプリケーション名に変更
    }
}

esc + :wqで保存して終了

データベースの設定

環境変数を使うため、これを管理するためのGemを導入

/(サーバー環境)
$ cd /var/www/rails/アプリ名
$ vi Gemfile

# Gemfile編集
gem 'dotenv-rails'

esc + :wqで保存して終了

/var/www/rails/アプリ名(サーバー環境)
bundle install

.envファイルの作成

/var/www/rails/アプリ名(サーバー環境)
vim .env

# .envファイルを編集
DB_NAME=データベース名_production #RDSで作成したDB名
DB_USERNAME=root #RDSのユーザー名
DB_PASSWORD=********* #RDSのパスワード
DB_HOSTNAME=***.ap-northeast-1.rds.amazonaws.com # RDSのエンドポイント

esc + :wqで保存して終了

環境変数が設定されたか確認

/var/www/rails/アプリ名(サーバー環境)
$ source .env
$ echo $DB_NAME
$ echo $DB_USERNAME
$ echo $DB_PASSWORD
$ echo $DB_HOSTNAME

database.ymlを編集

/var/www/rails/アプリ名(サーバー環境)
$ vi config/database.yml

# 以下を編集
production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOSTNAME'] %>

esc + :wqで保存して終了

(注意)

後々エラーに悩まされたくないので、ローカルのdatabase.ymlも編集しておくのがベター

データベースを起動

/var/www/rails/アプリ名(サーバー環境)
$ sudo service mysqld start

アプリの起動

マイグレーションしてテーブルを作成します。

/var/www/rails/アプリ名(サーバー環境)
$ bundle exec rake db:migrate RAILS_ENV=production

コンパイル実行
CSSファイルやJSファイル、imageファイルをプリコンパイル
これをしないと本番環境でCSSファイルなどが読み込まれない。

/var/www/rails/アプリ名(サーバー環境)
$ bundle exec rake assets:precompile RAILS_ENV=production

Nginx再起動

/var/www/rails/アプリ名(サーバー環境)
$ sudo service nginx restart

Unicorn起動

/var/www/rails/アプリ名(サーバー環境)
$ bundle exec unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production

ブラウザでElastic IPにアクセスしてアプリが表示できていればデプロイ完了です!!
お疲れさまでした。

補足

エラー画面が表示される場合、まずはエラーログを確認します。

/var/www/rails/アプリ名(サーバー環境)
$ tail -n 30 log/production.log

そこで出ているエラー文をググりながら試行錯誤します。
そのままでは変更が反映されないため、一度Unicornのプロセスをkillする必要があります。

Unicornのプロセス確認

/var/www/rails/アプリ名(サーバー環境)
ps -ef | grep unicorn | grep -v grep

# 下のようにプロセスが表示されるので、この内masterのプロセスID(この場合16066)をコピー
ec2-user 16066     1  0 13:48 ?        00:00:02 unicorn_rails master -c /var/www/rails/live_share/config/unicorn.conf.rb -D -E production
ec2-user 16072 16066  0 13:48 ?        00:00:06 unicorn_rails worker[0] -c /var/www/rails/live_share/config/unicorn.conf.rb -D -E production
ec2-user 16073 16066  0 13:48 ?        00:00:06 unicorn_rails worker[1] -c /var/www/rails/live_share/config/unicorn.conf.rb -D -E production

プロセスをkill

/var/www/rails/アプリ名(サーバー環境)
$ kill 16066

再度Unicorn起動

/var/www/rails/アプリ名(サーバー環境)
$ bundle exec unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production

そしてブラウザでIPアドレスにアクセスし、まだ表示されないなら再度エラーログを確認し・・・の繰り返しです。中々苦しい作業ですが、ググれば色んなパターンの解決法がたくさん出てくるのであきらめずに粘りましょう!

参考

https://qiita.com/miriwo/items/eb09c065ee9bb7e8fe06!
https://qiita.com/Yuki_Nagaoka/items/dbb185feb6d4f051c2f2#6unicorn%E3%81%AE%E8%A8%AD%E5%AE%9A
https://qiita.com/paranishian/items/bddaed7c3aacedb11967
https://qiita.com/azusanakano/items/771dc9919f347de061d7
https://railsguides.jp/asset_pipeline.html
https://qiita.com/oishihiroaki/items/bc663eb1282d87c46e97

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2を複製(コピー)したい場合に「同様のものを起動」ボタンという罠

小ネタです。
EC2インスタンスを複製、コピーしたい場合に、

  • AMI(イメージ)の作成
  • ↑で作成したAMIからEC2を作成

という手順をするのが正解ですが、「同様のものを起動」 という、一発でコピーしてくれそうなボタンがあります。

インスタンス___EC2_Management_Console.png

が、これは罠で、インスタンスのコピーではなく、一部設定のみを引き継ぐ、というものです。EC2内部のファイル諸々はコピーされません。

AWSのdoc

[Launch More Like This (同様のインスタンスをさらに起動)] ウィザードオプションでは、選択されたインスタンスは複製されません。一部の設定が複製されるのみです。インスタンスのコピーを作成するには、最初にインスタンスから AMI を作成して、AMI からさらに多くのインスタンスを起動します。

残念。

私達が本当に欲しい、

  • AMI(イメージ)の作成
  • ↑で作成したAMIからEC2を作成

をまとめてやってくれる機能はまだ(2020/11現在)ありません。残念。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】CloudFrontで署名付きURLの作成方法(プライベートコンテンツの配信)

導入

CloudFrontでプライベートコンテンツを配信する場合、署名付きURLを発行する必要性がある。
署名付きURLを発行することによって、下記のことを設定することが出来る。

  • URLに期限をつけることが出来る。
  • URLを知っているだけではアクセス出来ない。

また、CloudFrontで署名付きURLを発行するためには、2つの方法がある。

  1. CloudFrontキーペアを使用する方法
  2. 信頼されたキーグループを使用した方法

1の方法は、以前から存在していたが、
CloudFrontキーペアを作成するにあたって、AWSのrootユーザーを使用しなければならないということもあり、現在は 非推奨 の方法となっている。

2の方法は、最近追加された方法で、
CloudFrontのAPIを使用すれば、キーペアの作成やローテーションの自動化をすることができ、AWSのrootユーザーを使用せずに(IAMユーザーで)使用することが可能となっている。

今回は、2の方法を使用し署名付きURLを発行してみる。

キーペアの作成

  1. 公開・秘密鍵の作成
  2. CloudFrontに公開鍵のアップロード
  3. CloudFrontキーグループに公開鍵の追加

1. 公開・秘密鍵の作成

# 2048ビット長のRSAキーペアをprivate_key.pemという名称で保存
$ openssl genrsa -out private_key.pem 2048

# private_key.pemから公開鍵をpublic_key.pemという名称で出力
$ openssl rsa -pubout -in private_key.pem -out public_key.pem

# 公開鍵の登録で使用するのでクリップボードにコピー
$ cat public_key.pem | pbcopy

次から、AWSのコンソールで操作します。

2. CloudFrontに公開鍵のアップロード

CloudFrontのパブリックキーページにアクセスし、「Add public key」をクリック。
https://console.aws.amazon.com/cloudfront/home#publickey:

Key name:任意の名称
Key value:public_key.pemの内容
Comment:コメント(任意)

3. CloudFrontキーグループに公開鍵の追加

CloudFrontのキーグループページにアクセス、「Add key group」をクリック。
https://console.aws.amazon.com/cloudfront/home#kgconfig:

Key group name:任意の名称(識別子として使用される)
Comment:コメント(任意)
Public keys:先程追加した、公開鍵を選択肢、「Add」をクリック。

CloudFront DistributionsにSignerの追加

これで、URLを署名するために必要なキーペアを作成できたので、
次はそれをCloudFrontに適用させる。

適用させるには、
1. 適用させるCloudFrontのDistributionを選択
2. Behaviorの編集で、閲覧者アクセスの制限の設定

1. 適用させるCloudFrontのDistributionを選択

cloudfront.png

2. Behaviorの編集で、閲覧者アクセスの制限の設定

「Behaviors」タブから適用させたいBehaviorsを選択し、「Edit」をクリック。
下記、項目の選択をする。

項目 選択
Restrict Viewer Access Yes
Trusted Key Group or Trusted Signer Trusted Key Group
Trusted Key Groups 作成したキーグループを選択し「Add」

※ オレンジ色で囲まれた部分

behaviors.png

検証

  1. 署名なしで、アクセス
  2. 署名ありで、有効期限内にアクセス
  3. 署名ありで、有効期限外でアクセス

署名付きURLの生成

$ aws cloudfront sign \
--url https://xxxx.cloudfront.net/index.html \
--key-pair-id K3XXXXXXXXXXXX \
--private-key file://PATH/TO/YOUR/private_key.pem \
--date-less-than 2020-11-18T19:30:00+09:00

※ AWS CLIを使用して作成している。
※ 他にもIPアドレス制限や有効開始時刻の設定などのオプションがある。
※ 詳しくは ↓
CloudFront Command Reference

1. 署名なしで、アクセス

エラーになった。

$ curl https://xxxx.cloudfront.net/index.html
<?xml version="1.0" encoding="UTF-8"?><Error><Code>MissingKey</Code><Message>Missing Key-Pair-Id query parameter or cookie value</Message></Error>

2. 署名ありで、有効期限内にアクセス

アクセス出来た。

$ curl https://xxxx.cloudfront.net/index.html?Expires=XXXX&Signature=XXXX&Key-Pair-Id=XXXX
index

3. 署名ありで、有効期限外でアクセス

アクセスが拒否された。

$ curl https://xxxx.cloudfront.net/index.html?Expires=XXXX&Signature=XXXX&Key-Pair-Id=XXXX
<?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access denied</Message></Error>

補足

キーペア(公開鍵と秘密鍵)
秘密鍵:URLやCookieを署名
公開鍵:署名の検証

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2でyum installしようとしたらno space left on deviceが出た

ディスクの利用状況確認

いっぱいだった

df

メモリの利用状況確認

Swap領域(4G)は殆ど使われていなかった

free

Swap領域への割当を減らそう

破棄

swapoff /swapfile
rm /swapfile

作成

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

ちゃんと減っているか確認

free

参考URL
https://qiita.com/cyborg__ninja/items/891a1f5acf7c14237939
https://www.wantanblog.com/entry/2020/04/11/183201

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS] Terraform AWS Provider 3.0.0以降のACM書式変更について

概要

Terraform でACM(AWS Certificate Manager) を使用しSSL証明書を作成する際に、AWS Providerのversionによって書き方が異なっていたため変更点をまとめます。

環境

  • Mac
$ terraform version
Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/aws v3.17.0

Version3.0.0以前

無料証明書の検証用レコードは以下の様に[0]としてリスト形式で記載する必要があります。

https://registry.terraform.io/providers/hashicorp/aws/2.70.0/docs/resources/acm_certificate_validation

resource "aws_route53_record" "example_certificate" {
  name = aws_acm_certificate.example.domain_validation_options[0].resource_record_name
  type = aws_acm_certificate.example.domain_validation_options[0].resource_record_type
  records = [aws_acm_certificate.example.domain_validation_options[0].resource_record_value]
}

3.0.0以降、上記内容でterraform planを実行すると、Error: Invalid indexとしてエラーが返却されます。

Error: Invalid index

  on route53.tf line 36, in resource "aws_route53_record" "example_certificate":
  36:   type = aws_acm_certificate.example.domain_validation_options[0].resource_record_type

This value does not have any indices.

Version 3.0.0以降

公式ドキュメントに記載がある通り、for eachを使用し値を展開する必要があります。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation

resource "aws_route53_record" "example_certificate" {
  for_each = {
    for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }
  allow_overwrite = true
  name = each.value.name
  records = [each.value.record]
  type = each.value.type
  zone_id = data.aws_route53_zone.example.zone_id
  ttl = 60
}

まとめ

少し古めの書籍は基本的に3.0.0より前のversionが多いため、注意が必要です。
困ったら公式ドキュメントを読むことをおすすめします。

https://registry.terraform.io/providers/hashicorp/aws/latest

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 踏み台サーバーを使ったSSH接続の環境構築

はじめに

プログラミングスクールの演習で踏み台サーバー経由で公開されていないサーバーへのアクセスを可能にする環境の構築をしたのでアウトプットもかねてメモを残します。

完成図

スクリーンショット 2020-11-25 13.10.01.png

※サブネットはAZが同じものを利用すると通信のレイテンシを抑えられますが
今回はカリキュラムの構成上異なるAZ間での構築となります。

構築要件

構築要件は以下の通りです。

  • サーバーBはインターネットに公開されていない
  • サーバーA(踏み台サーバー)へのアクセスは、PCからターミナルでSSHで接続できる
  • サーバーBは、サーバーA(踏み台サーバー)からのみアクセスできる

前提

以下のように異なるAZにパブリックサブネットとプライベートサブネットを持つVPCが構築されていることを前提とします。
スクリーンショット 2020-11-25 13.23.00.png

①サーバーA(踏み台サーバー)からのSSHアクセスのみを許可するようにサーバーBに紐づくセキュリティグループの作成と割当て

[EC2のサイドメニュー▶︎ネットワーク & セキュリティ▶︎セキュリティグループ▶︎セキュリティグループの作成]からセキュリティグループを作成します。
スクリーンショット 2020-11-25 15.19.59.png

次にサーバーB(EC2インスタンス)のセキュリティグループの変更をします。
[右クリック▶︎セキュリティグループ▶︎セキュリティグループを変更]から先ほど作成したセキュリティグループを割当ます。
これでサーバーA(踏み台サーバー)からのSSH接続だけを許可するセキュリティグループを割り当てることができました。

②サーバーBの鍵をサーバーA(踏み台サーバー)に転送

$ scp -i ~/.ssh/○○○.pem ~/.ssh/○○○.pem ec2-user@[サーバーA(踏み台サーバー)のパブリックIPアドレス]:.ssh

scp [オプション] コピー元パス 保存先パス  という構成になっています

  • scp -i ~/.ssh/○○○.pem  -iはオプションでssh接続に使用する鍵ファイルを指定しています
  • ~/.ssh/○○○.pem コピー元のパス
  • [サーバーAのパブリックIPアドレス]:.ssh  保存先パス

サーバーA(踏み台サーバー)にSSH接続しサーバーA(踏み台サーバー)からサーバーBにSSH接続する

今までの手順で要件を満たす構築ができているので確認します。

サーバーA(踏み台サーバー)にSSH接続

$ ssh -i ~/.ssh/○○○.pem ec2-user@[サーバーA(踏み台サーバー)のパブリックIPアドレス]

サーバーA(踏み台サーバー)からサーバーBにSSH接続

$ ssh -i ~/.ssh/○○○.pem ec2-user@[サーバーBのプライベートIPアドレス]

以下のように表示されれば接続できています。

  __|  __|_  )
  _|  (     /   Amazon Linux AMI
 ___|\___|___|

最後に

ご覧いただきありがとうございました。
初心者のため間違っている点などありましたらご指摘いただけると幸いです。

参考

scpコマンド
https://qiita.com/chihiro/items/142ebe6980a498b5d4a7

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2でマイナーバージョン指定でpsqlをアップデートする方法

RPMをインストール

sudo rpm -ivh --nodeps https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

AmazonLinux2 はredhat7をベースにしているようなので$releaseverを7に置換

sudo sed -i "s/\$releasever/7/g" "/etc/yum.repos.d/pgdg-redhat-all.repo"

元々入っていたバージョンを削除

sudo yum list installed | grep postgres
sudo yum remove postgresql-11.5-5.amzn2.0.1.x86_64

入れたいマイナーバージョンを指定してインストール

sudo yum install postgresql11-server-11.6 postgresql11-11.6

参考URL
https://qiita.com/libra_lt/items/f2d2d8ee389daf21d3fb
http://h2shiki.hateblo.jp/entry/2016/04/24/170721
http://zaas.hatenablog.com/entry/2020/01/19/122726

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS 認定 ソリューションアーキテクト – プロフェッショナルに向けて

はじめに

難易度が高いといわれているソリューションアーキテクト – プロフェッショナル(SAP)に向けて、計画的に学習できるよう記録をつけていきます。
アソシエイトと比べて問題数や回答時間は増え、合格ラインも引き上げられているため、かなりの学習時間が求められます。
なんとなくでは絶対合格できないため、効果的な学習のをして少しでも合格確率を上げていきます。

学習教材

AWS Web問題集
udemy模擬問題集
AWS認定ソリューションアーキテクト-プロフェッショナル ~試験特性から導き出した演習問題と詳細解説 (日本語)

計画

テキスト→テキスト付属の問題集→Web問題集→udemy疑似問題集 の順番でやっていく。
年内取得は最低限の目標です。
できれば12月中にと考えていますが、難易度と受験料が高いため安定してからとなりそうです。
受験料は受かれば会社から支給されるのですが、落ちると自費になります(AWSからの特典で一回は半額になる)

なんのために

実務経験がない私にとって、資格の学習こそが知識をつける上で一番効率の良いやり方だと思うからです。
また、プロフェッショナル資格では多くのユースケースを学ぶことができるので、今後実案件に参画していく時に少しでも役に立てると思うからです。



早く合格記事を書けるように頑張ります。

参考

https://qiita.com/fkooo/items/17fa401f4e46ecd00675

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ローカルアプリからAWS S3に画像をアップロードする

ode# 目次

  • Macのローカルで作成したLaravelアプリから画像ファイルをS3にアップロードする方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.8 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする
Laravel バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提条件

  • MacのローカルでLaravelのアプリが作成できる状態になっていること。
  • コマンド$ composerが実行できる状態になっていること。

前提情報

  • 本記事はMacのローカルで作成されたLaravelアプリからAWSのS3に画像をアップロードする方法をまとめている。
  • AWSならS3にバケットを作成する部分から、ローカルならLaravelアプリを作成する部分から説明する。
  • 本記事の作業完了したソースは下記にアップしてある。

概要

  1. S3にてバケットを作成
  2. アクセスキーの取得
  3. Laravelアプリ作成
  4. Laravelアプリ側の設定
  5. 設定

詳細

  • 下記の説明で使用するコマンドはsshでインスタンスに接続して実行する物とする。
  1. S3にてバケットを作成
    1. 下記のリンクの手順を実施してS3にバケットを作成する。(testフォルダの作成まで実施する。)
  2. アクセスキーの取得
    1. 下記のリンクの手順を実施してアクセスキーとシークレットアクセスキーの取得を行う。
  3. Laravelアプリ作成

    1. 任意のディレクトリで下記コマンドを実行してLaravelアプリを作成する。作成するアプリ名は「laravel6_s3」とする。

      $ composer create-project "laravel/laravel=6.*" laravel6_s3
      
    2. 下記コマンドを実行して作成したLaravelアプリのディレクトリに移動する。

      $ cd laravel6_s3
      
  4. Laravelアプリ側の設定

    1. laravel6_s3ディレクトリで下記コマンドを実行して必要なライブラリをインストールする。

      $ composer require league/flysystem-aws-s3-v3 ~1.0
      
    2. 下記コマンドを実行してLaravelの設定ファイルを開く。

      $ vi .env
      
    3. 下記の様に設定ファイルを修正する。AWSのアカウント登録時にCSVファイルで得た情報を記載する。※シークレットアクセスキーはCSVファイルでのみ確認する事ができるため紛失した場合は別アカウントをAWSに登録したほうが早いかもしれない。

      • 修正前

        /var/www/html/test/.env
        AWS_ACCESS_KEY_ID=
        AWS_SECRET_ACCESS_KEY=
        AWS_DEFAULT_REGION=us-east-1
        AWS_BUCKET=
        
      • 修正後

        /var/www/html/test/.env
        AWS_ACCESS_KEY_ID=AWSのアクセスキーを記載する
        AWS_SECRET_ACCESS_KEY=AWSのシークレットアクセスキーを記載する
        AWS_DEFAULT_REGION=ap-northeast-1
        AWS_BUCKET=先に作成したバケット名
        
      • 修正後の.envファイルの全体を下記に記載する。

        /var/www/html/test/.env
        APP_NAME=test
        APP_ENV=local
        APP_KEY=base64:ZJYPq8Ij/UIWowQG+H4Gwz+zXjs/vEn85Yfv45qQa88=
        APP_DEBUG=true
        APP_URL=http://localhost
        
        LOG_CHANNEL=stack
        
        DB_CONNECTION=mysql
        DB_HOST=127.0.0.1
        DB_PORT=3306
        DB_DATABASE=test
        DB_USERNAME=root
        DB_PASSWORD=**************
        
        BROADCAST_DRIVER=log
        CACHE_DRIVER=file
        QUEUE_CONNECTION=sync
        SESSION_DRIVER=file
        SESSION_LIFETIME=120
        
        REDIS_HOST=127.0.0.1
        REDIS_PASSWORD=null
        REDIS_PORT=6379
        
        MAIL_MAILER=smtp
        MAIL_HOST=smtp.mailtrap.io
        MAIL_PORT=2525
        MAIL_USERNAME=null
        MAIL_PASSWORD=null
        MAIL_ENCRYPTION=null
        MAIL_FROM_ADDRESS=null
        MAIL_FROM_NAME="${APP_NAME}"
        
        AWS_ACCESS_KEY_ID=AWSのアクセスキーを記載する
        AWS_SECRET_ACCESS_KEY=AWSのシークレットアクセスキーを記載する
        AWS_DEFAULT_REGION=ap-northeast-1
        AWS_BUCKET=先に作成したバケット名
        
        PUSHER_APP_ID=
        PUSHER_APP_KEY=
        PUSHER_APP_SECRET=
        PUSHER_APP_CLUSTER=mt1
        
        MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
        MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
        
  5. ファイル設置処理の付与

    1. アプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。

      $ vi routes/web.php
      
    2. 開いたルーティングファイルを下記の様に修正する。(そのほかのルーティング情報が下記記載と一致していなくても追記部分だけ追記する。)

      アプリ名ディレクトリ/routes/web.php
      <?php
      
      use Illuminate\Support\Facades\Route;
      
      /*
      |--------------------------------------------------------------------------
      | Web Routes
      |--------------------------------------------------------------------------
      |
      | Here is where you can register web routes for your application. These
      | routes are loaded by the RouteServiceProvider within a group which
      | contains the "web" middleware group. Now create something great!
      |
      */
      
      Route::get('/', function () {
          return view('welcome');
      });
      
      Auth::routes();
      
      Route::get('/home', 'HomeController@index')->name('home');
      
      //下記を追記
      //画像ファイルをアップロードするボタンを設置するページへのルーティング
      Route::get('/upload/image', 'ImageController@input');
      //画像ファイルをアップロードする処理のルーティング
      Route::post('/upload/image', 'ImageController@upload');
      //上記までを追記
      
    3. アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。

      $ php artisan make:controller ImageController
      
    4. 下記のコントローラファイルが作成される。

      • アプリ名ディレクトリ/app/Http/Controllers/ImageController.php
    5. アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを開く。

      $ vi app/Http/Controllers/ImageController.php
      
    6. 開いたコントローラファイルを下記の様に修正する。

      アプリ名ディレクトリ/app/Http/Controllers/ImageCotroller.php
      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      //下記を追加する
      use Illuminate\Support\Facades\Storage;
      
      class ImageUploadController extends Controller
      {
          //下記を追加
          public function input()
          {
              return view('images.input');
          }
      
          public function upload(Request $request)
          {        
              $this->validate($request, [
                  'file' => [
                      // 必須
                      'required',
                      // アップロードされたファイルであること
                      'file',
                      // 画像ファイルであること
                      'image',
                      // MIMEタイプを指定
                      'mimes:jpeg,png',
                  ]
              ]);
      
              if ($request->file('file')->isValid([])) {
      
                  Storage::disk('s3')->putFile('/test', $request->file('file'), 'public');
                  return redirect('/');
              }else{
                  return redirect('/upload/image');
              }
          }
          //上記までを追記
      }
      
    7. アプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。

      $ mkdir resources/views/images
      
    8. アプリ名ディレクトリで下記コマンドを実行してビューファイルを作成する。

      $ touch resources/views/images/input.blade.php
      
    9. アプリ名ディレクトリで下記コマンドを実行して画像をアップロードするビューファイルを開く。

      $ vi resources/views/images/input.blade.php
      
    10. 開いたビューファイルを下記の様に記載する。

      アプリ名ディレクトリ/resources/views/images/input.blade.php
      @extends('layouts.app')
      
      @section('content')
      
      <!-- トリガー -->
      <form action="/upload/image" method="POST" enctype="multipart/form-data">
          @csrf
      
          <label for="photo">画像ファイル:</label>
          <input type="file" class="form-control" name="file">
          <br>
          <input type="submit">
      </form>
      @endsection
      
  6. 確認

    1. laravel6_s3ディレクトリで下記コマンドを実行してローカルサーバを起動する。

      $ php artisan serve
      
    2. 下記にアクセスする。

    3. 下記のページが表示されることを確認する。

      Laravel.png

    4. 任意の画像ファイルを選択し「送信」ボタンを押下する。(送信ボタン押下後にエラーが403エラーが発生する場合は.envファイルの記載に誤りがあることが多い。その他のエラー原因はこちら→AWS S3 Laravel 画像ファイルアップロード時にエラーが発生する)

      Laravel.png

    5. S3のバケットのテストファイル直下に下記の様にファイルが格納されていることを確認する。(ファイル名はランダムになる。)

      S3_Management_Console_と_ec2-user_ip-172-31-12-2__var_www_html_test_と_下書き一覧_-_Qiita_と_credentials__1_.png

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】ユーザー認証をCognito + Amplifyで構築してみた ~ 構築準備編 ~

はじめに

Reactで作成したWebアプリケーションのユーザー認証部分をCognito + Amplifyフレームワークで構築してみました。
本記事では、それぞれのサービスについて、Amplifyの設定方法についてまとめています。

完成画面

今回は、ユーザー名、パスワードとワンタイムパスワードの2段階認証を行います。そして、サインインをしたユーザーを識別し、トップページには「{ユーザー名}さんこんにちは!」という文字が出るようにします。

ezgif.com-gif-maker.gif

方法検討

要件

認証方法を考えるにあたり、条件は以下の通りです。

  • 静的コンテンツをS3に置いている
  • アプリケーション部分はLambdaで実装している
  • アプリケーション内でユーザーを管理しており、ユーザーに登録されている人だけ使えるようにしたい
  • 今後ユーザーのマイページも作りたいので、認証と合わせてユーザーを識別したい
  • パスワードはシステム管理者が管理しないようにするのがベター
  • ソーシャルアカウントは使わない
  • MFA(多要素認証)を使いたい

結論

この条件に沿って認証部分を考えた結果、Cognitoを利用することにしました。また、Cognitoと既存のWebアプリケーションを簡単に連携できるAWSのAmplifyフレームワークというものがあったので、こちらも使ってみることにしました。

使用するAWSサービスについて

Cognitoってなに?

公式サイトによると、次のように説明されています。

Amazon Cognito を使用すれば、ウェブアプリケーションおよびモバイルアプリに素早く簡単にユーザーのサインアップ/サインインおよびアクセスコントロールの機能を追加できます。Amazon Cognito は、数百万人のユーザーにスケールし、Facebook、Google、Amazon などのソーシャル ID プロバイダー、および SAML 2.0 によるエンタープライズ ID プロバイダーを使用したサインインをサポートします。

Cognitoでできること

今回のCognitoでやることは下記の通りです。

  • Webアプリケーションのユーザーの管理(パスワードなど含む)
  • ユーザーがサインインするときの認証

料金

料金は使った分だけです。最低料金もかかりません。
今回のように、ユーザープールの認証情報を使ってCognitoユーザープールに直接サインインする場合は50,000MAUの無料枠があります。50,000MAUを超えるアクティブユーザーがいる場合は、0.0055USD/MAUかかります。(人数幅によって多少減額あり。詳細はこちらをご覧ください。)
※1MAU=サインアップ、サインイン、トークンの更新またはパスワードの変更など、当該ユーザーに関わる ID 操作があったユーザー(アクティブユーザー)

参考:https://aws.amazon.com/jp/cognito/pricing/

Amplifyってなに?

公式サイトによると、次のように説明されています。

AWS Amplify は、モバイルとウェブのフロントエンドデベロッパーが、安全でスケーラブルなフルスタックアプリケーションを構築しデプロイできるようにする、AWS によるエンドツーエンドのソリューションです。Amplify を使用すれば、アプリケーションのバックエンドを数分で設定し、わずか数行のコードでそれをアプリケーションに接続できます。そして、3 ステップで静的なウェブアプリケーションをデプロイできます。

その中で、分析や認証などの機能を持つAWSリソースを構成するのに役立つ対話型のCLIを提供していたり、認証処理などの実装や画面の作成に使うライブラリ、UIコンポーネントを提供しているAmplifyフレームワークというものを使います。

Amplifyフレームワークでできること

今回Amplifyフレームワークでやることは下記の通りです。

  • Amplify CLIを使ってのCognitoユーザープールの構築
  • 既存のソースコードとCognitoの連携
  • サインイン画面作成
  • ユーザー情報の取得、サインアウト機能の実装

今回はフロントエンドフレームワークとしてReactを使いましたが、他にもReact Native、Angular、Vue、IonicやiOS/Android IDEでも使うことができます。

料金

Amplifyフレームワーク自体には料金はかかりません。

Amplify フレームワーク (ライブラリ、CLI、UIコンポーネント) を使用する場合は、基盤として使用する AWS のサービスに対してのみお支払いいただきます。Amplify フレームワークの使用には、追加料金は発生しません。

参考:https://aws.amazon.com/jp/amplify/pricing/?nc=sn&loc=3

手順

下記の流れで進めていきます。

本記事ではこちらの手順についてまとめています。
1. Reactの開発環境の構築
2. Amplifyの設定
3. Amplify用のIAMユーザーの作成
4. Amplifyの初期設定

下記の5番、6番については別記事 構築完成編 へ。
5. Cognitoユーザープールの作成
6. コード実装

やってみる

1. Reactの開発環境の構築

React環境を簡単に構築する環境構築ツールはcreate-react-app、パッケージマネージャーはyarnを使いました。

参考:新しい React アプリを作る

バージョン

  • node 14.15.0
  • yarn 1.22.10
  • create-react-app 4.0.0

2. Amplifyの設定

AmplifyをCLIで操作するために、Amplify CLIをインストールします。

$ yarn global add @aws-amplify/cli

そして、プロジェクトには、Amplifyのパッケージを追加します。

$ yarn add aws-amplify
$ yarn add aws-amplify-react
$ yarn add @aws-amplify/ui-react

3. Amplify用のIAMユーザーの作成

AWSでAmplifyが使うIAMユーザーの作成し、名前付きプロファイルにIAMユーザーを設定します。

$ amplify configure

上記のコマンドを実行すると、AWSのコンソールが自動で開くのでコンソールでIAMユーザーを作成します。その後、コマンドラインで対話形式で作成したIAMユーザーの認証情報をAWS CLIのcredentialsファイルに保存します。今回、プロファイル名はamplify-cognitoで保存しました。

詳しくは、こちらの記事のAWSアカウントの紐付けを参考にしました。
AWS Amplify CLIの使い方〜インストールから初期セットアップまで〜

ただ、Amplify用のIAMユーザーにAdministratorAccessのポリシーをアタッチするのは嫌だったので、こちらを参考に自分でポリシーを作成しました。不要そうなサービスへの権限を削除し、これでは権限が足りずエラーが出てしまったので、"cognito-idp:UntagResource"を追加しています。

※↓クリックするとIAMポリシーが見れます。

IAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "amplify:CreateApp",
                "amplify:CreateBackendEnvironment",
                "amplify:CreateBranch",
                "amplify:DeleteApp",
                "amplify:DeleteBackendEnvironment",
                "amplify:DeleteBranch",
                "amplify:GetApp",
                "amplify:GetBackendEnvironment",
                "amplify:ListApps",
                "amplify:ListBackendEnvironments",
                "amplify:ListBranches",
                "amplify:ListDomainAssociations",
                "amplify:UpdateApp",
                "cloudformation:CreateChangeSet",
                "cloudformation:CreateStack",
                "cloudformation:CreateStackSet",
                "cloudformation:DeleteStack",
                "cloudformation:DeleteStackSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:DescribeStackEvents",
                "cloudformation:DescribeStackResource",
                "cloudformation:DescribeStackResources",
                "cloudformation:DescribeStackSet",
                "cloudformation:DescribeStackSetOperation",
                "cloudformation:DescribeStacks",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:GetTemplate",
                "cloudformation:UpdateStack",
                "cloudformation:UpdateStackSet",
                "cognito-identity:CreateIdentityPool",
                "cognito-identity:DeleteIdentityPool",
                "cognito-identity:DescribeIdentity",
                "cognito-identity:DescribeIdentityPool",
                "cognito-identity:SetIdentityPoolRoles",
                "cognito-identity:GetIdentityPoolRoles",
                "cognito-identity:TagResource",
                "cognito-identity:UpdateIdentityPool",
                "cognito-idp:AdminAddUserToGroup",
                "cognito-idp:AdminCreateUser",
                "cognito-idp:CreateGroup",
                "cognito-idp:CreateUserPool",
                "cognito-idp:CreateUserPoolClient",
                "cognito-idp:DeleteGroup",
                "cognito-idp:DeleteUser",
                "cognito-idp:DeleteUserPool",
                "cognito-idp:DeleteUserPoolClient",
                "cognito-idp:DescribeUserPool",
                "cognito-idp:DescribeUserPoolClient",
                "cognito-idp:ListTagsForResource",
                "cognito-idp:ListUserPoolClients",
                "cognito-idp:UpdateUserPool",
                "cognito-idp:UpdateUserPoolClient",
                "cognito-idp:UntagResource",
                "iam:AttachRolePolicy",
                "iam:CreatePolicy",
                "iam:CreateRole",
                "iam:DeletePolicy",
                "iam:DeleteRole",
                "iam:DeleteRolePolicy",
                "iam:DetachRolePolicy",
                "iam:GetPolicy",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "iam:GetUser",
                "iam:ListPolicyVersions",
                "iam:PassRole",
                "iam:PutRolePolicy",
                "iam:UpdateRole",
                "lambda:AddLayerVersionPermission",
                "lambda:AddPermission",
                "lambda:CreateEventSourceMapping",
                "lambda:CreateFunction",
                "lambda:DeleteEventSourceMapping",
                "lambda:DeleteFunction",
                "lambda:DeleteLayerVersion",
                "lambda:GetEventSourceMapping",
                "lambda:GetFunction",
                "lambda:GetFunctionConfiguration",
                "lambda:GetLayerVersion",
                "lambda:GetLayerVersionByArn",
                "lambda:InvokeAsync",
                "lambda:InvokeFunction",
                "lambda:ListEventSourceMappings",
                "lambda:ListLayerVersions",
                "lambda:PublishLayerVersion",
                "lambda:RemoveLayerVersionPermission",
                "lambda:RemovePermission",
                "lambda:UpdateFunctionCode",
                "lambda:UpdateFunctionConfiguration",
                "s3:CreateBucket",
                "s3:DeleteBucket",
                "s3:DeleteBucketPolicy",
                "s3:DeleteBucketWebsite",
                "s3:DeleteObject",
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:HeadBucket",
                "s3:ListAllMyBuckets",
                "s3:ListBucket",
                "s3:PutBucketAcl",
                "s3:PutBucketCORS",
                "s3:PutBucketNotification",
                "s3:PutBucketPolicy",
                "s3:PutBucketWebsite",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "*"
        }
    ]
}

これより少なくすることはできるかもしれないですが、この権限があれば今回のCognitoとAmplifyでユーザー認証を構築するのは問題なくできました!

4. Amplifyの初期設定

Amplifyの設定を行うために下記のコマンドを実行します。

$ amplify init

聞かれた通りにプロジェクト名や使っているエディターなどを入力、選択していきます。プロジェクト名や環境名は、AWS上に作成されるリソースの名前になります。

? Enter a name for the project qiitatest
? Enter a name for the environment dev
? Choose your default editor: IntelliJ IDEA
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path:  src
? Distribution Directory Path: build
? Build Command:  yarn build
? Start Command: yarn start

そして、使うプロファイルについて聞かれるのでyと答え、先ほど3. Amplify用のIAMユーザーの作成で作成、保存したプロファイルamplify-cognitoを選択します。

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use amplify-cognito

この設定が完了すると、プロジェクト内にamplifyフォルダsrc/aws-exports.jsが作成されます。

おわりに

Amplifyフレームワークの設定が完了しました!Amplify用のIAMユーザーの作成方法(ポリシーの内容は変わってきます)やAmplifyの初期設定についてはCognitoに限らず他のサービスでも共通です。
次の構築完成編では、Cognitoユーザープールの作成とソースコードも書いていきます!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】ユーザー認証をCognito + Amplifyで構築してみた ~ 構築完成編 ~

はじめに

Reactで作成したWebアプリケーションのユーザー認証部分をCognito + Amplifyフレームワークで構築してみました。
本記事では、Cognitoのユーザープールの作成方法、Reactでのコード実装についてまとめています。

完成画面

今回は、ユーザー名、パスワードとワンタイムパスワードの2段階認証を行います。そして、サインインをしたユーザーを識別し、トップページには「{ユーザー名}さんこんにちは!」という文字が出るようにします。

ezgif.com-gif-maker.gif

方法検討

要件

認証方法を考えるにあたり、条件は以下の通りです。

  • 静的コンテンツをS3に置いている
  • アプリケーション部分はLambdaで実装している
  • アプリケーション内でユーザーを管理しており、ユーザーに登録されている人だけ使えるようにしたい
  • 今後ユーザーのマイページも作りたいので、認証と合わせてユーザーを識別したい
  • パスワードはシステム管理者が管理しないようにするのがベター
  • ソーシャルアカウントは使わない
  • MFA(多要素認証)を使いたい

結論

この条件に沿って認証部分を考えた結果、Cognitoを利用することにしました。また、Cognitoと既存のWebアプリケーションを簡単に連携できるAWSのAmplifyフレームワークというものがあったので、こちらも使ってみることにしました。

手順

下記の流れで進めていきます。

下記の1番から4番については別記事 構築準備編 へ。
1. Reactの開発環境の構築
2. Amplifyの設定
3. Amplify用のIAMユーザーの作成
4. Amplifyの初期設定

本記事ではこちらの手順についてまとめています。
5. Cognitoユーザープールの作成
6. コード実装

やってみる

5. Cognitoユーザープールの作成

前述の要件に沿ってユーザープールを作成していきます。
初めてのCognitoで何の設定をしているのかを調べるのが大変だったので1つ1つ残しておこうと思います。

Cognitoの作成を行うために下記のコマンドを実行します。

$ amplify add auth

詳細な設定を行うか、デフォルトの設定で良いか聞かれます。今回はMFAを使いたかったのでManual configurationを選択しました。

# Do you want to use the default authentication and security configuration?
Manual configuration

今回はサインインが使えれば良かったので、User Sign-Up & Sign-In only (Best used with a cloud API only)を選択しました。

# Select the authentication/authorization services that you want to use:
User Sign-Up & Sign-In only (Best used with a cloud API only)

リソース名とユーザープール名を入力します。

# Please provide a friendly name for your resource that will be used to label this category in the project: 
test
# Please provide a name for your user pool: 
test-cognito-mfa

ユーザー名とパスワードでサインインしたいので、Usernameを選択します。この項目は、後から変更できません。

# How do you want users to be able to sign in?
Username

参考
スクリーンショット 2020-11-01 14.47.16.png

今回はグループは作成しないのでNoを選択します。

# Do you want to add User Pool Groups? 
No

ユーザープール内の情報を取得したり、ユーザーを登録したりするAPIを叩けるようにするかを選択します。今回は使わないのでNoを選択します。
参考:https://docs.amplify.aws/cli/auth/admin

# Do you want to add an admin queries API?
No

今回はアプリケーション内でユーザーを管理していたため、このAPIを使わずに、自分でLambdaを作成しAWSのSDKを使ってユーザーの登録などを実装しましたが、このAPI使うのでも良かったかもしれないです。

MFAの設定を行います。今回はMFAを使いたいのでONを選択します。この設定はあとで変えられないので気をつけましょう。そして、MFAにはAuthenticatorやAuthyなどのアプリケーションを用いてのワンタイムパスワードを使いたいので、TOTPのみを選択しました。

# Multifactor authentication (MFA) user login options:
 ON (Required for all logins, can not be enabled later)
# For user login, select the MFA types: 
 Time-Based One-Time Password (TOTP)

参考
スクリーンショット 2020-11-03 19.28.34.png

SMSのメッセージの設定です。
SMSは使わず、Eメールを使うつもりなので、デフォルトのままEnterします。

# Please specify an SMS authentication message: 
 Your authentication code is {####}

ユーザープールにはEメールアドレスも登録し、Eメールを使ってユーザーの登録やパスワードの再設定を行いたいのでEnabledを選択します。

# Email based user registration/forgot password:
Enabled (Requires per-user email entry at registration)

参考(左メニュー [MFAそして確認] 内)
スクリーンショット 2020-11-03 23.37.46.png

認証コードを送るEメールの題名と本文の設定です。デフォルトのまま進みます。

# Please specify an email verification subject:
Your verification code
# Please specify an email verification message:
Your verification code is {####}

参考(左メニュー [メッセージのカスタマイズ] 内)
スクリーンショット 2020-11-06 23.10.00.png

パスワードポリシーを設定します。
文字数を8文字以上、数字、特殊文字、大文字、小文字を含むパスワードのみしか設定できないようにしました。

# Do you want to override the default password policy for this User Pool?
Yes
# Enter the minimum password length for this User Pool:
8
# Select the password character requirements for your userpool:
Requires Lowercase, Requires Uppercase, Requires Numbers, Requires Symbols

参考
スクリーンショット 2020-11-01 14.14.27.png

ちなみに、Do you want to override the default password policy for this User Pool?No (= デフォルトのパスワード設定)とすると、8文字以上という条件しか設定されません。

サインアップ時に必要な属性を設定します。パスワードの再設定等にメールアドレスを使用するため、Emailを選択しました。この項目は、後から変更できません。

# What attributes are required for signing up?
Email

参考(左メニュー [属性] 内)
スクリーンショット 2020-11-01 14.50.07.png

リフレッシュトークンはひとまずデフォルトの30日にしておきます。

# Specify the app's refresh token expiration period (in days): 
30

参考
スクリーンショット 2020-11-01 14.35.36.png

サインアップはユーザー自身が行わず別の処理で行うので書き込み権限は付与しません。また、ログインしたユーザーの識別にはUsernameを使うので読み取り権限も付与しません。

# Do you want to specify the user attributes this app can read and write?
No

今回は、アプリケーション内で事前に登録しているユーザーのみしかログインできず、ユーザー自身がサインアップすることがないので追加しませんでしたが、下記のような機能を追加することもできます。

  • Add Google reCaptcha Challenge
  • Email Verification Link with Redirect
  • Add User to Group
  • Email Domain Filtering (blacklist)
  • Email Domain Filtering (whitelist)
  • Custom Auth Challenge Flow (basic scaffolding - not for production)
# Do you want to enable any of the following capabilities? 
(選択なし)

今回はソーシャルログインは使わないのでOAuthはNoを選択します。

# Do you want to use an OAuth flow?
No

CognitoをLambda関数のトリガーとして使う予定はなかったのでnを入力。
例えば、ユーザーがサインアップしたことをトリガーとしてLambda関数を実行したいときなどに利用できます。

# Do you want to configure Lambda Triggers for Cognito?
No

参考
スクリーンショット 2020-11-01 14.22.29.png

これで構築するCognitoの設定が完了です。
そして、下記のコマンドで設定を保存します。

$ amplify push

環境やリソースがあっているかを聞かれるので、確認してyを入力します。

# ? Are you sure you want to continue?
Yes

これでCognitoのユーザープールが作成されました!そしてsrc/aws-exports.jsにはid等が書き込まれます。

最後に、このままだとユーザー自身がサインアップできてしまうので、Cognitoコンソールからできないようにします。
先ほど作成したCognitoのユーザープールを開き、左のメニューから[ポリシー]をクリックし、[管理者のみにユーザーの作成を許可する]を選択します。その後、[変更の保存]をクリックし、保存してください。

スクリーンショット 2020-11-03 23.27.48.png

Cognitoのコンソールからも設定を変更することもできますが、一部コンソールの変更では反映されないというのも見かけましたので、ご注意ください。Amplify CLIで設定を変更する場合は、$ amplify update authで設定を変更し、$ amplify pushを実行することで変更が保存されます。

6. コード実装

App.jsの中身を書き換えます。
参考:https://docs.amplify.aws/lib/auth/getting-started/q/platform/js

App.js
import React, {useEffect} from "react";
import Amplify, {Auth} from 'aws-amplify';
import awsconfig from './aws-exports';
import {withAuthenticator} from "@aws-amplify/ui-react";

Amplify.configure(awsconfig);

function App() {
    const [currentUserName, setCurrentUserName] = React.useState("");
    useEffect(() => {
        const init = async() => {
            const currentUser = await Auth.currentAuthenticatedUser();
            setCurrentUserName(currentUser.username);
        }
        init()
    }, []);

    const signOut = async() => {
        try {
            await Auth.signOut();
        } catch (error) {
            console.log('error signing out: ', error);
        }
        document.location.reload();
    }

    return (
        <div>
            <h1>{currentUserName}さんこんにちは</h1>
            <button onClick={signOut}>サインアウト</button>
        </div>
    );
}

export default withAuthenticator(App);

実行結果

ユーザーの追加

ユーザーの追加を行います。まだ、アプリケーション内から登録ができるようになっていないので、今回はAWSのCognitoコンソールから追加を行います。

先ほど作成したユーザープール内の左メニュー[ユーザーとグループ]を選択し、[ユーザーの作成]をクリックします。

スクリーンショット 2020-11-07 16.37.01.png

ユーザー名、ユーザーへの招待はEメールで行いたいのでEメールにチェック、電話番号は登録しないので検証済みのチェックを外し、Eメールアドレスを入力します。そして、[ユーザーの作成]をクリックし、ユーザーを作成します。ここで仮パスワードを未入力で登録すると、ユーザーにはランダムでパスワードが発行されます。

スクリーンショット 2020-11-07 16.43.13.png

ユーザーが作成できました。

スクリーンショット 2020-11-07 16.43.58.png

これでユーザーの登録は完了です。そしてユーザーには次のようなメールが送られます。

スクリーンショット 2020-11-07 16.44.59.png

サインイン一連の流れ(2回目以降)

冒頭の完成画面をご覧ください。
※初回サインイン時には、パスワードの変更、TOTP用のQRコードを読み取る操作が加わります。

サインインページからアカウントは本当につくれないのか

最後にAWSコンソールからユーザーがサインアップできないように設定しましたが、本当にできないのかを試してみます。

スクリーンショット 2020-11-07 18.01.02.png

エラーが出てサインイン画面からは登録できないことが確認できました!

おわりに

こんなに簡単にユーザー認証をつけることができました!画面もAmplifyのUIコンポーネントを使えば、こんなにも簡単に作成することができるんです!
ただ、このままではサインインページに使えないアカウント作成ボタンがあるので、そのボタンをなくしたい、AWSコンソールからではなくアプリケーションでユーザー管理できるようにしたいなど、要件に合うように多少カスタマイズも必要です。そのカスタマイズについて今後記事に残していければと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Cloud9でLambdaのデバッグが出来なくなった際の対応(Python)

私は今までAWS Cloud9を使用してLambda(Python)をデバッグしていましたが、2020年6月頃からAWS Cloud9がアップデートされているみたいで今まで通りデバッグが出来なくなりました。

どうにかこうにかデバッグ出来るように設定しましたので、対応した事を本記事にアウトプットして残したいと思います。

事象

ある日突然、Cloud9を新規作成してデバッグしようと思ったら下記のようなメッセージが出てデバッグが出来なくなりました

AWS Lambda preview
Python debugging with the AWS Lambda preview UI requires IKPdb to be installed in your code package. 
For more information see: 
https://docs.aws.amazon.com/console/cloud9/lambda-functions-debug

どうやらCloud9内部がアップグレードされている事が原因みたいです
※デフォルトの設定がPython2.6からPython3.6になっていたり、色々変わっていました

上記対応について全然記事を探せなかったので、この記事が他の人の役に立てたらと思います。

対応

今回の記事はまとめると下記の作業になります

  1. テスト用のLambdaと、Cloud9を作成
  2. LambdaをCloud9へインポート
  3. 「template.yaml」に「CodeUri: .debug/」を追加
  4. インポートしたLambdaディレクトリに移動
  5. 「pip-3.6 install ikp3db --target .」を実行
  6. 「python -m venv venv」を実行
  7. 「venv/bin/pip3.6 install ikp3db」を実行
  8. Cloud9でデバッグが出来るようになります

 1. テスト用のLambdaと、Cloud9を作成

※LambdaとCloud9の構築手順は参考サイトが多々ありますので省略しております
WS000000.JPG

2. LambdaをCloud9へインポート

WS000001.JPG

WS000002.JPG
右側の「λ」をクリックして、作成したテスト用Lambdaをインポートします
※事前に作成したokuhira-test-lambdaを選択しました

3. 「template.yaml」に「CodeUri: .debug/」を追加

image.png

テスト用Lambda(okuhira-test-lambda)をインポートすると、左側のツリーに「okuhira-test-lambda」フォルダが作成されます
「okuhira-test-lambda」フォルダ内にある「template.yaml」ファイルを開きます
上記の図のように、「CodeUri: .debug/」文言を追加します(※保存を忘れない事)

4. インポートしたLambdaディレクトリに移動

image.png

下側のターミナルウィンドウで「cd okuhira-test-lambda/」と入力し、Lambdaフォルダへ移動します

5. 「pip-3.6 install ikp3db --target .」を実行

そのままターミナルウィンドウで「pip-3.6 install ikp3db --target .」を実行します

6. 「python -m venv venv」を実行

そのままターミナルウィンドウで「python -m venv venv」を実行します

7. 「venv/bin/pip3.6 install ikp3db」を実行

そのままターミナルウィンドウで「venv/bin/pip3.6 install ikp3db」を実行します

※上記5~7を実行の画像
WS000004.JPG

8. Cloud9でデバッグが出来るようになります

下記の手順でデバッグ出来るようになります。
WS000006 - コピー.JPG

①lambda_function.pyを開く
②ブレークポイントを設定
③Runをクリック
④下記テストのイベント値を入力

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

⑤デバッグアイコンをクリック

最後に下記のRunをクリックするとデバッグできるよになりました
WS000007 - コピー.JPG

イミディエイトウィンドウもちゃんと機能しています ヨシ!

注意点

・インスタンススペックが低いとデバッグ実行時に固まってしまう時があるのですが、諦めずに画面更新、デバッグ実行を押す
・デバッグボタンをクリックする時は、Pythonのファイルをアクティブにする(※重要かも)
・今回はPython3.6の確認です、LambdaがPython3.8が対応したのでそれで作成したいのですが、Python3.8はもう少し調査が必要かも
・またバージョンアップされてしまったら対応方法が変わるかもです・・・

Cloud9のアップグレードに対応していくのは面倒くさいのですが、私の場合はローカルPCに開発環境が依存するよりは良いかなと思っています

※最近、2020年10月頃にAmazonLinux2でCloud9が作成できるようになりました、こちらでもデバッグが出来るようになりましたら記事を作成したいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Amazon Lightsail:①説明・作成

はじめに

Amazon Lightsailを記事にしたいと思います、長いのでシリーズ記事とします

1. 【AWS】Amazon Lightsail:①説明・作成 ※現在の記事 
2. 【AWS】Amazon Lightsail:②その他機能の設定
2. 【AWS】Amazon Lightsail:③他AWSサービスとの連携(VPC)
3. 【AWS】Amazon Lightsail:④他AWSサービスとの連携(ALB)
4. 【AWS】Amazon Lightsail:⑤他AWSサービスとの連携(Route53)
5. 【AWS】Amazon Lightsail:⑥他AWSサービスとの連携(WAF)
6. 【AWS】Amazon Lightsail:⑦iptableにてアウトバウンド設定

背景

WordPressブログを動かしているサーバの料金を安くしようとAmazon Lightsailに携わりました
結果、月額料金を約1/2削減出来ました
Lightsailを上手く使えると大幅なコスト削減を見込める事が出来ます

概要

Lightsailはある程度、使い所を見極める必要があります
サーバは停止しないで(24時間365日稼働)、WordPressブログや社内等の限定公開システム、その他ちょっとした開発・検証環境であればLightsailが適切かなと考えています
※土日、深夜にサーバを停止する方が安い場合もあります

また、見積もりが難しい「転送量」も1TBまで無料であり、分かりやすくて助かります
※プランによって転送量が異なります、指定量を超えると課金されます

Lightsail作成

今回は試しにLightsail(WordPress)の作成・動作確認だけ行います

(1) Lightsail画面へ遷移し、「インスタンスの作成」ボタンをクリック
AWSが提供するVPSサービスなので、今までのAWS画面と表示が変わります
image.png

(2) インスタンスロケーションは東京を選択します
image.png

(3) プラットフォームは「Linux/Unix」、設計図の選択は「WordPress」を選択
image.png

(4) SSHキーペアマネージャー「デフォルト」をダウンロードします
※起動スクリプトは今回は無し
image.png

(5) インスタンスプランは「$3.5」を選択
image.png

(6) インスタンス名を指定
今回は「test-WordPress-1」にします
image.png

インスタンスを作成ボタンをクリックして、Lightsail作成完了です、早いですね

下記のようにLightsailインスタンスが作成されました
image.png

(7) アクセスの制限
最初は自分だけしかアクセスさせないようにしたい場合、下記のように設定します
・右上の「3点線」クリック → 管理 → ネットワーキング → ファイアウォール
image.png
image.png
image.png

Lightsailのファイアウォール(インバウンド)はWeb画面で設定できます
※アウトバウンドはまだ設定できないみたいです
デフォルトだとSSH、HTTP、HTTPSポートがanyで開放されている状態です
下記のように自分のGIPからのみ接続するようにして安心しましょう
※(4)SSHに関してはSSHキーペアマネージャーが無いとSSH接続出来ませんが、キーペア漏えい等も考慮してSSH接続はちゃんとIP制限をかけます
image.png

最初の画面に戻るには左上の「ホーム」をクリックします
image.png

(8) WordPressへ接続
あとは通常のWordPress通り、下記に表示されているIPへブラウザからhttp接続を行うとWordPress画面が表示されます
※画像ではIPは伏せています
image.png

image.png

(9) LightsailへSSH接続
Tera Termを使って下記に接続
・IP:LightsailのIPに接続
・ユーザ名:bitnami
・秘密鍵:(4)でダウンロードしたSSHキーペアマネージャー
image.png
下記の通りログインできました

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
       ___ _ _                   _
      | _ |_) |_ _ _  __ _ _ __ (_)
      | _ \ |  _| ' \/ _` | '  \| |
      |___/_|\__|_|_|\__,_|_|_|_|_|

  *** Welcome to the Bitnami WordPress 5.4.2-0                     ***
  *** Documentation:  https://docs.bitnami.com/aws/apps/wordpress/ ***
  ***                 https://docs.bitnami.com/aws/                ***
  *** Bitnami Forums: https://community.bitnami.com/               ***

#######################################################
###    For frequently used commands, please run:    ###
###         sudo /opt/bitnami/bnhelper-tool         ###
#######################################################

今回は以上となります

注意点

上記の(3)で設計図を「WordPress」で選択すると、AWSが更新する度にOSやミドルウェアのバージョンが変わってくるように感じます
※1年前作成した時はOSがubuntuだったのですが、今はAmazonLinuxでした

OS、ミドルウェアバージョンを指定したい場合は「OSのみ」を選択してミドルウェアは自分でインストールする事をお勧めします

次回

2. 【AWS】Amazon Lightsail:②その他機能の設定

参考

AWS Lightsailを使ってみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Auroraオートスケール:④Cron式スケジュール変更

はじめに

Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

  1. 【AWS】Auroraオートスケール:①オートスケール概要
  2. 【AWS】Auroraオートスケール:②オートスケール設定
  3. 【AWS】Auroraオートスケール:③Cron式スケジュール設定
  4. 【AWS】Auroraオートスケール:④Cron式スケジュール変更  ※現在の記事
  5. 【AWS】Auroraオートスケール:⑤カスタムメトリクスでリードレプリカ数経過観察
  6. 【AWS】Auroraオートスケール:⑥チューニング・ブラッシュアップ等

Aurora Auto ScalingのCron式スケジュール設定変更

前回ではAuroraオートスケールに対してCron式スケジュールの設定を行いました。
Cron式スケジュールの修正や削除を行いたい際のコマンドを記載いたします。
image.png

前回設定したCron式スケジュールを修正する際は「scalable-target-action」コマンドを変更したコマンドを実行するだけでOKです
※「scheduled-action-name」がキーとなっています
【前回のコマンド】

aws --region ap-northeast-1 application-autoscaling put-scheduled-action \
--service-namespace rds \
--schedule "cron(0 8 * * ? *)" \
--scheduled-action-name 'test-aurora-cluster-schedule' \
--resource-id cluster:test-aurora-cluster \
--scalable-dimension rds:cluster:ReadReplicaCount \
--scalable-target-action 'MinCapacity=5,MaxCapacity=10'

【修正コマンド】

aws --region ap-northeast-1 application-autoscaling put-scheduled-action \
--service-namespace rds \
--schedule "cron(0 9 * * ? *)" \  #18時へ変更
--scheduled-action-name 'test-aurora-cluster-schedule' \
--resource-id cluster:test-aurora-cluster \
--scalable-dimension rds:cluster:ReadReplicaCount \
--scalable-target-action 'MinCapacity=4,MaxCapacity=7'  #最小4台、最大7台へ変更

確認実行結果

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling describe-scheduled-actions --service-namespace rds  --resource-id cluster:test-aurora-cluster
{
    "ScheduledActions": [
        {
            "ScheduledActionName": "test-aurora-cluster-schedule",
            "ScheduledActionARN": "arn:aws:autoscaling:ap-northeast-1:xxxxxxxxxxxx:scheduledAction:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:resource/rds/cluster:test-aurora-cluster:scheduledActionName/test-aurora-cluster-schedule",
            "ServiceNamespace": "rds",
            "Schedule": "cron(0 9 * * ? *)",
            "ResourceId": "cluster:test-aurora-cluster",
            "ScalableDimension": "rds:cluster:ReadReplicaCount",
            "ScalableTargetAction": {
                "MinCapacity": 4,
                "MaxCapacity": 7
            },
            "CreationTime": "2020-11-xxTxx:xx:xx.840000+00:00"
        }
    ]
}
[root@xxxx-server ~]#

Cron式スケジュールを削除してみる

下記コマンドを実行し、Cron式スケジュールを削除します

aws --region ap-northeast-1 application-autoscaling delete-scheduled-action \
--service-namespace rds \
--scheduled-action-name 'test-aurora-cluster-schedule' \
--resource-id cluster:test-aurora-cluster \
--scalable-dimension rds:cluster:ReadReplicaCount

実行結果

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling delete-scheduled-action \
> --service-namespace rds \
> --scheduled-action-name 'test-aurora-cluster-schedule' \
> --resource-id cluster:test-aurora-cluster \
> --scalable-dimension rds:cluster:ReadReplicaCount

削除されている事を確認

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling describe-scheduled-actions --service-namespace rds  --resource-id cluster:test-aurora-cluster
{
    "ScheduledActions": []
}
[root@xxxx-server ~]#

Cron式スケジュールの追加・修正・削除についての説明は以上で完了です
負荷が高まる時間帯に設定するのも良いですが、長期休暇時には少しリードレプリカ台数を増やす対応を取るのも、安心を得られて良いと思います

次回

5. 【AWS】Auroraオートスケール:⑤カスタムメトリクスでリードレプリカ数経過観察

参考

Aurora レプリカでの Amazon Aurora Auto Scaling の使用

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Auroraオートスケール:③Cron式スケジュール設定

はじめに

Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

  1. 【AWS】Auroraオートスケール:①オートスケール概要
  2. 【AWS】Auroraオートスケール:②オートスケール設定
  3. 【AWS】Auroraオートスケール:③Cron式スケジュール設定  ※現在の記事
  4. 【AWS】Auroraオートスケール:④Cron式スケジュール変更
  5. 【AWS】Auroraオートスケール:⑤カスタムメトリクスでリードレプリカ数経過観察
  6. 【AWS】Auroraオートスケール:⑥チューニング・ブラッシュアップ等

Aurora Auto ScalingのCron式スケジュール設定内容

Auroraの構築は済んでいて 下記図のような簡単な環境が出来ている前提で進めていきます。

今回はAWS CLIコマンドを使用して、Auroraオートスケール内に時間指定で最小キャパシティを増やす方法を行います。
※2020年12月時点ではAWSマネジメントコンソール画面で設定は出来ません。
image.png

対象のEC2サーバへログインし、Auroraへアクセスします

まずは状態確認を行います
下記のようにコマンドを実行し、スケジュールが何も設定されていないことを確認します

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling describe-scheduled-actions \
> --service-namespace rds  \
> --resource-id cluster:test-aurora-cluster
{
    "ScheduledActions": []
}
[root@xxxx-server ~]#

下記のようなコマンドを実行します
内容:1時から最小キャパシティ3台、最大キャパシティ5台へ設定

aws --region ap-northeast-1 application-autoscaling put-scheduled-action \
--service-namespace rds \
--schedule "cron(0 8 * * ? *)" \
--scheduled-action-name 'test-aurora-cluster-schedule' \
--resource-id cluster:test-aurora-cluster \
--scalable-dimension rds:cluster:ReadReplicaCount \
--scalable-target-action 'MinCapacity=3,MaxCapacity=5'

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling put-scheduled-action \
> --service-namespace rds \
> --schedule "cron(0 8 * * ? *)" \
> --scheduled-action-name 'test-aurora-cluster-schedule' \
> --resource-id cluster:test-aurora-cluster \
> --scalable-dimension rds:cluster:ReadReplicaCount \
> --scalable-target-action 'MinCapacity=3,MaxCapacity=5'
[root@xxxx-server ~]#
項目 設定値 説明
service-namespace rds サービスは「rds」を設定
schedule cron(0 8 * * ? *) Cron式スケジュールを設定 
※日本時間で17時
scheduled-action-name test-aurora-cluster-schedule 任意のCron式スケジュールの名前
resource-id cluster:test-aurora-cluster 対象Auroraクラスタ名
scalable-dimension rds:cluster:ReadReplicaCount この値は rds:cluster:ReadReplicaCount に設定
scalable-target-action MinCapacity=3,MaxCapacity=5 最小、最大キャパシティを設定

Cron式スケジュールについてはAWSユーザガイトをご確認ください
スケジュールに基づくスケーリングApplication Auto Scaling

再度、内容確認のコマンドを実行し、Cron式スケジュールが設定されていることを確認します

[root@xxxx-server ~]# aws --region ap-northeast-1 application-autoscaling describe-scheduled-actions \
> --service-namespace rds  \
> --resource-id cluster:test-aurora-cluster
{
    "ScheduledActions": [
        {
            "ScheduledActionName": "test-aurora-cluster-schedule",
            "ScheduledActionARN": "arn:aws:autoscaling:ap-northeast-1:xxxxxxxxxxxx:scheduledAction:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:resource/rds/cluster:test-aurora-cluster:scheduledActionName/test-aurora-cluster-schedule",
            "ServiceNamespace": "rds",
            "Schedule": "cron(0 8 * * ? *)",
            "ResourceId": "cluster:test-aurora-cluster",
            "ScalableDimension": "rds:cluster:ReadReplicaCount",
            "ScalableTargetAction": {
                "MinCapacity": 3,
                "MaxCapacity": 5
            },
            "CreationTime": "2020-11-xxTxx:xx:xx.840000+00:00"
        }
    ]
}
[root@xxxx-server ~]#

17時になり正常に3台目が作成されました
image.png

オートスケールのCron式スケジュールが正常に動作していると、下記のようなログが出力されます。
image.png

これでAuroraオートスケールにCron式スケジュールを組み込む対応が完了しました
負荷が高まる処理やイベント時には事前に台数を増やしておく事で安心を得る事が出来ます。

次回

4.【AWS】Auroraオートスケール:④Cron式スケジュール変更

参考

Aurora レプリカでの Amazon Aurora Auto Scaling の使用

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Auroraオートスケール:②オートスケール設定

はじめに

Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

  1. 【AWS】Auroraオートスケール:①オートスケール概要
  2. 【AWS】Auroraオートスケール:②オートスケール設定 ※現在の記事
  3. 【AWS】Auroraオートスケール:③Cron式スケジュール設定
  4. 【AWS】Auroraオートスケール:④Cron式スケジュール変更
  5. 【AWS】Auroraオートスケール:⑤カスタムメトリクスでリードレプリカ数経過観察
  6. 【AWS】Auroraオートスケール:⑥チューニング・ブラッシュアップ等

Aurora Auto Scaling設定内容

Auroraの構築は済んでいて 下記図のような最小限の簡単な環境が出来ている前提で進めていきます。
image.png

①作成したAuroraクラスタ > ログとイベント > 「Auto Scalingポリシーの追加」ボタンをクリック
image.png

②Auto Scalingポリシーの設定を行います
・ポリシー名(任意):test-aurora-policy
・ターゲットメトリクス:Auroraレプリカの平均CPU使用率
・ターゲット値:80%
・スケールインクールダウン期間
・スケールアウトクールダウン期間
・最小キャパシティー:2 ※現在リードレプリカが1台ですが、最小の2台へ増えます
・最大キャパシティー:3 ※どんなに負荷が増えても、リードレプリカは3台以上へは増えません

※デフォルトの設定値は下記の内容となりました
・AuroraのCPU使用率が80%以上になると、オートスケールによってリードレプリカが1台増える
・AuroraのCPU使用率が72%以下になると、オートスケールによってリードレプリカが1台減るimage.png
image.png

③Aurora Auto Scaling設定後の動作
リードレプリカが最小2台に設定しましたので、Auto オートスケール設定直後にリードレプリカが1台作成されました
image.png

また、下記のようにスケールイン・スケールアウト用のCloudWatchのアラートが作成されます
image.png
上記アラート既定値は運用によって調整・設定していきます。

以上でAuroraオートスケールの設定は完了です。

次回

3. 【AWS】Auroraオートスケール:③Cron式スケジュール設定

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Auroraオートスケール:①オートスケール概要

はじめに

Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

  1. 【AWS】Auroraオートスケール:①オートスケール概要 ※現在の記事
  2. 【AWS】Auroraオートスケール:②オートスケール設定
  3. 【AWS】Auroraオートスケール:③Cron式スケジュール設定
  4. 【AWS】Auroraオートスケール:④Cron式スケジュール変更
  5. 【AWS】Auroraオートスケール:⑤カスタムメトリクスでリードレプリカ数経過観察
  6. 【AWS】Auroraオートスケール:⑥チューニング・ブラッシュアップ等

背景

ユーザ数が増えてリードレプリカの負荷が上がり、
緊急対応としてリードレプリカを増やす対応を2~3回ほど行い、結構な工数を要しました
上記の対策としてAuroraオートスケールを実装し、リードレプリカの負荷によって自動でスケールアップする仕組みを取り入れました
Auroraオートスケールは便利なのですが、あまり記事を見かけない為、ナレッジを残したいと思います
※Cron式スケジュール設定の記事が少なくて数時間苦戦しました・・・

Auroraオートスケール概要説明

リードレプリカの平均CPU使用率、平均接続数の負荷に応じて自動でリードレプリカ台数をオートスケールします
上記により可用性、運用・課金コスト削減等のメリットを得る事が出来ます
急激に負荷が上がってしまった場合を想定して、障害を未然に防ぐ為にも標準で取り入れた方が良いと考えています

リードレプリカへの負荷が高まるとオートスケール処理が開始され、自動でスケールアップ(増大)を行う
image.png

読込処理も分散されます
image.png

Cron式スケジュール

負荷が高まる時間帯を事前に分かる場合は、Cron式スケジュールでリードレプリカを増やす事が出来ます
※12時負荷が高まる場合、事前に11時にリードレプリカ台数を増やす、下記は3台から5台に増えた図です
image.png

次回

2.【AWS】Auroraオートスケール:②オートスケール設定

参考

[AWS] Amazon Auroraについて
Amazon Aurora

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Amplify フレームワークの使い方Part14〜Lambda レイヤー編〜

はじめに

Lambda関数を複数作成していると、このライブラリや関数を共通化したいな、と思うことがよく有りました。そんな時、気づいたら追加されていたLambdaのレイヤー機能を使えば、一発解決です。

バージョン

amplify-cli 4.32.1

実装方法

新規作成

まずは、関数を追加します。

$ amplify add function

レイヤーを選択。

? Select which capability you want to add:
> Lambda layer (shared code & resource used across functions)

名前を決めて、実行環境は今回はNodeJSを選択します。

? Provide a name for your Lambda layer: testLayer
? Select up to 2 compatible runtimes: NodeJS

同一のアカウントor同一の組織(Organizationsで設定したAWSアカウント)or全体公開の3つからアクセス権限を選びます。同一アカウントだけでなく同一の組織とも共通化できるなんて素晴らしいですね。

? The current AWS account will always have access to this layer.
Optionally, configure who else can access this layer. (Hit <Enter> to skip) (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ Specific AWS accounts
 ◯ Specific AWS organization
 ◯ Public (Anyone on AWS can use this layer)

これで準備完了です。ライブラリの追加は、自動生成された関数フォルダ内の/lib/nodejs直下に移動して、必要なライブラリをインストールしてください。

$ cd amplify/backend/function/testLayer/lib/nodejs/

関数の共通化をしたい場合は、/opt直下にtestLayer.jsを作成し、共通化したい関数を記載すれば、各Lambda関数から呼び出すことができます。(ファイル名は何でもいいですが、後で各関数からこのファイル名を呼び出すので、レイヤー名と同じがわかりやすいと思います。)

$ cd amplify/backend/function/testLayer/opt/
$ touch testLayer.js 
/opt/testLayer.js
module.exports = {
  // 現時刻の取得
  testFunction: () => {
   console.log('test!!!')
  }
}

紐付け

紐付けたいLambda関数の作成時または更新時に紐付けの設定を行います。

$ amplify function add
or
$ amplify function update

設定を進めていくと以下のようにレイヤーん設定をどうするか聞かれますので、Yesを選択し、紐付けしたいレイヤーとそのバージョンを選択します。

? Do you want to configure Lambda layers for this function?
> Yes
? Provide existing layers or select layers in this project to access from this function (pick up to 5):
> testLayer
? Select a version for testLayer:
> 1

レイヤーは5つまで選択することができます。複数のレイヤーを紐付けた場合はその順番を並び替えることで、競合する箇所があれば前のレイヤーを上書きします。

? Modify the layer order (Layers with conflicting files will overwrite contents of layers earlier in the list):
testLayer
testLayer2

また、共通化した関数を使用したい場合は、紐付けるLambda関数のindex.jsに記載します。

index.js
const TEST_LAYER = require('/opt/testLayer')
exports.handler = () => {
  TEST_LAYER.testFunction()
}

あとはいつものコマンドでローカルの更新情報をアップしたらお終いです。たったこれだけの設定なんてすばらしい。

$ ampify push

更新

コードやライブラリを更新して $ amplify pushすると以下の質問ができてきます。最新のレイヤーと同じ権限かこのアカウントのみの権限にするかを選択すると、新しいバージョンのレイヤーが作成されます。

What permissions do you want to grant to this new layer version? 
❯ The same permission as the latest layer version 
  Only accessible by the current account. You can always edit this later with: amplif
y update function 

レイヤーはそんなに更新するものではないかもしれませんが、ここでひとつ問題が。

基本的に既存のバージョンを更新するのはではなく、新しいバージョンを追加する形のため、その更新した新しいレイヤーに関しては、再度各関数に紐付けが必要です。

これって地味に大変ですよね、、、。何かいい方法があれば教えていただきたい、、、。

削除

レイヤーの削除については、わかっていないことが多く、苦しめられる可能性があるので、注意が必要です。

$ amplify function remove

このコマンドで消したらこれまでの様々な関数のとの関係を解消してすべてがなかったことに、なってくれたらなんて幸せなことか、、、。

紐付けの解消が、まぁー何故かうまく行かない、、、。(わたしだけ?)
amplify function updateで紐付けている関数を更新してちゃんと紐付けを解消し、pushし、その上でremoveをしても、紐付けをちゃんと解除してから削除しろ、と怒られ、現状スマートな方法が見つかりませんでした。(紐付け解消後に、backend.configや紐付けた関数のtemplate内に残っているlayer情報を削除したりしましたがエラー、、、。)

結局現段階では、紐付けた関数を一旦削除してから、layer関数も削除するという力技なんとかしています。

この削除のスマートな方法も誰か知っていたら教えていただきたい、、、。

おわりに

と、最後はやや愚痴気味になってしまいましたが、そんなトラブルがあってもメリットのほうが大きいので、大いに役に立ってはくれそうです。

よきAmplifyライフを!!

参考記事

How to use Lambda layers with the Amplify CLI(公式コラム)

関連記事

AWS amplify フレームワークの使い方Part1〜Auth設定編〜
AWS Amplify フレームワークの使い方Part2〜Auth実践編〜
AWS Amplify フレームワークの使い方Part3〜API設定編〜
AWS Amplify フレームワークの使い方Part4〜API実践編〜
AWS Amplify フレームワークの使い方Part5〜GraphQL Transform @model編〜
AWS Amplify フレームワークの使い方Part6〜GraphQL Transform @auth編〜
AWS Amplify フレームワークの使い方Part7〜GraphQL Transform @key編〜
AWS Amplify フレームワークの使い方Part8〜GraphQL Transform @connection編〜
AWS Amplify フレームワークの使い方Part9〜Function 基礎編〜
AWS Amplify フレームワークの使い方Part10〜Storage編〜
AWS Amplify フレームワークの使い方Part11〜Function 権限管理編〜
AWS Amplify フレームワークの使い方Part12〜ENV編〜
AWS Amplify フレームワークの使い方Part13〜Auth 設定更新編〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3のサーバーサイド暗号化とダウンロード経路

TL;DR

以下の組み合わせのダウンロード可否を調査する機会があったのでまとめます。

  • サーバーサイド暗号化の種類
    • なし
    • SSE-S3
    • SSE-KMS
  • ダウンロード経路
    • 静的ホスティング
    • Get Object URL
    • Presigned URL
    • CloudFront

結果だけ気になる人は結論へ飛んでください。

サーバーサイド暗号化

S3にはサーバーサイド暗号化(Server Side Encryption、SSE)という機能があります。
保存時に暗号化が行われ、取得時に復号されるので、利用者はあまり意識せずにオブジェクトを暗号化することができます。
公式ドキュメント

サーバーサイド暗号化の種類

サーバーサイド暗号化には現在3つの暗号化の方法があります。

SSE-Cを利用するシーンは(個人的に)あまりないため、今回は「暗号化なし」「SSE-S3」「SSE-KMS」を対象に調査を行うことにします。

SSE-S3

AWSが用意したS3用の暗号鍵を用いて暗号化を行います。
公式ドキュメント

SSE-KMS

ユーザーがAWS KMSで作成した鍵を用いて暗号化を行います。
公式ドキュメント

SSE-C

ユーザーが作成した鍵を用いて暗号化を行います。
オブジェクトをS3にアップロードする際とダウンロードする際に暗号鍵を指定します。
AWS上に暗号鍵をアップロードすることなく、手元で管理することが可能です。
公式ドキュメント

S3上のオブジェクトのダウンロード経路

さて、S3上のオブジェクトをアプリケーションから取得する方法はいくつか存在します。

  • S3の静的サイトホスティング機能
  • S3のGet Object URL
  • S3のPresigned URL(SigV4)
  • CloudFrontのOriginに指定
  • アプリケーション上でAWS SDKで取得

アプリケーション上でAWS SDKで取得に関しては、当然どのようなサーバーサイド暗号化であろうと取得可能なので、今回の調査では対象外とします。

実装

Terraformでサクッと調査対象のS3バケットやCloudFrontなどを実装しました。

結論

結果は以下のようになりました。

SSEなし SSE-S3 SSE-KMS
静的ホスティング ×
Get Object URL ×
Presigned URL
CloudFront ×

要件次第ですが、SSE-S3が無難かなと。

おまけ

SSE-KMS + CloudFrontはLambda Edgeで署名を付与することで復号できるようになるようです。
https://aws.amazon.com/jp/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Amplify フレームワークの使い方Part13〜Auth 設定更新編〜

はじめに

あとあとAuthの設定を変更したいということは出てくるかと思います。変更不可な項目もありますが、今回はAmplifyを通して更新できるものを紹介していきます。

バージョン

amplify-cli 4.32.1

Authの設定

まずはおなじみのコマンドから実行で複数の選択項目が出てきます。Authの設定状況によってこの項目は変わるようなので、知っている範囲内で解説していきます。

$ amplify auth update
 What do you want to do? (Use arrow keys)
  Apply default configuration without Social Provider (Federation) 
  Apply default configuration with Social Provider (Federation) 
❯ Walkthrough all the auth configurations 
  Add/Edit signin and signout redirect URIs 
  Update OAuth social providers 
  Create or update Cognito user pool groups 
  Create or update Admin queries API 

Apply default configuration without Social Provider (Federation)

ソーシャルプロバイダなしでのCognitoのデフォルトをテンプレートに作り直してくれます。

Apply default configuration with Social Provider (Federation)

ソーシャルプロバイダありでのCognitoのデフォルトをテンプレートに作り直してくれます。

Add/Edit signin and signout redirect URIs

ソーシャルログインでのサインインおよびサインアウト時の遷移先のURLを更新できます。

Update OAuth social providers

OAuthの設定を更新できます。

Create or update Cognito user pool groups

Cognitoのグループの新規作成および更新が行なえます。

Create or update Admin queries API

いまだによくわかっていない、このアドミン用API。管理者グループに所属していればなんでもアクセス化的なことなんだとは思っているのですが、手つかずでございます。

Walkthrough all the auth configurations

細かい設定を行う場合はこの項目を選択して各項目の再設定をしていきます。

更新ができる全項目についてどうするか聞かれますので、1つ1つ設定をしていきます。

User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage fe

atures for images or other content, Analytics, and more)
選択項目はこの1つのみなので、そのまま選択。

Do you want to add User Pool Groups? (Use arrow keys)

Cognitoのグループの変更(削除、追加、優先順位変更)がこの項目から行えます。

Do you want to add an admin queries API? (Use arrow keys)

いまだによくわかっていない、このアドミン用API。管理者グループに所属していればなんでもアクセス化的なことなんだとは思っているのですが、手つかずでございます。とりあえず、Noを選択。

Email based user registration/forgot password: (Use arrow keys)

新規登録時およびパスワード忘れたときの認証をメールで行うか、
基本メールでいいと思っています。(SMS/TOTPの場合をあまり白台だけ。)

❯ Enabled (Requires per-user email entry at registration) 
  Disabled (Uses SMS/TOTP as an alternative) 

Please specify an email verification subject:

メール認証を有効にした場合の件名の入力。

Please specify an email verification message:

メール認証を有効にした場合の文章入力。

Do you want to override the default password policy for this User Pool?

パスワードポリシーを変更したい場合はこちらから。

Specify the app's refresh token expiration period (in days):

リフレッシュトークンの有効期限の変更。

Do you want to specify the user attributes this app can read and write? (y/N)

ユーザー属性(usernameとかemail)の読み込みと書き込み権限の再設定ができます。

Do you want to enable any of the following capabilities?

便利な機能たちがこんなにも簡単に実装できるなんて素晴らしい。(まだどれも試したことはないが。)

 ◯ Add Google reCaptcha Challenge
 ◯ Email Verification Link with Redirect
 ◯ Add User to Group
 ◯ Email Domain Filtering (blacklist)
❯◯ Email Domain Filtering (whitelist)
 ◯ Custom Auth Challenge Flow (basic scaffolding - not for production)
 ◯ Override ID Token Claims

Do you want to use an OAuth flow? (Use arrow keys)

OAuthの再設定ができます。Googleやfacebookのログイン設定をしたい場合はこちらから。

? Do you want to configure Lambda Triggers for Cognito? (Y/n)

Cognitoのトリガーに紐づく、Lambda関数を作成できます。

注意点として、そのLambda関数に色んなリソースのアクセス権限をつけてPUSHをするとエラーが起き更新ができなくなってしまうバグがあるため、注意が必要です。

現時点で、解決方法が見つからなかったので、普通に関数を作ってGUIからトリガーしているのが現状です。GUI管理は極力なくしたいので、いずれは解決したい問題の1つ。

Circular dependency between resources: [他の関数リソース名]
An error occurred during the push operation: Circular dependency between resources: [他の関数リソース名]

注意点/わかったこと

選択方法によって、上書きのされ方が違う

「Walkthrough all the auth configurations 」で設定をする場合は、問に対してNoと答えた場合は、
あくまでも設定しない、の意味なので、上書き処理は走らずに、前回の設定がそのまま残りました。

逆に「Update OAuth social providers」でOAuthの設定をしたときは、完全に OAuth情報が上書きされるため、1つOAuthのプロバイダを追加した場合は、必ず以前のプロバイダ情報も一緒に入力する必要があります。

項目ごとに検証はできていませんが、注意が必要です。

自分で追加したCloudFomationは要注意

$amplify auth updateで更新を行うと、amplifyフォルダ内のauthのファイルが更新されます。その際に、これまでにxxxxxxx -cloudformation-template.ymlのファイルに手書きで追加したコードについては消えてしまいます。
それに気づかずにpushしてしまうとエラーになって悲しいことになってしまいますので、更新後には必ずxxxxxxx -cloudformation-template.ymlに手書きコードを追加してからpushしましょう。

環境間で引き継がない情報もある

基本的には、環境を移動(amplify env checkout)したあとに、pushすれば、別の環境で整えた環境がそのまま同じように出来上がります。
細かく検証ができていませんが、例えばOAuthの登録した情報は基本的には引き継がれず、その環境ごとに設定が必要なようです。(OAuthに関して言えば、当たり前といえば当たり前だが。)

OAuthの設定については、もっとうまくやれる気はしているが、なにかシンプルな方法があれば教えてほしい、、、。

おわりに

Cognito自体はまだ使い切れていない機能がたくさんありそうなので、引き続き精進しなければと感じております。
Amplifyを利用する人の一助になれば幸いです。よきAmplifyライフを!!

関連記事

AWS amplify フレームワークの使い方Part1〜Auth設定編〜
AWS Amplify フレームワークの使い方Part2〜Auth実践編〜
AWS Amplify フレームワークの使い方Part3〜API設定編〜
AWS Amplify フレームワークの使い方Part4〜API実践編〜
AWS Amplify フレームワークの使い方Part5〜GraphQL Transform @model編〜
AWS Amplify フレームワークの使い方Part6〜GraphQL Transform @auth編〜
AWS Amplify フレームワークの使い方Part7〜GraphQL Transform @key編〜
AWS Amplify フレームワークの使い方Part8〜GraphQL Transform @connection編〜
AWS Amplify フレームワークの使い方Part9〜Function 基礎編〜
AWS Amplify フレームワークの使い方Part10〜Storage編〜
AWS Amplify フレームワークの使い方Part11〜Function 権限管理編〜
AWS Amplify フレームワークの使い方Part12〜ENV編〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS LambdaのPrivateLinkを試してみた

概要

2020/11/02のアップデートで、「AWS LambdaのPrivateLink対応」の発表がありました。
LambdaのPrivateLinkを試してみたいと思います。

AWS PrivateLink を使用してプライベート AWS ネットワーク経由で AWS Lambda にアクセスする

AWS Lambda Private Linkとは

VPCエンドポイントを作成してVPCからインターネットを経由せずに
Lambda関数を管理および呼び出すためのサービスです。

イメージ図

PrivateLink

lambda_privatelink_00.png

インターネット経由

lambda.png

やってみた

マネジメントコンソールからVPCの管理画面を開き、左メニューの「エンドポイント」をクリックします。

lambda_privatelink_01.png

「エンドポイントの作成」ボタンを押します。

lambda_privatelink_02.png

エンドポイントの作成画面に移動するので、サービスカテゴリは「AWSサービス」を選択した状態でサービス名の検索バーに「lambda」を入力すると以下の状態になるため、サービス名を選択し、インターフェースエンドポイントを作成するVPCを選択します。

lambda_privatelink_03.png

エンドポイントを作成する可能性があるサブネットを指定します。

lambda_privatelink_04.png

必要に応じて、DNSオプションを有効にします。
エンドポイントに独自のDNSオプションを名を指定出来るようです。(未検証)

lambda_privatelink_05.png

セキュリティグループを指定します。
プロトコル、ポート、および送信元/送信先のIPアドレス制限が可能です。

lambda_privatelink_06.png

VPCエンドポイントにアクセス可能なユーザを制御するポリシーを設定します。
今回は検証のためデフォルトの「完全アクセス」を選択しました。
Amazon Web ServicesブログにIAMユーザ、ファンクションを指定するサンプルがありますので制限する場合はそちらを参考にしてください。

lambda_privatelink_07.png

「エンドポイントの作成」ボタンを押します。

lambda_privatelink_08.png

以下のような成功メッセージが表示されればエンドポイントの作成が完了です。

lambda_privatelink_09.png

設定後の確認

次に設定前後でどのように変わったのかをlambdaのエンドポイントにdigを実行して確認してみます。

設定前のlambdaエンドポイント

lambda_privatelink_20.png

設定後のlambdaエンドポイント

lambda_privatelink_21.png

lambdaのエンドポイントのIPアドレスがグローバルIPからプライベートIPに変わっていることがわかります。

ちなみに

Lambdaには、VPC内Labmdaと呼ばれる利用方法も可能です。

[発表] Lambda 関数が VPC 環境で改善されます

イメージ図

lambda_vpc.png

所感

今までNATゲートウェイなどで実現していた部分が不要になるので運用、コスト面での削減が可能になり、また、異なるアカウント間でのプライベートアクセスも簡単に可能となるため、利用場面が増えるのではないでしょうか。

誰かのご参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kinesis Data Streams のストリーミングデータを Lambda で処理する

はじめに

AWS では、いろいろなサーバーレスで構築したシステムから共通した部分を抜き出し、 "サーバーレスパターン" としてサービスの組み合わせを紹介しています。表題の「 Kinesis Data Streams のストリーミングデータを Lambda で処理する」という処理は、 "サーバーレスパターン" で "流入データの連続処理" として紹介されているものです。パターンの学習はやりたいことを実現するためのヒントとなり、共同作業をする人との共通意識となり作業のスピードを高める効果があります。
今回はこの "流入データの連続処理" としてあらわされている Kinesis Data Streams と Lambda の処理を組んでみたいと思います。以下の説明では 東京 (ap-northeast-1) リージョンを使用します。

「流入データの連続処理」パターンの概要

Pattern-Streaming.7b2876deed217d21f4e4e326fe1535be25cb9603.png

  1. プロデューサーから受け取ったデータを "Amazon Kinesis Data Streams" (以下、Kinesis と記載します) がストリーミングデータにする。
    • Kinesis にデータを送信するアプリケーションのことを "プロデューサー" と呼びます。
  2. Lambda は Kinesis からストリーミングデータを取り出し加工した後、加工したデータを S3 に保存する。
    • Kinesis からデータを取得して処理をするアプリケーションは "コンシューマー" と呼びます。

Kinesis を準備する

  1. Amazon Kinesis コンソールのデーターストリームページから、"データーストリームの作成" を選択してください。
  2. データストリームの作成ページで以下のプロパティを入力して "データストリームの作成" を選択してください。
    • データストリーム欄:データストリーム名 - MyDataStreams
    • データストリームの容量欄:
      • シャドーエスティメーター デフォルトのまま
      • 開いているシャードの数 - 1

S3 を準備する

  1. Amazon S3 コンソールを開きます。バケットページで "バケットを作成" を選択します。
  2. "バケットを作成" ページにて以下のプロパティを入力して "バケットを作成" を選択してください。
    • 一般的な設定欄:
      • バケット名 - mydatastreams-bucket
      • リージョン - アジアパシフィック(東京)ap-northeast-1
    • 他の値はすべてデフォルトとします

実行ロールを準備する

  1. IAM コンソールで、ロールページを開き、"ロールの作成" を選択します。
  2. 次のプロパティでロールを作成します。
    • 信頼されたエンティティ - AWS サービス
    • ユースケース - Lambda
    • Attach アクセス権限ポリシー - AWSLambdaExecute 、および AWSLambdaKinesisExecutionRole
    • ロール名 - my-datastreams-role
    • ロールの説明 - Allows Lambda functions to read data records and create data in the bucket.

Lambda ( コンシューマー ) を準備する

Kinesis をイベントソースとして Lambda にデータをおくるイベントソースマッピングを作成します。

  1. Lambda コンソールの 関数ページを開き、"関数の作成" を選択します。
  2. 次のプロパティを設定し、"関数の作成" を選択します。
    • 関数の作成 - 一から作成
    • 関数名 - myDatastreamsFunction
    • ランタイム - Node.js 12.x
    • デフォルトの実行ロールの変更
      • 実行ロール - 既存のロールを使用する
      • 既存のロール - 先ほど作成したロール my-datastreams-role を選びます。
  3. デザイナーペインで "トリガーの追加" を選択します。
  4. トリガーを追加ページで、次のプロパティを設定し、"追加" を設定します。
    • トリガーの設定 - Kinesis
    • Kinesis ストリーム - 先に用意した MyMyDataStreams を選択する
    • コンシューマー - コンシューマーなし (デフォルト)
    • バッチサイズ - 100 (デフォルト)
    • バッチウィンドウ - オプション - なし
    • 開始位置 - 最新 (デフォルト)
    • トリガーの有効化 - チェック
  5. 関数コードペインの index.js を次のように変更し、"Deploy" を選択します。
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {

    let submits = [];

    event.Records.forEach(record => {
        // Kinesis data is base64 encoded so decode here
        var payload = Buffer.from(record.kinesis.data, 'base64').toString('ascii');
        console.log('Decoded payload:', payload);
        let params = {
            Bucket: 'mydatastreams-bucket',
            Key: `${record.eventID}.json`,
            Body: JSON.stringify({'key1': payload})
        };
        submits.push(s3.putObject(params).promise());
    });
    try {
        await Promise.all(submits);
    } catch (error) {
        console.log(error);
        return {
            success: false,
            errorMessage: error.message
        };
    }

    return {
        success: true
    };
};

プロデューサー用のロールを準備する

今回は EC2 から Kinesis エージェント を利用して Kinesis へデータを送信します。EC2 へは Systems Manager によりインスタンスに接続します。ここでは EC2 に割り当てるロールを準備します。

まず、Kinesis へデータを書き込むためのポリシーを用意します。

  • IAM コンソールで、ポリシーページを開き、"ポリシーの作成" を選択します。
  • "JSON" タブを選択し、次の JSON を入力します。Amazon リソースネームの部分のフォーマットは arn:aws:kinesis:region:account-id:stream/stream-name になります。account-id 部分 (下の 111122223333 部分) は自分のアカウント ID に置き換えてください。入力が終わったら "ポリシーの確認" を選択します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:PutRecords"
            ],
            "Resource": [
                "arn:aws:kinesis:ap-northeast-1:111122223333:stream/*"
            ]
        }
    ]
}
  • ポリシーの作成ページにて、以下のプロパティを入力して "ポリシーの作成" を選択します。
    • 名前 - MyDataStreamsPolicy
    • 説明 - Allows producer to write data records.

次にロールを用意します。

  • IAM コンソールで、ロールページを開き、"ロールの作成" を選択します。
  • 次のプロパティでロールを作成します。
    • 信頼されたエンティティ - AWS サービス
    • ユースケース - 一般的なユースケースから EC2 を選択して、"次のステップ:アクセス権限" を選択します。
    • Attach アクセス権限ポリシー - AmazonEC2RoleforSSM と先ほど作成した MyDataStreamsPolicy
    • ロール名 - MyDataStreamsRole
    • ロールの説明 - Allows EC2 instances to call Kinesis data streams on your behalf.

プロデューサーを準備する

  • EC2 コンソールから、インスタンスページを開き、 "インスタンスを起動" を選択します。
  • 次のプロパティで EC2 を起動します。
    • Amazon マシンイメージ - Amazon Linux 2 AMI (HVM), SSD Volume Type64 ビット(x86)
    • インスタンスタイプの選択 - タイプ t2.micro
    • インスタンスの詳細設定
      • インスタンス数 - 1 (デフォルト)
      • ネットワーク - デフォルトVPC
      • サブネット - デフォルトサブネット
      • IAM ロール - MyDataStreamsRole
      • 他はすべてデフォルト設定
    • セキュリティグループの設定
      • セキュリティグループの割り当て - 新しいセキュリティグループを作成する
      • ルールは削除してください。
  • インスタンス作成の確認ページにて "起動" を選択すると下のイメージにあるダイアログが現れます。ここでは キーペアなしで続行 を選択し、下のチェックボックスにチェックを入れ、"インスタンスの作成" を選択します。

Screenshot_2020-11-23 インスタンスウィザードを起動 EC2 Management Console.png

  • インスタンスID を確認し、インスタンスの状態が "実行中" に変わったら、Systems Manager コンソールを開きます。
  • セッションマネージャーページで、"セッションの開始" を選択します。ターゲットインスタンスのリストから先ほど確認したインスタンス ID のラジオボタンをチェックして、"セッションを開始する" を選択します。
  • 次のコマンドを使用してエージェントをインストールします。
sudo yum install –y aws-kinesis-agent
  • 設定ファイル (/etc/aws-kinesis/agent.json) を開き、編集します。
sudo vi /etc/aws-kinesis/agent.json
{
  "cloudwatch.emitMetrics": false,
  "kinesis.endpoint": "kinesis.ap-northeast-1.amazonaws.com",
  "flows": [
    {
      "filePattern": "/tmp/app.log*",
      "kinesisStream": "MyDataStreams"
    }
  ]
}
  • エージェントを開始します。
sudo service aws-kinesis-agent start
  • データを作成して、エージェントに送信させます。うまくいかない場合は、こちら /var/log/aws-kinesis-agent/aws-kinesis-agent.log にエージェントのログが出力されています。
echo "Hello, this is a test." > /tmp/app.log1

確認する

  • S3 コンソールから、バケットページを開き、"mydatastreams-bucket" を選択します。
  • オブジェクトペインに作成したファイルが格納されていると思います。オブジェクトにチェックを入れ、アクションから "ダウンロード" を選択するとファイルをダウンロードできます。

Screenshot_2020-11-24 S3 Management Console.png

もし、ファイルが作成されていなかったら、 Kinesis エージェントのログや、Lambda のログを確認してみてください。以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 Route 53 + ACM + CloudFront + S3 構成の構築でハマったこと

この記事の対象者

  • Route 53 + ACM + CloudFront + S3 構成を構築しようと試みている人
  • AWS で独自ドメインで HTTPS 通信でWebサイトを配信したい人
  • AWS 初心者

はじめに

AWS で Web サイトを独自ドメインで配信するにはどうしたらいいのか調べてたところ、どうも Route 53 + ACM + CloudFront + S3 の構成がスタンダードのようでした。

【参考】
AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む)

そして、この構成についての参考になるサイトがたくさん存在します。

以下リンクになります。

AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
AWSをフル活用してブログをdevドメインに移行した
Amazon S3 + AWS Certificate Manager (ACM) + Amazon CloudFront + オリジンアクセスアイデンティティ(OAI) でhttpsサイト公開

特に1番上の記事は全ての手順に画像があるので非常にわかりやすかったです。

初めはこれらに相当する記事を書こうと思ったのですが、上記のようにそのような記事は既にあったため、この記事は自分が実際に環境を構築した際にハマったところについて書いていきたいと思います。

ハマったところ

SSL やら DNSサーバー やら 証明書 が何だかわからない

独自ドメインを設定したりするため、SSL やら DNSサーバー やら 証明書 やらその辺の知識が必要になってきます。

ITパスポートレベルの基礎的なことだと思うのですが、この辺がわからなくて自分はかなりハマりました。

調べてよく理解しながら進むしかないと思います。

以下、よく見たサイトのリンクになります。

暗号化通信
HTTPS と SSL と TLS:その違いを5分でわかりやすく解説!
SSL/TLSとは何か

DNS レコード
DNSレコード
AレコードとCNAMEレコードの違い

全体感がわからない

解説の記事通りやっても、かなり操作が多いため、途中で自分が何を何のためにやっているかわからなくなります。

一応、私、なりに全体感を解説していきます。

まず、サンプルとして以下の値を設定したとして、全体感がわかるように手順を書いておきます。

設定値(サンプル)

  • 独自ドメイン名:hogehoge.com
  • S3 バケット名:mogemoge-bucket
  • 発行される CloudFront ドメイン名:nantoka.cloudfront.net. ← 実際は設定不可能な値
  • 一般ユーザーがサイトにアクセスする際のURL:https://pokapoka.hogehoge.com

独自ドメイン発行サービス(名前.com や freenom など、もちろん Route 53 で買ってもよい)

  • hogehoge.com というドメインを発行する

Route 53

  • hogehoge.com の HostedZone を作成する(Route 53 でドメインを購入した場合は自動で作成される)
  • (この操作は CloudFront 設定後の作業)CloudFront で代替ドメイン名 (CNAMEs)として登録したドメイン pokapoka.hogehoge.com と Distribution のドメイン nantoka.cloudfront.net. を結びつけるために ALIAS レコード(A レコード)を挿入する

ACM(AWS Certificate Manager)

S3

  • mogemoge-bucket というバケットを作成する(今回の構成ではドメイン名と合わせる必要はありません)
  • mogemoge-bucket を静的ウェブサイトとして公開する
  • mogemoge-bucket に静的コンテンツを配置する(最低限 index.html があればよい)

CloudFront

  • CloudFront の Distribution 作成する
    • Distribution を S3 の mogemoge-bucket に指定
    • Distribution の代替ドメイン名 (CNAMEs) を pokapoka.hogehoge.com と登録する(複数登録することも可能)
    • さきほど ACM で作成した証明書を指定する
    • CloudFront の Distribution のドメインが自動的に発行される(nantoka.cloudfront.net. など)(※このドメイン名は自動発行)
  • Distribution を作成後に CloudFront の Distribution の origin access identity(OAI)の編集から S3 の mogemoge-bucket へのアクセスを CloudFront を介してのみに制限する(これを行うとワンクリックで mogemoge-bucket のバケットポリシーが更新される)(※ これを設定しないと S3 の mogemoge-bucket は静的ウェブサイトとして公開しているため、CloudFront を経由せずに直接アクセス可能になってしまう)

操作の結果

そして、これらの手順の結果、各 AWS のサービスの状態と、その状態が表す意味は以下のようになります。

  • Route 53
    • CNAME レコード
      • ACM の DNS 検証 で挿入したレコード(証明書の発行のときに挿入したよ、普段はとくに使わないよ、このレコードがある間は ACM が証明書の自動更新をやってくれるよ)
    • A レコード
      • pokapoka.hogehoge.com = nantoka.cloudfront.net.pokapoka.hogehoge.comnantoka.cloudfront.net. のフリをするよ、名前解決のときに使うよ)
  • ACM
    • 証明書
      • hogehoge.com*.hogehoge.com というドメインに対する証明書(この証明書は ACM で管理しているよ、一度、証明書を発行したらここの設定を変えることはないよ)
  • CloudFront
    • Distribution
      • S3 mogemoge-bucketnantoka.cloudfront.net. のアクセス先は S3 の mogemoge-bucket だよ)
    • Distribution CNAMEs
      • nantoka.cloudfront.net. = pokapoka.hogehoge.comnantoka.cloudfront.net.pokapoka.hogehoge.com のフリをするよ、基本的に pokapoka.hogehoge.com でアクセスされたのを nantoka.cloudfront.net. に読み替えるよ)
    • SSL Certificate
      • *.hogehoge.com の証明書を設定(この Distribution では *.hogehoge.com の証明書を使うよ)
  • S3
    • 静的ウェブサイトホスティング設定
      • 有効(HTTP/HTTPS のリクエストがきたら mogemoge-bucket の中身をWebページとして返却するよ)
    • パケットポリシー
      • CloudFront のみ OK(mogemoge-bucket にアクセスにするには必ず CloudFront を経由してくださいね、それ以外の経路でアクセスしたら断ますよ)

図で表すと以下のようになります。
img_5f01d1bdc21cb.png
また、名前解決の通信のフローは以下の図のようになります。
ここでの 1 〜 7 までのフローが上の図の「ドメイン名の解決」、8 〜 9 のフローが上の図の「コンテンツ配信」に相当します。
how-route-53-routes-traffic.png
また、8 〜 9 は SSL 通信をしており、それを表すと以下の図のようになります。
fig02.png
このように 1 〜 7 までのフローを Route 53、8 〜 9 のフローを CloudFront のサービスが請け負っていることがわかるかと思います。

この辺の全体感を見失うとすぐに迷子になります。

【参考】
AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
ウェブサイトやウェブアプリケーションへのインターネットトラフィックのルーティング
SSL/TLSとは何か

freenom で無料ドメインが発行できない

この構成での解説記事は freenom というサイトで無料ドメインを作成して、それを用いて検証しているものが多くありました。

それに習って、無料ドメインを作成したかったのですが、なぜか作成できませんでした。

なので、仕方なく AWS の Route 53 は有料でしたが、年間 12-14 ドルほどで購入できるとのことでしたので、Route 53 でドメインを購入しました。

ドメインの購入は一瞬で作成できたので、初めから Route 53 で購入しておけば楽だったと後悔しました。

【参考】
Route53でドメインを購入方法

ACM での証明書のリクエストなにやっているかわからない問題

ACM での証明書のリクエストはなにやっているかわからなくて、何度も調べたので、私なりにまとめました。
(結局、公式ドキュメントを読んだらよく理解できました。)

ACM では証明書のリクエストをすると Amazon 認証局 (CA) が証明書を発行する前にドメイン名の所有者または管理者であることを検証します。

その検証の方法は以下の 2 種類あります。

  1. DNS 検証
  2. E メール検証

公式ドキュメントにもあるように DNS 検証の方が証明書の自動更新などの恩恵を受けられるので E メール検証よりも DNS 検証が推奨されています。

DNS 検証の手順は以下の通りです。

  1. DNS 検証を選択する
  2. DNS データベースに挿入する CNAME レコードを ACM が発行される
  3. 発行された CNAME レコードを DNS データベースに挿入する(Route 53 を DNS プロバイダにしている場合はACM のコンソールからワンクリックで挿入可能)
  4. CNAME レコード挿入後、しばらくすると自動的に ACM が DNS 検証を完了します(完了までに数分かかります)

ここで発行される CNAME レコードの値は ACM が所有するドメインを指すエイリアスであり、ACM が証明書を自動更新するときに使用されるらしいです(ここでのレコードの値については特に気にする必要はない理解)。

ACM での証明書のリクエストで行っていることはこのような感じになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 Route 53 + ACM + CloudFront + S3 の構成を構築した際にハマったところ

この記事の対象者

  • Route 53 + ACM + CloudFront + S3 構成を構築しようと試みている人
  • Route 53 + ACM + CloudFront + S3 構成を構築してみたがいまいち全体像がわからない人
  • AWS で独自ドメインで HTTPS 通信で Web サイトを配信したい人
  • AWS 初心者

はじめに

AWS で Web サイトを独自ドメインで配信するにはどうしたらいいのか調べてたところ、どうも Route 53 + ACM + CloudFront + S3 の構成がスタンダードのようでした。

【参考】
AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む)

そして、この構成についての参考になるサイトがたくさん存在します。

以下リンクになります。

AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
AWSをフル活用してブログをdevドメインに移行した
Amazon S3 + AWS Certificate Manager (ACM) + Amazon CloudFront + オリジンアクセスアイデンティティ(OAI) でhttpsサイト公開

特に1番上の記事は全ての手順に画像があるので非常にわかりやすかったです。

初めはこれらに相当する記事を書こうと思ったのですが、上記のようにそのような記事は既にあったため、この記事は自分が実際に環境を構築した際にハマったところについて書いていきたいと思います。

ハマったところ

基本的にここのサイトの手順になぞって構築してうまくいきました。
AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)

個人的にハマったところを書いていきたいと思います。

いまいち全体感がつかめない(この記事のメイン)

解説の記事通りやっても、かなり操作が多いため、途中で自分が何を、何のためにやっているか分からなくなります。

全体感が分かりやすくなるように、私なりに解説していきます。

まず、サンプルとして以下の値を設定するとして、各サービス別での操作を書いていきたいと思います。

設定値(サンプル)

  • 独自ドメイン名:hogehoge.com
  • S3 バケット名:mogemoge-bucket
  • 発行される CloudFront ドメイン名:nantoka.cloudfront.net. ← 実際は設定不可能な値
  • 一般ユーザーがサイトにアクセスする際のURL:https://pokapoka.hogehoge.com

各サービスごとに実施する操作

独自ドメイン発行サービス(お名前.com や freenom など、もちろん Route 53 でドメインを買ってもよい)

  • hogehoge.com というドメインを発行する(末尾が .com である必要はない)

Route 53

  • hogehoge.com の HostedZone ( = DNS レコードを格納できるところ) を作成する(Route 53 でドメインを購入した場合は自動で作成される)
  • (この操作は CloudFront 設定後の作業)CloudFront で代替ドメイン名(CNAMEs)として登録したドメイン pokapoka.hogehoge.com と、CloudFront の Distribution のドメイン nantoka.cloudfront.net. を結びつけるために ALIAS レコード(A レコード)を挿入する

ACM(AWS Certificate Manager)

  • hogehoge.com*.hogehoge.com というドメインに対する証明書を発行する(ワイルドカードを使ってドメインある程度まとめてドメインを発行したほうがあとあと便利)(参考:パブリック証明書のリクエスト

S3

  • mogemoge-bucket というバケットを作成する(今回の構成ではドメイン名と合わせる必要はありません)
  • mogemoge-bucket を静的ウェブサイトとして公開する
  • mogemoge-bucket に静的コンテンツをアップロードする(最低限 index.html があればよい)

CloudFront

  • CloudFront の Distribution 作成する
    • Distribution を S3 の mogemoge-bucket に指定
    • Distribution の代替ドメイン名 (CNAMEs) を pokapoka.hogehoge.com と登録する(複数登録することも可能)
    • さきほど ACM で作成した証明書を指定する
  • Distribution 作成すると Distribution のドメインが自動的に発行される(nantoka.cloudfront.net. など)(※このドメイン名は自動発行)
  • Distribution を作成後に CloudFront の Distribution の origin access identity(OAI)の編集から S3 の mogemoge-bucket へのアクセスを CloudFront を介してのみに制限する(これを行うとワンクリックで mogemoge-bucket のバケットポリシーが更新される)(これを設定しないと S3 の mogemoge-bucket は静的ウェブサイトとして公開しているため、CloudFront を経由せずに直接アクセス可能になってしまう)

操作の結果

そして、これらの手順の結果、各 AWS のサービスの状態と、その状態が表す意味は以下のようになります。

Route 53

  • CNAME レコード
    • ACM の DNS 検証 で挿入したレコード
      • (解説)証明書の発行のときに挿入したよ、普段はとくに使わないよ、このレコードがある間は ACM が証明書の自動更新をやってくれるよ
  • A レコード
    • pokapoka.hogehoge.com = nantoka.cloudfront.net.
      • (解説)pokapoka.hogehoge.comnantoka.cloudfront.net. のフリをするよ、名前解決のときに使うよ

ACM(AWS Certificate Manager)

  • 証明書
    • hogehoge.com*.hogehoge.com というドメインに対する証明書
      • (解説)この証明書は ACM で管理しているよ、一度、証明書を発行したらここの設定を変えることはないよ

CloudFront

  • Distribution
    • S3 mogemoge-bucket
      • (解説)nantoka.cloudfront.net. のアクセス先は S3 の mogemoge-bucket だよ
  • Distribution CNAMEs
    • nantoka.cloudfront.net. = pokapoka.hogehoge.com
      • (解説)nantoka.cloudfront.net.pokapoka.hogehoge.com のフリをするよ、基本的に pokapoka.hogehoge.com でアクセスされたのを nantoka.cloudfront.net. に読み替えるよ
  • SSL Certificate
    • *.hogehoge.com の証明書を設定
      • (解説)この Distribution では *.hogehoge.com の証明書を使うよ

S3

  • 静的ウェブサイトホスティング設定
    • 有効
      • (解説)HTTP/HTTPS のリクエストがきたら mogemoge-bucket の中身をWebページとして返却するよ
  • パケットポリシー
    • CloudFront のみ OK
      • (解説)mogemoge-bucket にアクセスにするには必ず CloudFront を経由してくださいね、それ以外の経路でアクセスしたら断ますよ

全体像

ここで、全体像を確認したいと思います。

まず、名前解決を含めた Web サイトにアクセスした際の通信のフローは以下の図のようになります。
how-route-53-routes-traffic.png

大きく分けて以下のフローに分けれれます。

  • 1 〜 7 :ドメインの名前解決
  • 8 〜 9 :コンテンツ配信

そのフローを、 Route 53 + ACM + CloudFront + S3 構成の全体像で当てはめると以下のようになります。
img_5f01d1bdc21cb.png

Route 53 は 「ドメインの名前解決する役割」 と 「ACM の証明書リクエストを検証する役割」があるということが分かります。

また、CloudFront は 「証明書が置いてある Web サーバーとしての役割」 と 「キャッシュサーバーとしての役割」 があることがわかります。

ちなみに、8 〜 9のコンテンツ配信は SSL 通信をしており、その詳細のフローは以下の図のようになります。
fig02.png

【参考】
AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
ウェブサイトやウェブアプリケーションへのインターネットトラフィックのルーティング
SSL/TLSとは何か

SSL やら DNSサーバー やら 証明書 が何だかわからない

今回の構成は SSL やら DNSサーバー やら 証明書 やらその辺の知識が必要になってきます。

ITパスポートレベルの基礎的なことだと思うのですが、自分はこの辺の理解が乏しく、よくわからないまま環境を構築することになりました。

(自分が無知なだけでありますが、)AWS の公式ドキュメントは割とそのあたりの知識があることを前提としているので、基本的な用語などについては別で調べて、よく理解しながら進むしかないと思います。

以下、よく見たサイトのリンクになります。

暗号化通信
HTTPS と SSL と TLS:その違いを5分でわかりやすく解説!
SSL/TLSとは何か

DNS レコード
DNSレコード
AレコードとCNAMEレコードの違い

freenom で無料ドメインが発行できない

この構成での解説記事は freenom というサイトで無料ドメインを作成して、それを用いて検証しているものが多くありました。

それに習って、無料ドメインを作成したかったのですが、なぜか作成できませんでした。

なので、仕方なく AWS の Route 53 は有料でしたが、年間 12-14 ドルほどで購入できるとのことでしたので、Route 53 でドメインを購入しました。

ドメインの購入は一瞬で作成できたので、初めから Route 53 で購入しておけば楽だったと後悔しました。

【参考】
Route53でドメインを購入方法

ACM での証明書のリクエスト時の DNS 検証がよくわかわからない

ACM での証明書のリクエストはなにやっているかわからなくて、何度も調べたので、私なりにまとめました。
(結局、公式ドキュメントを読んだらよく理解できました。)

以下、解説になります。

ACM では証明書のリクエストをすると Amazon 認証局 (CA) が証明書を発行する前にドメイン名の所有者または管理者であることを検証します。

その検証の方法は以下の 2 種類があります。

  1. DNS 検証
  2. E メール検証

公式ドキュメントにもあるように DNS 検証の方が証明書の自動更新などの恩恵を受けられるので E メール検証よりも DNS 検証が推奨されています。

DNS 検証の手順は以下の通りです。

  1. DNS 検証を選択する
  2. DNS データベースに挿入する CNAME レコードを ACM が発行される
  3. 発行された CNAME レコードを DNS データベースに挿入する(Route 53 を DNS プロバイダにしている場合はACM のコンソールからワンクリックで挿入可能)
  4. CNAME レコード挿入後、しばらくすると自動的に ACM が DNS 検証を完了します(完了までに数分かかります)

ここで発行される CNAME レコードの値は ACM が所有するドメインを指すエイリアスであり、ACM が証明書を自動更新するときに使用されるらしいです(ここでのレコードの値については特に気にする必要はない理解)。

ACM での証明書のリクエストで行っていることはこのような感じになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 Route 53 + ACM + CloudFront + S3 の構成を構築する際につまずいたところ解説

この記事の対象者

  • Route 53 + ACM + CloudFront + S3 構成を構築しようと試みている人
  • Route 53 + ACM + CloudFront + S3 構成を構築してみたがいまいち全体像がわからない人
  • AWS で独自ドメインで HTTPS 通信で Web サイトを配信したい人
  • AWS 初心者

はじめに

AWS で Web サイトを独自ドメインで配信するにはどうしたらいいのか調べてたところ、どうも Route 53 + ACM + CloudFront + S3 の構成がスタンダードのようでした。

【参考】
AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む)

そして、この構成についての参考になるサイトがたくさん存在します。

以下リンクになります。

AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
AWSをフル活用してブログをdevドメインに移行した
Amazon S3 + AWS Certificate Manager (ACM) + Amazon CloudFront + オリジンアクセスアイデンティティ(OAI) でhttpsサイト公開

特に1番上の記事は全ての手順に画像があるので非常にわかりやすかったです。

初めはこれらに相当する記事を書こうと思ったのですが、上記のようにそのような記事は既にあったため、この記事は自分が実際に環境を構築した際につまずいたところについて書いていきたいと思います。

つまずいたところ解説

基本的にここのサイトの手順になぞって構築してうまくいきました。
AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)

個人的につまずいたところを書いていきたいと思います。

全体感がつかめない(この記事のメイン)

解説の記事通りやっても、かなり操作が多いため、途中で自分が何を、何のためにやっているか分からなくなります。

全体感が分かりやすくなるように、私なりに解説していきます。

まず、サンプルとして以下の値を設定するとして、各サービス別での操作を書いていきたいと思います。

設定値(サンプル)

  • 独自ドメイン名:hogehoge.com
  • S3 バケット名:mogemoge-bucket
  • 発行される CloudFront ドメイン名:nantoka.cloudfront.net. ← 実際は設定不可能な値
  • 一般ユーザーがサイトにアクセスする際のURL:https://pokapoka.hogehoge.com

各サービスごとに実施する操作

独自ドメイン発行サービス(お名前.com や freenom など、もちろん Route 53 でドメインを買ってもよい)

  • hogehoge.com というドメインを発行する(末尾が .com である必要はない)

Route 53

  • hogehoge.com の HostedZone ( = DNS レコードを格納できるところ) を作成する(Route 53 でドメインを購入した場合は自動で作成される)
  • (この操作は CloudFront 設定後の作業)CloudFront で代替ドメイン名(CNAMEs)として登録したドメイン pokapoka.hogehoge.com と、CloudFront の Distribution のドメイン nantoka.cloudfront.net. を結びつけるために ALIAS レコード(A レコード)を挿入する

ACM(AWS Certificate Manager)

  • hogehoge.com*.hogehoge.com というドメインに対する証明書を発行する(ワイルドカードを使ってドメインある程度まとめてドメインを発行したほうがあとあと便利)(参考:パブリック証明書のリクエスト

S3

  • mogemoge-bucket というバケットを作成する(今回の構成ではドメイン名と合わせる必要はありません)
  • mogemoge-bucket を静的ウェブサイトとして公開する
  • mogemoge-bucket に静的コンテンツをアップロードする(最低限 index.html があればよい)

CloudFront

  • CloudFront の Distribution 作成する
    • Distribution を S3 の mogemoge-bucket に指定
    • Distribution の代替ドメイン名 (CNAMEs) を pokapoka.hogehoge.com と登録する(複数登録することも可能)
    • さきほど ACM で作成した証明書を指定する
  • Distribution 作成すると Distribution のドメインが自動的に発行される(nantoka.cloudfront.net. など)(※このドメイン名は自動発行)
  • Distribution を作成後に CloudFront の Distribution の origin access identity(OAI)の編集から S3 の mogemoge-bucket へのアクセスを CloudFront を介してのみに制限する(これを行うとワンクリックで mogemoge-bucket のバケットポリシーが更新される)(これを設定しないと S3 の mogemoge-bucket は静的ウェブサイトとして公開しているため、CloudFront を経由せずに直接アクセス可能になってしまう)

操作の結果

そして、これらの手順の結果、各 AWS のサービスの状態と、その状態が表す意味は以下のようになります。

Route 53

  • CNAME レコード
    • ACM の DNS 検証 で挿入したレコード
      • (解説)証明書の発行のときに挿入したよ、普段はとくに使わないよ、このレコードがある間は ACM が証明書の自動更新をやってくれるよ
  • A レコード
    • pokapoka.hogehoge.com = nantoka.cloudfront.net.
      • (解説)pokapoka.hogehoge.comnantoka.cloudfront.net. のフリをするよ、名前解決のときに使うよ

ACM(AWS Certificate Manager)

  • 証明書
    • hogehoge.com*.hogehoge.com というドメインに対する証明書
      • (解説)この証明書は ACM で管理しているよ、一度、証明書を発行したらここの設定を変えることはないよ

CloudFront

  • Distribution
    • S3 mogemoge-bucket
      • (解説)nantoka.cloudfront.net. のアクセス先は S3 の mogemoge-bucket だよ
  • Distribution CNAMEs
    • nantoka.cloudfront.net. = pokapoka.hogehoge.com
      • (解説)nantoka.cloudfront.net.pokapoka.hogehoge.com のフリをするよ、基本的に pokapoka.hogehoge.com でアクセスされたのを nantoka.cloudfront.net. に読み替えるよ
  • SSL Certificate
    • *.hogehoge.com の証明書を設定
      • (解説)この Distribution では *.hogehoge.com の証明書を使うよ

S3

  • 静的ウェブサイトホスティング設定
    • 有効
      • (解説)HTTP/HTTPS のリクエストがきたら mogemoge-bucket の中身をWebページとして返却するよ
  • パケットポリシー
    • CloudFront のみ OK
      • (解説)mogemoge-bucket にアクセスにするには必ず CloudFront を経由してくださいね、それ以外の経路でアクセスしたら断ますよ

全体像

ここで、全体像を確認したいと思います。

まず、名前解決を含めた Web サイトにアクセスした際の通信のフローは以下の図のようになります。
how-route-53-routes-traffic.png

大きく分けて以下のフローに分けれれます。

  • 1 〜 7 :ドメインの名前解決
  • 8 〜 9 :コンテンツ配信

そのフローを、 Route 53 + ACM + CloudFront + S3 構成の全体像で当てはめると以下のようになります。
img_5f01d1bdc21cb.png

Route 53 は 「ドメインの名前解決する役割」 と 「ACM の証明書リクエストを検証する役割」があるということが分かります。

また、CloudFront は 「証明書が置いてある Web サーバーとしての役割」 と 「キャッシュサーバーとしての役割」 があることがわかります。

ちなみに、8 〜 9のコンテンツ配信は SSL 通信をしており、その詳細のフローは以下の図のようになります。
fig02.png

【参考】
AWSで独自ドメインのhttpsな静的Webサイトを構築する(ACM+S3+CloudFront+Route53)
ウェブサイトやウェブアプリケーションへのインターネットトラフィックのルーティング
SSL/TLSとは何か

SSL やら DNSサーバー やら 証明書 が何だかわからない

今回の構成は SSL やら DNSサーバー やら 証明書 やらその辺の知識が必要になってきます。

ITパスポートレベルの基礎的なことだと思うのですが、自分はこの辺の理解が乏しく、よくわからないまま環境を構築することになりました。

(自分が無知なだけでありますが、)AWS の公式ドキュメントは割とそのあたりの知識があることを前提としているので、基本的な用語などについては別で調べて、よく理解しながら進むしかないと思います。

以下、よく見たサイトのリンクになります。

暗号化通信
HTTPS と SSL と TLS:その違いを5分でわかりやすく解説!
SSL/TLSとは何か

DNS レコード
DNSレコード
AレコードとCNAMEレコードの違い

freenom で無料ドメインが発行できない

この構成での解説記事は freenom というサイトで無料ドメインを作成して、それを用いて検証しているものが多くありました。

それに習って、無料ドメインを作成したかったのですが、なぜか作成できませんでした。

なので、仕方なく AWS の Route 53 は有料でしたが、年間 12-14 ドルほどで購入できるとのことでしたので、Route 53 でドメインを購入しました。

ドメインの購入は一瞬で作成できたので、初めから Route 53 で購入しておけば楽だったと後悔しました。

【参考】
Route53でドメインを購入方法

ACM での証明書のリクエスト時の DNS 検証がよくわかわからない

ACM での証明書のリクエストはなにやっているかわからなくて、何度も調べたので、私なりにまとめました。
(結局、公式ドキュメントを読んだらよく理解できました。)

以下、解説になります。

ACM では証明書のリクエストをすると Amazon 認証局 (CA) が証明書を発行する前にドメイン名の所有者または管理者であることを検証します。

その検証の方法は以下の 2 種類があります。

  1. DNS 検証
  2. E メール検証

公式ドキュメントにもあるように DNS 検証の方が証明書の自動更新などの恩恵を受けられるので E メール検証よりも DNS 検証が推奨されています。

DNS 検証の手順は以下の通りです。

  1. DNS 検証を選択する
  2. DNS データベースに挿入する CNAME レコードを ACM が発行される
  3. 発行された CNAME レコードを DNS データベースに挿入する(Route 53 を DNS プロバイダにしている場合はACM のコンソールからワンクリックで挿入可能)
  4. CNAME レコード挿入後、しばらくすると自動的に ACM が DNS 検証を完了します(完了までに数分かかります)

ここで発行される CNAME レコードの値は ACM が所有するドメインを指すエイリアスであり、ACM が証明書を自動更新するときに使用されるらしいです(ここでのレコードの値については特に気にする必要はない理解)。

ACM での証明書のリクエストで行っていることはこのような感じになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

M1 MackbookでAmazon EBSをマウントする

我がM1 MackBookの、蓋開けから画面点灯まで速すぎるとか、Safariの動作が爆速過ぎるとか、電池が長持ちし過ぎて電源ケーブルつけてないことを忘れるとか、色々快適すぎて毎日macをいじる今日この頃。今回は、SSHFSを使ってAWS EC2ボリュームをマウントしたので、その時のメモです。ちょうどApple Silicon対応したDeveloper Previewがあったので、ありがたく使わせていただきました。

FUSE for macOSをインストール

https://osxfuse.github.io

Apple Silicon対応のDeveloper Preview macFUSE 4.0.0以降をダウンロード&インストール

※SSHFSだけに用があったのですが、FUSE for macOS(macFUSE?)も必要とのことで先にインストールします。
image.png
真ん中のInstall macFUSEを選択
image.png
途中、以下のダイアログが出ますので指示通りに、環境設定を開きます。

一旦電源切る -> 電源長押し -> パスワード解除 -> 起動セキュリティユーティリティ -> "Machintosh HD"のセキュリティポリシー -> 低セキュリティ -> 確認済みの開発元から...のチェックを有効 -> システム終了

起動 -> セキュリティとプライバシー -> 鍵アイコン解除 -> 開発元"Benjyamin... を許可 -> システム再起動
image.png

SSHFSをインストール

トップページからSSHFS 2.5.0をダウンロード&インストール
スクリーンショット 2020-11-24 11.14.30.jpeg
完了後、sshfsを実行すると以下のようなエラーが出るので、

dyld: Library not loaded: /usr/local/lib/libosxfuse_i64.2.dylib

リンクを貼る。

cd /usr/local/lib
sudo ln -s libfuse.2.dylib libosxfuse_i64.2.dylib

Amazon EBSをマウントする

sshfs -o IdentityFile=private-key.pem user-name@xxx.amazonaws.com:/home/user-name/share mount-point

なお、アンマウントはfusermountでなくumountで良い。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Advanced Architecting on AWSを受講しました

公式サイトの説明はあまりに情報が少ないので、
受講を検討している方の一助となればと思い記録を残します。

Advanced Architecting on AWSとは

Architecting on AWSの応用編コースになっています。
様々な要件に基づいて複雑で難易度の高いアーキテクチャを設計できることを目指します。
受講者のターゲットは次の通り。要求されるレベルは高いです。

  • ソリューションアーキテクトアソシエイトを取得した方
  • 業務でAWSを利用していて一通りのサービスを熟知している方

Advanced Architecting on AWS

実施概要

  • 講師: 1名
  • 受講者: 十数名くらい
  • 形式: オンライン
  • 日数: 3日間

講義内容

※ 内容は時期や講師によって変更となる可能性があります

1日目

  • Well-Architectedフレームワーク
  • AWSアカウントの管理
  • ネットワーク(ハンズオン有)
  • デプロイ管理(グルディス有)

2日目

  • データストア・データ移行(ハンズオン有)
  • 大規模アプリケーション向けアーキテクチャ(ハンズオン有)

3日目

  • セキュリティ対策(ハンズオン有)
  • データ暗号化(グルディス有)

Well-Architectedフレームワーク

まずは、お馴染みのWell-Architectedフレームワークから学んでいきます。
自動化やマネージドサービスを駆使してビジネス価値の向上にリソースを割きましょうね。
勘に頼らずにちゃんとキャパシティプランニングしてアーキテクチャ決定しましょうね。等々

Well-Architectedフレームワーク

AWSアカウントの管理

セキュリティや監査の観点から、どのようなアカウント構造を取るべきか学べました。
個人的には、AWS Organizationsを詳しく知らなかったので勉強になりました。

ネットワーク

VPCやオンプレミスとの接続といったネットワーク周りを学びます。
VPCエンドポイントを利用したVPCとVPC外サービス(S3やSQS等)のセキュアな通信方法であったり、
サイト間VPNやDirect Connectを使用したオンプレとの接続サービスやその選択基準を勉強しました。

デプロイ管理

数々のDevOpsツールの内、CloudFormation、CodeDeploy、OpsWorks、Beanstalk、ECSに焦点を当てています。講師の方曰く、AWSのプロビジョニングはCloudFormation、構成管理はAnsibleを利用するのが運用者に易しくシンプルでよいとのことでした。もちろん要件に依りますが。

データストア・データ移行

データストアやキャッシュ、データベースについて一通りのサービスを学びます。
S3のパフォーマンスを向上する方法であったり、ElastiCasheの使い所など勉強になりました。
また、オンプレの大容量データをどうやってAWSに運び出すのか、リードタイム、コストの観点から最適な方法を選ぶ手続きも勉強しました。

大規模アプリケーション向けアーキテクチャ

大量のトラヒックを捌くためのアーキテクチャや、Blue/Greenデプロイメントによる安心なリリース方法について学びます。ハンズオンでは、リードレプリカをElastiCasheで置き換えたときのクエリ実行時間を比較することで、いかにキャッシュが高速にデータを更新できるか体験しました。

セキュリティ対策

DDoS攻撃やUDPリフレクションなどのセキュリティ攻撃をどうやって防ぐのかが主題です。
これには、バックエンドサーバをインターネットに公開しない、なるべく固定的にEIPを持たないという一般的なことから、CloudWatchやGuardDutyを使った異常検知の方法まで幅広く学ぶことができました。

ハンズオンでは、XSSをWAFによって防御する様子を実際に攻撃して体験しました。

データ暗号化

データキーを暗号化するためのカスタマーマスターキーの安全な管理を実現するのがKMSです。
さらにセキュリティ性をHWレベルで高めたCloudHSMであったり、自前で鍵を用意するDIYもありますが、基本はKMSでよさそうでした。

まとめ

個人的には、本講座は辞書的に活用するのがよさそうだと感じました。
全ての講義内容を今すぐ使うわけではないので、必要になったときに、そういえば講座でこういう方法を勉強したなと思い出しながら、実際に手を動かしてみて自分のものにしていきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む