- 投稿日:2020-03-20T23:33:33+09:00
AppSyncでLambdaを呼び出す
AppSyncでLambdaを呼び出す
はじめに
先日「API Gatewayでリクエストして、Lambdaで処理させて、AppSyncで受け取る」という記事を書きました。この記事のあとがきにも書いたのですが、フロントエンドからLambdaを実行させるために何の迷いもなくAPI Gatewayを利用していたのですが、どうやらAppSyncでも出来そうだぞということで。
データソースにDynamoDBを指定しているAppSyncへ、LambdaをデータソースとするIFを追加します。
スキーマへIFの追加
AppSyncのスキーマに、モザイク処理を実行するためのIFを追加します。
AWSコンソール > AppSync > 目的のAPI > スキーマ
MutationへprocessApplyMosaicという関数、そして入出力用のデータ型を定義します。
入出力用のデータ型はAPI Gatewayの時と同じ仕様とし、また、認証タイプはCognitoとします。: input ProcessApplyMosaicInput { guid: String! orgKey: String! pointsList: [String] } type ProcessApplyMosaicResult @aws_cognito_user_pools { statusCode: Int! body: String } type Mutation { processApplyMosaic(input: ProcessApplyMosaicInput!): ProcessApplyMosaicResult @aws_cognito_user_pools createSampleAppsyncTable(input: CreateSampleAppsyncTableInput!): SampleAppsyncTable @aws_iam :スキーマを保存ボタンを押下してください。
リゾルバーの追加
スキーマを編集して保存すると、スキーマの右側にあるResolversというところに追加したprocessApplyMosaicが表示されるようになります。Resolverはまだ未割り当てなので「アタッチ」ボタンを押下して割り当てることになります。
が、一時中断です。その前にやることがあります。Lambdaの作成
スキーマのMutationに追加したprocessApplyMosaicのリゾルバーを割り当てるためのLambdaを作成します。
AWSコンソール > Lambda > 関数の作成 > 一から作成
名前は「apply_mosaic_from_appsync」、ラインタイムは「Python 3.6」として作成します。作成したLambdaのIAMロールに必要な権限を当てておきます。
AWSコンソール > IAM > ロール > Lambdaとセットで作成されたロール(apply_mosaic_from_appsync-role-xxxxxxxx)
S3とAppSyncへのアクセスが必要ですので、以下のような内容でインラインポリシーを追加します。{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:PutObject", "s3:GetObject", "appsync:GraphQL" ], "Resource": [ "arn:aws:s3:::sample-vue-project-bucket-work/*", "arn:aws:appsync:ap-northeast-1:888888888888:apis/xxxxxxxxxxxxxxxxxxxxxxxxxx/*" ], "Effect": "Allow" } ] }作成したLambdaに この記事 で作成したPythonコードをインポートするわけですが、インプットパラメータを受け取るところの実装を少しだけ変更します。
: def lambda_handler(event, context): try: # guid = event["guid"] # orgKey = event["orgKey"] # pointsList = event["pointsList"] # AppSyncから渡される引数はinputタグの中に入れてるので↓のように変更する。 guid = event["input"]["guid"] orgKey = event["input"]["orgKey"] pointsList = event["input"]["pointsList"] :データソースの作成
AWSコンソール > AppSync > 目的のAPI > データソース
データソースの作成ボタンを押下し、先ほど作成したLambdaを選択して作成します。
リゾルバーへLambdaのアタッチ
それでは中断した作業に戻ります。
AppSyncのスキーマの右側にあるResolversというところに追加したprocessApplyMosaicが表示されるようになり、そこに表示されている「アタッチ」ボタンを押下します。
データソース名のコンボボックスから先ほど作成したデータソースを選択して、「リゾルバーを保存」ボタンを押下します。リクエスト/レスポンス マッピングテンプレートは特に編集しません。これでAPI側の準備は整いました。
フロントエンドから呼び出し
それではフロントエンドから呼び出してみましょう。
VueのWebアプリにてAPI Gatewayで呼び出していたところをAppSyncに置き換えることになります。src/graphql/mutations.jsexport const processApplyMosaic = ` mutation processApplyMosaic($input: ProcessApplyMosaicInput!) { processApplyMosaic(input: $input) { statusCode body } } `;src/components/List.vue: <script> import { Auth, API, graphqlOperation, Storage } from 'aws-amplify'; import { listSampleAppsyncTables } from "../graphql/queries"; import { onCreateSampleAppsyncTable } from "../graphql/subscriptions"; import { processApplyMosaic } from "../graphql/mutations"; : async processMosaic() { : /* API Gatewayの時のコード const currSession = await Auth.currentSession(); config.headers["Authorization"] = currSession.getIdToken().getJwtToken(); axios .post(apiUrl, {guid: this.myGuid, orgKey: orgKey, pointsList: pointsList}, config) .then(response => { let result = response.data console.log(result) }).catch(error => console.log(error))*/ let apiResult = await API.graphql(graphqlOperation(processApplyMosaic, {input : {guid: this.myGuid, orgKey: orgKey, pointsList: pointsList}}) ).catch(error => { console.error(error); }); }, :コード的にも、Amplifyで統一できてスッキリしましたね。
あとがき
AppSyncとAPI Gateway、両方使うことで得られるメリットはアーキテクチャ図のアイコンが増えて華やかになることくらいでしょうか。
というのは流石に冗談が過ぎますね。目的を実現するための手段は多岐にわたりますが、より多くの選択肢の中から適切に取捨選択できるようになりたいものです。
- 投稿日:2020-03-20T23:08:23+09:00
【Laravel】CloudFront+S3で署名付きURLを使いプライベートコンテンツを配信する
環境
- PHP 7.4.1
- Composer 1.9.3
- Laravel Framework 6.14.0
- league/flysystem-aws-s3-v3 1.0.24
- aws/aws-sdk-php 3.133.40
- aws/aws-sdk-php-laravel 3.5.0
手順
長いのでだいぶ雑です。
1. S3アップロード実装
まず公式ドキュメントに則り、Flysystemを使ってS3に画像をアップロードするところまで進めます。
AWSアカウントの作成, S3バケットの作成, IAMポリシー/ユーザの作成などは、ググれば良い資料が沢山出てくるのでそちらを参照してください。composer require league/flysystem-aws-s3-v3
config/filesystems.php
には既にS3用の記述が存在するため、編集する必要はありません。
.env
ファイルは自身の環境に合わせて書き換えましょう。config/filesystems.php(編集不要)'s3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), ],/.envAWS_ACCESS_KEY_ID=hoge AWS_SECRET_ACCESS_KEY=fuga AWS_DEFAULT_REGION=ap-northeast-1 AWS_BUCKET=hoga AWS_URL=画像アップロード用のHTMLとコントローラ、ルーティングを作成します。
routes/web.phpRoute::get('/', function () { return view('index'); }); Route::Post('/', 'TestController@create');resources/views/index.blade.php<form method="POST" action="/" enctype="multipart/form-data"> {{ csrf_field() }} <input type="file" name="media" accept="image/*"> <input type="submit"> </form>app/Http/Controllers/TestController.phpuse Illuminate\Http\Request; use Storage; public function create(Request $request) { // S3アップロード $media = $request->file('media'); $path = Storage::disk('s3')->putFile('/', $media); $url = Storage::disk('s3')->url($path); dd($url); }アップロードがうまくいかない場合、IAMポリシーやアクセスキーのチェックを行い、
php artisan cache:clear
やphp artisan config:clear
を叩いてみましょう。この状態では、URLを叩くとエラーになるはずです。画像をブラウザで確認する場合、S3バケットのパブリックアクセスをオンにする必要があります。
S3バケットの「パブリックアクセスをすべてブロック」をオフにして、putFile()の第三引数に'public'を追記
してアップロードすると、見れるようになるはずです。確認が終わったら設定を戻しておきましょう。2. CloudFrontとの連携
ルートユーザでAWSマネジメントコンソールにアクセスし、「マイセキュリティ資格情報」からCloudFrontキーペアを生成します。
キーペアをダウンロードし、秘密鍵をアプリケーションディレクトリ直下に保存します。/pk-hogefuga.pem-----BEGIN RSA PRIVATE KEY----- aaaaaaaaaaaaa -----END RSA PRIVATE KEY-----次に、CloudFrontのページで「Create Distribution」→Webの「Get Started」と進み、以下の情報を入力して設定を完了します。StatusがDeployedに変わるまで待ちましょう。
この操作が完了すると、S3のバケットポリシーが更新され、CloudFront経由でしかアクセスできないようになります。Origin Domain Name: S3のバケットを選択 Restrict Bucket Access: Yes Origin Access Identity: Create a New Identity Grant Read Permissions on Bucket: Yes, Update Bucket Policy Restrict Viewer Access(Use Signed URLs or Signed Cookies): Yes Trusted Signers: Self次に、以下のコマンドでAWS SDKを導入します。
コマンド入力後は、 https://github.com/aws/aws-sdk-php-laravel に記載のある通り、providersとaliasesを更新します。
その後、composer dump-autoload
を叩いてください。composer require aws/aws-sdk-php-laravelここまでできたら、後は署名付きURLを取得するだけです。
コントローラと.envファイルを以下のように書き換えます。app/Http/Controllers/TestController.phpuse Illuminate\Http\Request; use Storage; use AWS; public function create(Request $request) { // S3アップロード $media = $request->file('media'); $path = Storage::disk('s3')->putFile('/', $media); $url = Storage::disk('s3')->url($path); // 署名付きURLを取得 $client = AWS::createClient('cloudfront'); $signedUrlCannedPolicy = $client->getSignedUrl([ 'url' => $url, 'expires' => time() + 30, // 30秒間有効 'private_key' => base_path('pk-hogefuga.pem'), 'key_pair_id' => env('AWS_CLOUDFRONT_KEY_PAIR_ID') ]); dd($signedUrlCannedPolicy); }/.envAWS_URL=https://xxx.cloudfront.net # CloudFrontのページにある「Domain Name」 AWS_CLOUDFRONT_KEY_PAIR_ID=hogefuga # 鍵ファイル名のハイフン以降の文字列実行後、以下のようなURLが取得できたらうまくいっています。
CloudFront経由でしかアクセスできない(S3に直接アクセスが禁止されている)こと、GETパラメータを外すとアクセスできないこと、有効期限を過ぎるとアクセスできないことを確認してみてください。
- 投稿日:2020-03-20T22:17:15+09:00
Elastic Beanstalkの.ebextensionsでApacheのDocument Rootを変更する方法
Elastic BeanstalkでEC2を立ち上げる際、ApacheのDocument Rootは
httpd.confDocumentRoot "/var/www/html/"となっています。
これを変更しようとしたのですが、ちょっとトリッキーなことをしたので、残しておきます。環境
64bit Amazon Linux/2.9.3
Apache/2.4.41やり方
.ebextensionsのフォルダ内に以下のファイルを入れます。
apache.configfiles: /etc/httpd/conf/myhttpd.conf: content: | ##以下にDocment Rootを変更したconfファイルの内容を記載する ##例えば↓↓ DocumentRoot "/var/www/html/public" #### End of AWS Settings #### container_commands: 00-rm-httpd-conf: command: "sudo rm /etc/httpd/conf/httpd.conf" 01-cp-conf-file: command: "sudo cp /etc/httpd/conf/myhttpd.conf /etc/httpd/conf/httpd.conf" 02-httpd-restart: command: "sudo httpd -k restart"このファイルでは
①Document Rootを変更した設定ファイルmyhttpd.conf
をEC2に置く
②元々の設定ファイルhttpd.conf
でApacheを立ち上げた後、httpd.conf
を削除する
③myhttpd.conf
をhttpd.conf
に置き換える
④Apacheを再起動する
という手順を踏んでいます。この手順を踏んでいる理由
元々は最初のApacheの立ち上げの前から
httpd.conf
を上書きしようとしたのですが、そうするとなぜかDocument Rootがデフォルトに書き換わってしまいました。
なので、ちょっとトリッキーな手順を踏みました。
- 投稿日:2020-03-20T21:10:26+09:00
Rails アプリを EC2 にデプロイしよう!(サーバー構築編)
Rails アプリを Amazon Web Service を使ってデプロイするまでの手順をまとめました。
次の順番でデプロイまで持っていきます。1, 準備編
2, サーバー構築編
3, 環境構築編
4, デプロイ編今回は「サーバー構築編」です。
「準備編」を読んでない方は先に読んでください。EC2 インスタンスの作成
EC2とは Elastic Compute Cloud の略で、クラウド上に存在する仮想のサーバーのことです。
サーバーは、サービスを提供する (server) コンピューターのことです。
要するにパソコンを借ります。早速借りましょう。
1, コンソール画面から検索するなりして「EC2」をクリックしてください。
2, 左のメニューバーから「インスタンス」をクリックしてください。
3, 左上辺りにある[インスタンスの作成]をクリックしてください。AMIの選択
最初に「AMIの選択」を行います。
AMIとは Amazon Machine Image の略で、ここでは今作成しようとしているパソコン(EC2)のタイプを選択します。4, 今回は
Ruby
を使用するので、
「Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type」
を選択しましょう。
AMIを間違えるとRubyが動かないので注意しましょう。
OSもここで決まります。今回はAmazon Linuxを使用します。
名称が変わっている場合は、次のような説明文が書かれているものを選択してください。Amazon Linux AMI は、AWS がサポートする EBS-backed イメージです。デフォルトのイメージには、AWS コマンドラインツール、Python、Ruby、Perl、および Java が含まれます。レポジトリには、Docker、PHP、MySQL、PostgreSQL、およびその他のパッケージが含まれます。
インスタンスタイプの選択
次に「インスタンスタイプの選択」を行います。
AWSにはさまざまな種類のCPUやメモリ、ストレージなどを組み合わせたインスタンスが存在しています。
今回は具体的なインスタンスタイプの種類について割愛します。5, 今回は
t2.micro
を使用するので
次のインスタンスタイプを選択してください。
今回は「無料枠」を選択しています。
無料枠が表示されない方もいるかもしれませんが、それについてはご了承ください。インスタンスの詳細の設定
次は「インスタンスの詳細の設定」を行います。
いろいろ項目がありますが、意味は次の通りです。
名称 意味 インスタンス数 作成するインスタンスの数 スポットインスタンスのリクエスト 同じ地域の使用されていないインスタンスを、入札制で使用出来る仕組み。費用削減が期待できる。今回はチェックしない。 ネットワーク 使用するVPCを選択する。準備編で作成したVPCをプルダウンで選択しましょう。 サブネット 使用するサブネットを選択する。準備編で作成したサブネットをプルダウンで選択しましょう。 自動割り当てパブリックIP インターネットを通じてインスタンスにアクセスするためのIPアドレス。有効化します。 配置グループ プレイスメントグループというグループを作成することで、インスタンス間の通信速度を高速化させることができます。今回は使用しません。 キャパシティーの予約 任意の時間やタイミングでキャパシティー(性能)を上げることができます。今回は使用しません。 IAMロール IAMというユーザーの種類別にリソースの使用権限を割り振ったもの。誰がこのインスタンスにアクセス出来て、誰が出来ないかなどを設定できる。今回は設定しない。 シャットダウン動作 EC2をシャットダウンした際に削除するのか停止させるのか選択できる。 停止 - 休止動作 インスタンスの停止中に「休止状態」が選択できるようにする。 終了保護の有効化 インスタンスを誤って削除しないように設定できる。 モニタリング CloudWatchというインスタンス監視サービスを利用するかどうかを選択できる。利用すると追加料金が発生する。 テナンシー ハードウェアを占有するか、それとも他の利用者と共有するかを選択できる。 Elastic Inference 説明を割愛します。 T2/T3 無制限 説明を割愛します。 ストレージの追加
次は「ストレージの追加」を行います。
ストレージシステム(EC2)の管理に役立つ特別なディレクトリと構成ファイルが格納されている場所で、Windowsで言う所の「Cドライブ」に該当します。タグの追加
次は「タグの追加」を行います。
ここでEC2に名前をつけましょう。セキュリティグループの設定
最後に「セキュリティグループの設定」を行います。
準備編で設定したセキュリティグループを選択しましょう。インスタンス作成の確認
これまでの手順を振り返って問題がなければ、
右下にある「起動」をクリックしましょう。クリックすると「既存のキーペアを選択するか、新しいキーペアを作成します。」という画面が出てきます。
新しいキーペアの作成
SSH という通信プロトコルを使って安全な通信を行います。
この通信では、ユーザーはプライベートファイルをAWSから保存して、これを使用してインスタンスに接続します。10, 新しいキーペアを作成して、キーペアをダウンロードしてください。
再度ダウンロードすることはできないので注意してください。
また、安全な場所に保存するようにしてください。これを保存した後、やっとインスタンスを作成することができます。
11, 「インスタンスの作成」をクリックしましょう。
12, 作成ステータスが表示されますが、そのまま「インスタンスの表示」をクリックしましょう。以下のようにインスタンスが作成されていれば OK です。
Elastic IP の設定
今回の最後に Elastic IP を設定していきます。
EC2サーバーはインターネットに接続を行う場合、どのサーバーも例外なくパブリックIPというものを持つ必要があります。そして、先ほど作成したEC2インスタンスにも作成時にパブリックIPが自動で割り振られるのですが、サーバーを再起動させるたびにこのパブリックIPが変わってしまうという欠点を持っています。
そこで Elastic IP を使用します。
これは、先に固定のIPアドレスを他に使用されないように押さえてしまい、それをパブリックIPとしてEC2インスタンスに紐付けることで、インスタンスの起動、停止に関わらず常に同じIPで通信を行うことができます。では早速作成していきましょう。
1, 左のメニューバーから「Elastic IP」をクリックしてください。
2, 右上辺りにある「セキュリティグループの作成」をクリックしてください。
3, 「Amazon の IPv4 アドレスプール」が設定されていると思います。
4, そのまま「割り当て」をクリックしましょう。
ここでは既にName
タグを設定していますが、「タグの管理」をクリックすれば設定できます。次に、このIPを先ほど作成したインスタンスに割り当てましょう。
5, 右上辺りにある「Action」から「Elastic IP アドレスの関連付け」を選択してください。
6, 先ほど作成したインスタンスとそのパブリックIPを選択して「関連付ける」をクリックしてください。
以下の画面のように、インスタンスが関連づけられていれば OK です。
最後に
今回は「サーバー構築編」でした。
次回からやっとコマンドラインを使用することになります(長い!)。それでは次回「環境構築編」お楽しみに。
- 投稿日:2020-03-20T21:03:36+09:00
ELB(ALB)の設定・接続・確認
内容
Application Load Balancerの設定を行う。
以下のような構成を構築する。
前提
・下記構成が既に配置されていること。
・セキュリティグループの通信許可設定がされていること
・EC2にApacheがインストールされていて起動していること# yum install -y httpd # systemctl start httpd.service # systemctl status httpd.service # ps -ef | grep -v grep | grep apache手順
各サーバにHTMLファイルを配置する
/var/www/html配下にそれぞれ以下を記載したindex.htmlを配置します。
・ap-northeast-1aにはap-northeast-1aが記載されたファイルを格納します。
・ap-northeast-1cにはap-northeast-1cが記載されたファイルを格納します。ap-northeast-1a
# vi /var/www/html/index.html <html><h1>ap-northeast-1a</h1></html> # cat index.html <html><h1>ap-northeast-1a</h1></html>ap-northeast-1c
# vi /var/www/html/index.html <html><h1>ap-northeast-1c</h1></html> # cat index.html <html><h1>ap-northeast-1c</h1></html>表示確認
それぞれのインスタンスのIPアドレスをコピーしてブラウザに張り付けて
上記のap-northeast-1a、ap-northeast-1cが表示されることを確認します。
これでELBによる振り分けを行った時にそれぞれ1aと1cに振り分けられていることを確認できます。ALBの作成
ログイン~作成画面まで
[AWSマネジメントコンソール]⇒[サービス]⇒[コンピューティング]⇒[EC2]を選択します。
[EC2ダッシュボード]⇒[ロードバランシング]⇒[ロードバランサー]を選択します。
ロードバランサー一覧画面より[ロードバランサーの作成]を押下します。
ALBの選択
ロードバランサーの設定
ロードバランサーの設定を行います。赤枠の部分の設定となります。
今回は外部用なのでインターネット向けでipv4を選択。
プロトコルはHTTPでポートは80を使用。ここでHTTPSを選択すると次の画面で追加設定がありますが今回はHTTP。
設定 値 スキーム インターネット向け IPアドレスタイム ipv4 リスナー HTTP:80 セキュリティ設定の構成
セキュリティグループの設定
HTTPの通信許可設定がされているセキュリティグループを作成するか、割り当てを行います。
ルーティングの設定
ヘルスチェックの詳細設定は今回すぐにUnHealthyを確認したいので間隔を短くしています。
ターゲットグループ
設定 値 ターゲットの種類 インスタンス プロトコル HTTP ポート 80 ヘルスチェック
設定 値 プロトコル HTTP パス / ターゲットの登録
画面下部にターゲット登録可能な設定が表示されるので選択後[登録済みに追加]を押下します。
※Apacheを起動しておかないと表示されません。作成完了
[ロードバランサーを正常に作成しました]と表示されればELBの作成が完了となります。
接続確認
[作成したELB]⇒[説明タブ]よりARNをコピーしてブラウザに貼り付けます。
何回か行うとap-northeast-1aとap-northeast-1cが表示され、振り分けが行われているのが分かります。ELB+α
リスナーIDがELBのプロトコルと待ち受けポート(下の図赤枠)で、転送先が設定した振り分け先のターゲットグループ(下の図青枠)となります。
振り分け先が正常か否かはターゲットグループのターゲットタブかモニタリングタブで確認できます。
1aのApacheは停止、1cのApacheは起動している状態だと
1aのステータスはunhealthy、1cのステータスはhealthyとなります。
終わり
- 投稿日:2020-03-20T17:41:21+09:00
AWS Backup定時備份RDS
- 0. Intro
- 1. 認識AWS Backup
- 2. 透過Web console來建立AWS Backup
- 3. 透過Cloudformation來建立AWS Backup
- 4. 使用tags來快速filter需要備份的資源
0. Intro
有使用過AWS RDS的使用者應該都會了解在RDS本身已經有提供enable auto backup來確保daily都有一份可還原的備份。
而先前AWS也推出集中性管理的AWS Backup console來提供給使用者集中式的管理所有需要備份的計畫與排程,接下來介紹怎麼使用AWS Backup來幫production 的DB做每個小時的備份。
1. 認識AWS Backup
AWS Backup 是AWS的Centralized Backup console,以往我們在各個AWS資料存儲服務(EC2, EBS/EFS, RDS/DynamoDB等)各自備份的排程任務,都可以在新的Backup console中集中管理。
2. 透過Web console來建立AWS Backup
2.1 新增Backup Plan
首先先從web console到
AWS Console > Service > AWS Backup > Backup Plans > [Create Backup Plan]Backup Plan Name這邊可以填入任意你可以識別的文字
接著Rule name這邊可以輸入 rds-backup-hourly,Schedule的部分因為預設的下拉選單中最短的時間是12小時,所以我們選擇Custom cron expression,填入
cron(0 * * * ? *)
。其他Backup window(8小時)與lifecycle都可以是預設值,加密的Valut預設也可以用AWS Default即可。
新增Rule成功後,我們可以繼續來assign 要備份的resource給已經建立的Backup Rule。
2.2 Assign Backup Resource
AWS目前提供了兩種方式來綁定相關的resource
1. 直接指定Resource ID
2. 透過Tag來filter相關的resource,例如所有環境是production的資源,就可以透過env=prod這樣的方式新增。
儲存後應該就可以看到相關的資源已經列在Backup Plan下方資源清單中,這樣就可以下班了XD
BTW,前面敘述有提到Backup Window預設是8小時,而我們設定的backup是每小時備份,如果剛設定完的下一個小時沒有開始備份是正常的XD
3. 透過Cloudformation來建立AWS Backup
除了透過web console建立,我們也可以透過Cloudformation來建立整個Backup plan&resources。
直接修改相關的Region/Account ID/DB Instance ID就可以快速的deploy這個stack了~
AWSTemplateFormatVersion: "2010-09-09" Description: "Hourly Backup Plan for <resources?>" Parameters: AWSAccountID: Type: String Default: "<AWS Account ID>" Resources: DBBackupPlanWithHourlyBackups: Type: "AWS::Backup::BackupPlan" Properties: BackupPlan: BackupPlanName: "rds-prod-hourly-backup" BackupPlanRule: - RuleName: "RuleForHourlyBackups" TargetBackupVault: "Default" ScheduleExpression: "cron(0 * * * ? *)" StartWindowMinutes: 60 Lifecycle: DeleteAfterDays: 30 TagBasedBackupSelection: Type: "AWS::Backup::BackupSelection" Properties: BackupSelection: SelectionName: "resource-of-rds-prod-hourly-backup" IamRoleArn: !Sub arn:aws:iam::${AWSAccountID}:role/service-role/AWSBackupDefaultServiceRole Resources: - !Sub arn:aws:rds:<rds region>:${AWSAccountID}:db:<RDS DB Instance Identify Name> BackupPlanId: !Ref DBBackupPlanWithHourlyBackups DependsOn: DBBackupPlanWithHourlyBackups4. 使用tags來快速filter需要備份的資源
如果需要透過Tag來大量assign相關的resource,可以將上面的template中的Resources換成下面的表示方式
ListOfTags: - ConditionType: "STRINGEQUALS" ConditionKey: "env" ConditionValue: "prod"
- 投稿日:2020-03-20T17:33:00+09:00
Amplify Consoleで複数バージョンのVueアプリケーションのデプロイとFacebook認証
やりたいこと
VueとAmplifyを使って以下のアーキテクチャを構築する。
- Facebook認証機能を持ったVueアプリケーションの実装
- production/development の2つのデプロイ環境を作る
- Githubへのプッシュをフックし、それぞれの環境へデプロイするCIの構築
Vueアプリを作る
vue create
したあとにCSSフレームワークとしてBulmaを組み込む。
Vuetifyとかvue-bulmaを使わないのはただのポリシー。$ vue create vue-amplify-facebook $ cd vue-amplify-facebook $ npm install --save bulma node-sass sass-loader $ mkdir src/assets/sass $ touch src/assets/sass/main.scsssrc/assets/sass/main.scss
@import "~bulma/bulma";src/main.js
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false require('./assets/sass/main.scss'); new Vue({ render: h => h(App), }).$mount('#app')http://localhost:8080 で表示を確認したらGithubへコミット。
$ git push -u origin master
Amplifyのセットアップ, ホスティング、CI
VueアプリケーションにAmplifyを組み込む。
Amplify CLのバージョンは以下。$ amplify -v 4.16.1
init
では特に変わった操作はしていないかな。ほぼほぼデフォルト。$ amplify init Note: It is recommended to run this command from the root of your app directory ? Enter a name for the project vue-amplify-facebook ? Enter a name for the environment prod ? Choose your default editor: Visual Studio Code ? Choose the type of app that you're building javascript Please tell us about your project ? What javascript framework are you using vue ? Source Directory Path: src ? Distribution Directory Path: dist ? Build Command: npm run-script build ? Start Command: npm run-script serve Using default provider awscloudformation For more information on AWS Profiles, see: https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html ? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use defaultS3へのホスティング設定。
最初の質問でManaged hosting with custom domains,
を選ぶ。
Continuous deployment
これでAmplifyConsoleでのCIがセットアップされる。$ amplify add hosting ? Select the plugin module to execute Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment) ? Choose a type Continuous deployment (Git-based deployments) ? Continuous deployment is configured in the Amplify Console. Please hit enter once you connect your rep ository Amplify hosting urls: ┌──────────────┬──────────────────────────────────────────────┐ │ FrontEnd Env │ Domain │ ├──────────────┼──────────────────────────────────────────────┤ │ master │ https://master.d3bh1ri8gu6eyb.amplifyapp.com │ └──────────────┴──────────────────────────────────────────────┘できたら作成されたファイルをコミットして、Githubへプッシュ。
$ git push origin master
Amplify ConsoleでCIが走ってVueアプリケーションがS3へデプロイされる。
認証画面のブランチを作る
認証機能を組み込む前に、UI部分を実装する。
Vueのナビゲーションメニューを設置して、そこにFacebook認証ボタンを置く感じに。※ 別ブランチで作業する。
$ git checkout -b developmentVue画面を編集。
src/components/Auth.vue
展開しないハンバーガーボタンがあるけどご愛嬌で。。
<template> <nav class="navbar" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <h1 class="title">Vue Amplify</h1> </a> <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" > <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div class="navbar-menu"> <div class="navbar-end"> <div class="navbar-item"> <div class="buttons"> <button class="button is-link" @click="signin"> <strong>SignIn with Facebook</strong> </button> <button class="button is-light" @click="signout"> <strong>SignOut</strong> </button> </div> </div> </div> </div> </nav> </template> <script> export default { name: "Auth", methods: { signin() { console.log("signin"); }, signout() { console.log("signout"); } } }; </script>表示が確認できたらmasterとは別のブランチへpushする。
$ git push origin development
開発バージョン確認用の環境を作る
開発用ブランチの表示確認をするため Amplify のenvを追加する。
$ amplify env add dev Note: It is recommended to run this command from the root of your app directory ? Do you want to use an existing environment? No ? Enter a name for the environment dev Using default provider awscloudformation For more information on AWS Profiles, see: https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html ? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use default Adding backend environment dev to AWS Amplify Console app: d3bh1ri8gu6eybAmplify Consoleを開く。
$ amplify console
コンソールから「リポジトリブランチの追加」。
さきほど Githubへpushした developmentブランチをamplify env add
で作ったdev
と紐付ける。設定が完了するとCIが走ってdevelopmentブランチがデプロイされる。
ここまでの操作で以下のように2つのURLが払い出されている。それぞれのURLにアクセスして表示内容が異なっていることを一応確認しておく。
認証機能を追加する
Amplify CLI
で認証機能を実装する。
ソーシャルプロバイダでの認証を選択し、リダイレクト先のURLに先ほどデプロイしたmaster, devのURLと、ローカルホストを指定する。$ amplify add auth Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? Default configuration with So cial Provider (Federation) Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Email Do you want to configure advanced settings? No, I am done. What domain name prefix you want us to create for you? vueamplify-facebook1e4b7722-1e4b7722 Enter your redirect signin URI: http://localhost:8080/ ? Do you want to add another redirect signin URI Yes Enter your redirect signin URI: https://master.d3bh1ri8gu6eyb.amplifyapp.com/ ? Do you want to add another redirect signin URI Yes Enter your redirect signin URI: https://development.d3bh1ri8gu6eyb.amplifyapp.com/ ? Do you want to add another redirect signin URI No Enter your redirect signout URI: http://localhost:8080/ ? Do you want to add another redirect signout URI Yes Enter your redirect signout URI: https://master.d3bh1ri8gu6eyb.amplifyapp.com/ ? Do you want to add another redirect signout URI Yes Enter your redirect signout URI: https://development.d3bh1ri8gu6eyb.amplifyapp.com/ ? Do you want to add another redirect signout URI No Select the social providers you want to configure for your user pool: Facebook You've opted to allow users to authenticate via Facebook. If you haven't already, you'll need to go to https://developers.facebook.com and create an App ID. Enter your Facebook App ID for your OAuth flow: 9xxxxxxxxxxxxxx Enter your Facebook App Secret for your OAuth flow: 22exxxxxxxxxxxxxxxxxxxxxxx Successfully added resource vueamplifyfacebook1e4b7722 locally Some next steps: "amplify push" will build all your local backend resources and provision it in the cloud "amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud$ amplify status Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------------- | --------- | ----------------- | | Auth | vueamplifyfacebook1e4b7722 | Create | awscloudformation | | Hosting | amplifyhosting | No Change | | Amplify hosting urls: ┌──────────────┬───────────────────────────────────────────────────┐ │ FrontEnd Env │ Domain │ ├──────────────┼───────────────────────────────────────────────────┤ │ development │ https://development.d3bh1ri8gu6eyb.amplifyapp.com │ ├──────────────┼───────────────────────────────────────────────────┤ │ master │ https://master.d3bh1ri8gu6eyb.amplifyapp.com │ └──────────────┴───────────────────────────────────────────────────┘最後に作成したリソースを反映させる。
$ amplify push
Facebook Developers の設定
Facebook側にアプリドメインと有効なOAuthリダイレクトURIを設定する。
設定方法は以下のドキュメントを参考に。Amplify Javascript - Facebook Instructions
Vue app に Amplifyを組み込む
npm install --save aws-amplify複数のコールバックURLを指定している場合、Amplifyの仕様で複数のコールバックURLの設定が読み込めないので、aws-exports.jsのロード後にwindow.hostnameから適切なリダイレクトURLを判定するコードをいれる。
これに関しては別途まとめているのでそちらを参考に。
Amplify auth は複数のコールバックURLに対応していない
src/main.js
import Vue from "vue"; import App from "./App.vue"; import Amplify from "aws-amplify"; import awsconfig from "./libs/aws-config"; // debug: リダイレクトURLが正しく判定されているか確認のため console.log(awsconfig.oauth); Amplify.configure(awsconfig); Vue.config.productionTip = false; require("./assets/sass/main.scss"); new Vue({ render: h => h(App) }).$mount("#app");デバッグ用にAmplifyのLoggerを使ってHubで受け取るイベントの内容をコンソールに出力している。
Amplify.Logger.LOG_LEVEL = "INFO"; const logger = new Logger("AmplifyFacebook"); logger.info(event, data);Facebook認証は以下のような感じ。
これを実行すると各認証プロバイダ用の認証画面へリダイレクトする。Auth.federatedSignIn({ provider: "Facebook" });
federatedSignIn
で認証した後、認証情報を受け取るのにHub
を使う。
HubはAmplifyの提供するイベントリスナで、Amplifyで発生する各種イベントの通知を受け取ることができる。
認証が成功するとCLIで指定したリダイレクトURLをリダイレクトされ、Hubを使って認証状態の変更を受け取ることができる。Hub.listen("auth", ({ payload: { event, data } }) => { logger.info(event, data); switch (event) { case "signIn": await this.saveCurrentAuthenticatedUser(); break; case "signOut": this.clearCurrentAuthenticatedUser(); break; } });最終的なコード。
Amplify Javascript - OAuth and Hosted UI に記載されているReactでの実装を参考にしている。<template> <nav class="navbar is-white" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <h1 class="title">Vue Amplify</h1> </a> <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" > <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div class="navbar-menu"> <div class="navbar-end"> <div class="navbar-item"> <div v-if="isSignedIn" class="buttons"> <a class="navbar-item">{{ user.attributes.email }}</a> <button class="button is-light" @click="signout"> <strong>SignOut</strong> </button> </div> <div v-else class="buttons"> <button v-if="!isSignedIn" class="button is-link" @click="signin"> <strong>SignIn with Facebook</strong> </button> </div> </div> </div> </div> </nav> </template> <script> import Amplify, { Auth, Hub, Logger } from "aws-amplify"; Amplify.Logger.LOG_LEVEL = "INFO"; const logger = new Logger("AmplifyFacebook"); export default { name: "Auth", data() { return { user: null }; }, computed: { isSignedIn() { return this.user !== null; } }, async created() { Hub.listen("auth", this.authEventListener); await this.saveCurrentAuthenticatedUser(); }, methods: { signin() { Auth.federatedSignIn({ provider: "Facebook" }); }, signout() { Auth.signOut() .then(() => { this.user = null; }) .catch(err => logger.warn(err)); }, async saveCurrentAuthenticatedUser() { try { const user = await Auth.currentAuthenticatedUser(); this.user = user; } catch (error) { logger.warn(error); return null; } }, clearCurrentAuthenticatedUser() { this.user = null; }, async authEventListener({ payload: { event, data } }) { logger.info(event, data); switch (event) { case "signIn": await this.saveCurrentAuthenticatedUser(); break; case "signOut": this.clearCurrentAuthenticatedUser(); break; } } } }; </script>1つよくわかっていないことがあって、
Hubで受け取る認証情報と、currentAuthenticatedUser
が返す認証情報が微妙に異なるのだよな。
なので↑のコードではHubで認証完了イベントを受け取ってからcurrentAuthenticatedUser
を実行して改めて認証ユーザーの情報を取得している。localhostで動作確認をしてから
development
ブランチへpush。
すると再びCIが走ってdev環境へ認証機能を実装したバージョンがデプロイされる。デモ
最終的にこんな感じになる。
- 投稿日:2020-03-20T16:32:16+09:00
PythonモジュールをLambda Layerにアップロードする時のフォルダ構成について
はじめに
Lambda Layerを使おうとした際にPythonモジュールのフォルダ構成でハマったので、備忘として記事にします。Lambda LayerについてはAWSの公式ドキュメントをご確認ください。
フォルダ構成
プログラミング言語ごとのフォルダ構成については公式ドキュメントでも言及されています。
Pythonの場合、python/
配下にLambda Layerで使用するモジュールを配置する必要があります。
例えば以下のようなイメージです。python ├─test1.py └─common └─test2.pyLayerにアップロードするには、上記
python
フォルダをzipファイルにした上でアップロードします。
上記構成を無視してzipファイルを作成してアップロードした場合、当然ですが、Lambdaで使用する際にエラーになります。
最初はなぜエラーになっているかもわからずハマってました。。。ちゃんとドキュメントは確認しないといけないなと反省しました。
- 投稿日:2020-03-20T14:57:51+09:00
Excon::Error::Socket: getaddrinfo: Name or service not known (SocketError)というエラー文の対応
環境
$ ruby -v
ruby 2.6.5
$ rails -v
Rails 5.2.4Amazon Linux 2
状況
本番環境としてデプロイした後に、画像をCarriorwave,fogを通じてS3にアップロードしようとすると、エラーが発生。
エラー文は以下の2種類。Excon::Error::Socket: getaddrinfo: Name or service not known (SocketError)SocketError: getaddrinfo: Name or service not known本件の原因
config/initializer/carrior_wave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_provider = 'fog/aws' config.fog_credentials = { provider: 'AWS', region: 'ap-northeast-1a', # 問題箇所 aws_access_key_id: 'アクセスキー', aws_secret_access_key: 'シークレットキー' } config.fog_directory = 'バケット名' config.cache_storage = :fog end end
'ap-northeast-1a'
なんてリージョンはなく、ap-northeast-1
の間違いであった。解決した対応
問題箇所の
ap-northeast-1a
をap-northeast-1
にしてpumaを再起動した。こんなしょうもないミスで2時間潰しました笑
- 投稿日:2020-03-20T13:39:35+09:00
AWS CDKで快適なクラウド開発
はじめに
このスライドはどこかでLT発表するためにつくりました。今回はAWS CDKを使うメリットについて改めてお話します。
自己紹介
AWS CDKとはなにか?
AWS CDKとは、プログラミング言語を使ってAWSのクラウド環境をプロビジョニングするためのオープンソースのフレームワークである。
AWS CDKではソースコードからCloudFormationを作成してリソースのクラウドへのデプロイを行う。
プロビジョニングとは?
AWSのインフラ環境を構築すること。通常のインフラ構築はマネジメントコンソールを使ってGUI上で行うが、CloudFormationとAWS CDKを用いる場合はテンプレートファイル(yaml, json, プロビジョニング言語)上にリソースを定義して行う。
マネジメントコンソールを使う問題点
例えば一度構築したAWSのインフラ環境の再現手順を記録したい場合、以下の2つの手段が思いつく
- コンソールで行った操作手順を記録する
- AWS CLIで同様の環境構築をするためのシェルスクリプトを書く
直感的に
1.
も2.
の方法もやりたくはない。。。
CloudFormationを書くという方法
記述例
json
もしくはyml
の形式で定義ファイルを記述する。以下はDynamoDB
の例。dynamodb.template"myDynamoDBTable" : { "Type" : "AWS::DynamoDB::Table", "Properties" : { "AttributeDefinitions": [ { "AttributeName" : {"Ref" : "HashKeyElementName"}, "AttributeType" : {"Ref" : "HashKeyElementType"} } ], "KeySchema": [ { "AttributeName": {"Ref" : "HashKeyElementName"}, "KeyType": "HASH" } ], "ProvisionedThroughput" : { "ReadCapacityUnits" : {"Ref" : "ReadCapacityUnits"}, "WriteCapacityUnits" : {"Ref" : "WriteCapacityUnits"} } } }定義したリソースをデプロイすることで、AWSのクラウド上に実際にリソースを構築することができる。
CloudFormationの問題点
- テンプレートファイルの記法を覚える必要がある
- それなりに独特のルールがあるので一種の言語に近い
- 構文エラーチェックがやりにくい
- 一応構文チェックしてくれるツールはある
- 冗長な構文が増える
- 共通化したいなら自分でシェルスクリプト書くしかない
AWS CDKを使うという方法
プログラミング言語
以下の言語が選択できる
記述例
TypeScriptで
lambda
+API Gateway
+DynamoDB
の環境を記述した例import * as cdk from '@aws-cdk/core' import * as lambda from '@aws-cdk/aws-lambda' import * as apigateway from '@aws-cdk/aws-apigateway' import * as dynamodb from '@aws-cdk/aws-dynamodb' export class CdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props) const table = new dynamodb.Table(this, 'Table', { partitionKey: { name: 'key', type: dynamodb.AttributeType.STRING } }) const handler = new lambda.Function(this, 'Handler', { runtime: lambda.Runtime.NODEJS_10_X, code: lambda.Code.asset('lambda'), handler: 'index.handler', environment: { TABLE_NAME: table.tableName } }) table.grantReadWriteData(handler) new apigawteway.LambdaRestApi(this, 'Endpoint', { handler }) } }AWS CDKだとシンプルにわかりやすくテンプレートが作成できる。
AWS CDKのいいところ
- 使い慣れた構文で書ける
- 共通化ができる
- 構文チェックがやりやすい
AWS CDKの問題点
- CloudFormationでできないことは同様にできない
- 出て間もないツールなので仕様のアップデートが頻繁に行われる
- 文献が少ない
詳しい情報
- 公式
- クラスメソッドの記事
さいごに宣伝
CDKのためにつくったnpmパッケージ
- cdk-lambda-api
Lmbda
+API Gateway
のリソースをシンプルに構築できる- data-pipeline-d2s-cdk
DynamoDB
からS3
へのバックアップ行うData Pipeline
のリソース構築をシンプルにできる
AWS CDK関係で書いた記事
- CDKでSlack botを作ろう
- AWS CDK+React+TypeScriptでLIFF開発
- 自分のためのAlexaテンプレートをAWS CDKとGitHub Actionsを使って公開した
- CDKで「買い物リスト」LINE botをつくる
みんなも始めようAWS CDK!
- 投稿日:2020-03-20T13:37:25+09:00
Route53のバックアップを取得する
はじめに
Route53のゾーン情報をバックアップする方法を説明します。
バックアップはBINDのゾーンファイル形式でテキスト出力されます。
Route53はゾーンファイルのインポートが可能なので、Route53を別アカウントに引っ越すことになった場合にも利用できそうです。手段
cli53を利用します。
https://github.com/barnybug/cli53検証環境
今回の記事を書くにあたり、以下の環境で確認を行いました。
- バックアップスクリプト実行環境
- Linux(CentOS8)
- aws cli 2.0.4
- cli53 0.8.17
- 対象のDNS
- AWS(Route53)
- パブリップホストゾーン
- プライベートホストゾーン
事前準備
AWS側の準備
IAMユーザの作成
Route53の情報を出力できるユーザを作成します。
今回は「AmazonRoute53ReadOnlyAccess」のポリシーをアタッチしました。Linux(バックアップスクリプト実行)側の準備
AWS CLIのインストール
手順は省略します。
AWSの操作に問題がないかを確認するだけなので AWS CLI自体は必須ではありません。AWS CLIの認証情報を保存
# 「Access Key ID」と「Secret Access Key」を登録します aws configure # Route53の情報が取得できるかを確認します # (例)ホストしているゾーンの取得 aws route53 list-hosted-zones --query "HostedZones[*].Name" --output textcli53のダウンロード
https://github.com/barnybug/cli53/releases/latest から最新のバイナリをダウンロードします。
wget https://github.com/barnybug/cli53/releases/download/0.8.17/cli53-linux-amd64 chmod 555 cli53-linux-amd64 mv cli53-linux-amd64 /usr/local/bin/cli53コマンドのテスト
以下のコマンドを実行して出力結果を確認します。
cli53 export <ホストゾーン ID> または、 cli53 export <ドメイン名> (例) cli53 export example.comバックアップスクリプトの作成
#!/bin/bash # ホストされているドメインのリストを取得して変数に代入 domain_list=$(cli53 list | sed -e '1d' | awk '{print $2}') # ドメイン毎に別ファイルでエクスポート for i in ${domain_list} do cli53 export $i > /tmp/$i`date '+%Y%m%d'`.txt done※date でファイルに日付けを付与しています
※ファイルの保存場所は /tmp です
※複数のAWSアカウントを管理している場合はプロファイルの指定が可能です(例) cli53 export example.com --profile defaultおわりに
AWS CLI(aws route53 list-resource-record-sets)で取得できるjsonやtable、yamlの形式では情報がわかりにくかったので、cli53を使用しました。
参考
Route 53 で設定した DNS レコードをエクスポートする
https://qiita.com/tmtysk/items/6ca808dd9ed13abc1992